From 38ab48b1882f36ed7eb7e50c4fb46ce5d376fbc3 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Wed, 26 Feb 2025 20:01:45 +0100 Subject: Fix some deducing-this & functional stuff, add invocable concept --- asl/base/defer.hpp | 6 ++---- asl/base/functional.hpp | 19 ++++++++++++++++--- asl/base/functional_tests.cpp | 24 +++++++++++++++++++----- 3 files changed, 37 insertions(+), 12 deletions(-) (limited to 'asl/base') diff --git a/asl/base/defer.hpp b/asl/base/defer.hpp index b6d52af..e881d8a 100644 --- a/asl/base/defer.hpp +++ b/asl/base/defer.hpp @@ -6,8 +6,7 @@ namespace asl { -// @Todo Add invokable check -template +template class DeferCallback { Callback m_callback; @@ -36,8 +35,7 @@ public: struct DeferFactory { - // @Todo Add invokable check - template + template DeferCallback operator<<(Callback&& callback) const { return DeferCallback(ASL_FWD(callback)); diff --git a/asl/base/functional.hpp b/asl/base/functional.hpp index d820bce..b4b5312 100644 --- a/asl/base/functional.hpp +++ b/asl/base/functional.hpp @@ -7,6 +7,7 @@ namespace asl { template 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 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 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 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 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 struct _result_of_helper; +template +struct _invoke_result_helper; template -struct _result_of_helper +struct _invoke_result_helper { using type = decltype(invoke(declval(), declval()...)); }; -template using result_of_t = _result_of_helper::type; +template +using invoke_result_t = _invoke_result_helper::type; + +template +concept invocable = requires (F&& f, Args&&... args) +{ + invoke(ASL_FWD(f), ASL_FWD(args)...); +}; } // namespace asl diff --git a/asl/base/functional_tests.cpp b/asl/base/functional_tests.cpp index 92c5c7b..991c3c1 100644 --- a/asl/base/functional_tests.cpp +++ b/asl/base/functional_tests.cpp @@ -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, int64_t>); -static_assert(asl::same_as, int>); -static_assert(asl::same_as(some_func1))(float)>, float>); -static_assert(asl::same_as, void>); -static_assert(asl::same_as, int>); +static_assert(asl::same_as, int>); +static_assert(asl::same_as, int>); +static_assert(asl::same_as, int64_t>); +static_assert(asl::same_as, int>); +static_assert(asl::same_as(some_func1)), float>, float>); +static_assert(asl::same_as, void>); +static_assert(asl::same_as, const int&>); + +static_assert(asl::invocable); +static_assert(!asl::invocable); +static_assert(asl::invocable); +static_assert(!asl::invocable); +static_assert(asl::invocable); +static_assert(asl::invocable); +static_assert(!asl::invocable); +static_assert(asl::invocable(some_func1)), float>); +static_assert(asl::invocable); +static_assert(!asl::invocable); +static_assert(asl::invocable); ASL_TEST(invoke_member_function) { -- cgit