Fix some deducing-this & functional stuff, add invocable concept
This commit is contained in:
@ -6,8 +6,7 @@
|
||||
namespace asl
|
||||
{
|
||||
|
||||
// @Todo Add invokable check
|
||||
template<typename Callback>
|
||||
template<invocable Callback>
|
||||
class DeferCallback
|
||||
{
|
||||
Callback m_callback;
|
||||
@ -36,8 +35,7 @@ public:
|
||||
|
||||
struct DeferFactory
|
||||
{
|
||||
// @Todo Add invokable check
|
||||
template<typename Callback>
|
||||
template<invocable Callback>
|
||||
DeferCallback<Callback> operator<<(Callback&& callback) const
|
||||
{
|
||||
return DeferCallback<Callback>(ASL_FWD(callback));
|
||||
|
@ -7,6 +7,7 @@ namespace asl {
|
||||
|
||||
template<typename... Args, typename C>
|
||||
constexpr auto invoke(is_func auto C::* f, auto&& self, Args&&... args)
|
||||
-> decltype((self.*f)(ASL_FWD(args)...))
|
||||
requires requires {
|
||||
(self.*f)(ASL_FWD(args)...);
|
||||
}
|
||||
@ -16,6 +17,7 @@ constexpr auto invoke(is_func auto C::* f, auto&& self, Args&&... args)
|
||||
|
||||
template<typename... Args, typename C>
|
||||
constexpr auto invoke(is_func auto C::* f, auto* self, Args&&... args)
|
||||
-> decltype((self->*f)(ASL_FWD(args)...))
|
||||
requires requires {
|
||||
(self->*f)(ASL_FWD(args)...);
|
||||
}
|
||||
@ -25,6 +27,7 @@ constexpr auto invoke(is_func auto C::* f, auto* self, Args&&... args)
|
||||
|
||||
template<typename... Args, typename C>
|
||||
constexpr auto invoke(is_object auto C::* m, auto&& self, Args&&...)
|
||||
-> decltype(self.*m)
|
||||
requires (
|
||||
sizeof...(Args) == 0 &&
|
||||
requires { self.*m; }
|
||||
@ -35,6 +38,7 @@ constexpr auto invoke(is_object auto C::* m, auto&& self, Args&&...)
|
||||
|
||||
template<typename... Args, typename C>
|
||||
constexpr auto invoke(is_object auto C::* m, auto* self, Args&&...)
|
||||
-> decltype(self->*m)
|
||||
requires (
|
||||
sizeof...(Args) == 0 &&
|
||||
requires { self->*m; }
|
||||
@ -45,6 +49,7 @@ constexpr auto invoke(is_object auto C::* m, auto* self, Args&&...)
|
||||
|
||||
template<typename... Args>
|
||||
constexpr auto invoke(auto&& f, Args&&... args)
|
||||
-> decltype(f(ASL_FWD(args)...))
|
||||
requires requires {
|
||||
f(ASL_FWD(args)...);
|
||||
}
|
||||
@ -52,14 +57,22 @@ constexpr auto invoke(auto&& f, Args&&... args)
|
||||
return ASL_FWD(f)(ASL_FWD(args)...);
|
||||
}
|
||||
|
||||
template<typename F> struct _result_of_helper;
|
||||
template<typename Void, typename F, typename... Args>
|
||||
struct _invoke_result_helper;
|
||||
|
||||
template<typename R, typename... Args>
|
||||
struct _result_of_helper<R(Args...)>
|
||||
struct _invoke_result_helper<void, R, Args...>
|
||||
{
|
||||
using type = decltype(invoke(declval<R>(), declval<Args>()...));
|
||||
};
|
||||
|
||||
template<typename F> using result_of_t = _result_of_helper<F>::type;
|
||||
template<typename F, typename... Args>
|
||||
using invoke_result_t = _invoke_result_helper<void, F, Args...>::type;
|
||||
|
||||
template<typename F, typename... Args>
|
||||
concept invocable = requires (F&& f, Args&&... args)
|
||||
{
|
||||
invoke(ASL_FWD(f), ASL_FWD(args)...);
|
||||
};
|
||||
|
||||
} // namespace asl
|
||||
|
@ -24,11 +24,25 @@ static int some_func1(int x) { return x + 1; }
|
||||
[[maybe_unused]] static float some_func1(float x) { return x + 1; }
|
||||
static int some_func2(int x, int b) { return x + b; }
|
||||
|
||||
static_assert(asl::same_as<asl::result_of_t<Functor()>, int64_t>);
|
||||
static_assert(asl::same_as<asl::result_of_t<Functor(int)>, int>);
|
||||
static_assert(asl::same_as<asl::result_of_t<decltype(static_cast<float(*)(float)>(some_func1))(float)>, float>);
|
||||
static_assert(asl::same_as<asl::result_of_t<decltype(&HasFunction::do_something)(HasFunction, int, float)>, void>);
|
||||
static_assert(asl::same_as<asl::result_of_t<decltype(&HasMember::member)(HasMember)>, int>);
|
||||
static_assert(asl::same_as<asl::invoke_result_t<int()>, int>);
|
||||
static_assert(asl::same_as<asl::invoke_result_t<int(float), float>, int>);
|
||||
static_assert(asl::same_as<asl::invoke_result_t<Functor>, int64_t>);
|
||||
static_assert(asl::same_as<asl::invoke_result_t<Functor, int>, int>);
|
||||
static_assert(asl::same_as<asl::invoke_result_t<decltype(static_cast<float(*)(float)>(some_func1)), float>, float>);
|
||||
static_assert(asl::same_as<asl::invoke_result_t<decltype(&HasFunction::do_something), HasFunction, int, float>, void>);
|
||||
static_assert(asl::same_as<asl::invoke_result_t<decltype(&HasMember::member), const HasMember>, const int&>);
|
||||
|
||||
static_assert(asl::invocable<int()>);
|
||||
static_assert(!asl::invocable<int(), int>);
|
||||
static_assert(asl::invocable<int(float), float>);
|
||||
static_assert(!asl::invocable<int(float), int*>);
|
||||
static_assert(asl::invocable<Functor>);
|
||||
static_assert(asl::invocable<Functor, int>);
|
||||
static_assert(!asl::invocable<Functor, void*>);
|
||||
static_assert(asl::invocable<decltype(static_cast<float(*)(float)>(some_func1)), float>);
|
||||
static_assert(asl::invocable<decltype(&HasFunction::do_something), HasFunction, int, float>);
|
||||
static_assert(!asl::invocable<decltype(&HasFunction::do_something), HasFunction, int, int*>);
|
||||
static_assert(asl::invocable<decltype(&HasMember::member), const HasMember>);
|
||||
|
||||
ASL_TEST(invoke_member_function)
|
||||
{
|
||||
|
@ -395,32 +395,27 @@ public:
|
||||
return value();
|
||||
}
|
||||
|
||||
template<
|
||||
typename F,
|
||||
typename Self,
|
||||
typename Result = result_of_t<F(copy_cref_t<Self&&, T>)>
|
||||
>
|
||||
template<typename F, typename Self>
|
||||
constexpr auto and_then(this Self&& self, F&& f)
|
||||
requires is_option<Result>
|
||||
{
|
||||
using Result = invoke_result_t<F, copy_cref_t<Self&&, T>>;
|
||||
static_assert(is_option<Result>);
|
||||
|
||||
if (self.has_value())
|
||||
{
|
||||
return invoke(ASL_FWD(f), ASL_FWD_LIKE(decltype(self), ASL_FWD(self).value()));
|
||||
return invoke(ASL_FWD(f), ASL_FWD(self).value());
|
||||
}
|
||||
return Result{ asl::nullopt };
|
||||
}
|
||||
|
||||
template<
|
||||
typename F,
|
||||
typename Self,
|
||||
typename Result = result_of_t<F(copy_cref_t<Self&&, T>)>
|
||||
>
|
||||
template<typename F, typename Self>
|
||||
constexpr auto transform(this Self&& self, F&& f)
|
||||
{
|
||||
using Result = invoke_result_t<F, copy_cref_t<Self&&, T>>;
|
||||
if (self.has_value())
|
||||
{
|
||||
return option<un_cvref_t<Result>>{
|
||||
invoke(ASL_FWD(f), ASL_FWD_LIKE(decltype(self), ASL_FWD(self).value()))
|
||||
invoke(ASL_FWD(f), ASL_FWD(self).value())
|
||||
};
|
||||
}
|
||||
return option<un_cvref_t<Result>>{ asl::nullopt };
|
||||
@ -428,14 +423,14 @@ public:
|
||||
|
||||
template<typename F>
|
||||
constexpr option or_else(F&& f) const&
|
||||
requires same_as<un_cvref_t<result_of_t<F()>>, option>
|
||||
requires same_as<un_cvref_t<invoke_result_t<F>>, option>
|
||||
{
|
||||
return has_value() ? *this : invoke(ASL_FWD(f));
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
constexpr option or_else(F&& f) &&
|
||||
requires same_as<un_cvref_t<result_of_t<F()>>, option>
|
||||
requires same_as<un_cvref_t<invoke_result_t<F>>, option>
|
||||
{
|
||||
return has_value() ? ASL_MOVE(*this) : invoke(ASL_FWD(f));
|
||||
}
|
||||
|
Reference in New Issue
Block a user