From f19d93a69a0ec5c7a89dcb4c064c984aac90ba71 Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Wed, 26 Mar 2025 18:54:54 +0100 Subject: Improve implementation of invoke --- asl/base/functional.hpp | 61 +++++++++++++++++++------------------------ asl/base/functional_tests.cpp | 26 +++++++++++++++--- asl/base/meta.hpp | 15 ++++++----- asl/base/meta_tests.cpp | 14 ++++++++++ todo.txt | 1 + 5 files changed, 74 insertions(+), 43 deletions(-) diff --git a/asl/base/functional.hpp b/asl/base/functional.hpp index 509a2b2..5649bf8 100644 --- a/asl/base/functional.hpp +++ b/asl/base/functional.hpp @@ -9,56 +9,49 @@ namespace asl { -template -constexpr auto invoke(is_func auto C::* f, auto&& self, Args&&... args) - -> decltype((self.*f)(std::forward(args)...)) - requires requires { - (self.*f)(std::forward(args)...); +template +constexpr auto invoke(F&& f, Args&&... args) + -> decltype(std::forward(f)(std::forward(args)...)) + requires (!is_member_ptr>) && requires { + f(std::forward(args)...); } { - return (std::forward(self).*f)(std::forward(args)...); + return std::forward(f)(std::forward(args)...); } -template -constexpr auto invoke(is_func auto C::* f, auto* self, Args&&... args) - -> decltype((self->*f)(std::forward(args)...)) - requires requires { - (self->*f)(std::forward(args)...); - } +template +constexpr auto&& invoke(auto C::* f, same_or_derived_from auto&& arg) { - return (self->*f)(std::forward(args)...); + return std::forward(arg).*f; } -template -constexpr auto invoke(is_object auto C::* m, auto&& self, Args&&...) - -> decltype(self.*m) +template +constexpr auto&& invoke(auto C::* f, auto&& arg) requires ( - sizeof...(Args) == 0 && - requires { self.*m; } + !same_or_derived_from + && requires { (*arg).*f; } ) { - return std::forward(self).*m; + return (*std::forward(arg)).*f; } -template -constexpr auto invoke(is_object auto C::* m, auto* self, Args&&...) - -> decltype(self->*m) - requires ( - sizeof...(Args) == 0 && - requires { self->*m; } - ) +template +constexpr auto invoke(is_func auto C::* f, same_or_derived_from auto&& self, Args&&... args) + -> decltype((std::forward(self).*f)(std::forward(args)...)) + requires requires { (self.*f)(std::forward(args)...); } { - return self->*m; + return (std::forward(self).*f)(std::forward(args)...); } -template -constexpr auto invoke(auto&& f, Args&&... args) - -> decltype(f(std::forward(args)...)) - requires requires { - f(std::forward(args)...); - } +template +constexpr auto invoke(is_func auto C::* f, auto&& self, Args&&... args) + -> decltype(((*std::forward(self)).*f)(std::forward(args)...)) + requires ( + !same_or_derived_from + && requires { ((*self).*f)(std::forward(args)...); } + ) { - return std::forward(f)(std::forward(args)...); + return ((*std::forward(self)).*f)(std::forward(args)...); } template diff --git a/asl/base/functional_tests.cpp b/asl/base/functional_tests.cpp index 5e7b052..6332784 100644 --- a/asl/base/functional_tests.cpp +++ b/asl/base/functional_tests.cpp @@ -7,9 +7,12 @@ struct HasFunction { - void do_something(int, float) {} + void do_something(int, float) const {} + int& do_something2(int, float) &; }; +struct HasFunction2 : public HasFunction {}; + struct HasMember { int member{}; @@ -17,6 +20,8 @@ struct HasMember void (*member_fn)(){}; }; +struct HasMember2 : public HasMember {}; + struct Functor { int64_t operator()() { return 35; } @@ -34,7 +39,13 @@ 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::same_as, void>); +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, const int&>); +static_assert(asl::same_as, const int&>); static_assert(asl::invocable); static_assert(!asl::invocable); @@ -45,8 +56,17 @@ 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); 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); +static_assert(asl::invocable); +static_assert(asl::invocable); ASL_TEST(invoke_member_function) { diff --git a/asl/base/meta.hpp b/asl/base/meta.hpp index b17f05c..1d57367 100644 --- a/asl/base/meta.hpp +++ b/asl/base/meta.hpp @@ -92,12 +92,6 @@ template concept trivially_destructible = __is_trivially_destructibl template concept copyable = copy_constructible && copy_assignable; template concept moveable = move_constructible && move_assignable; -template -concept convertible_to = __is_convertible(From, To); - -template -concept derived_from = __is_class(Derived) && __is_class(Base) && convertible_to; - using nullptr_t = decltype(nullptr); template struct _un_const_helper { using type = T; }; @@ -154,6 +148,15 @@ template struct _is_ptr_helper : true_type {}; template concept is_ptr = _is_ptr_helper>::value; +template +concept convertible_to = __is_convertible(From, To); + +template +concept derived_from = __is_class(Derived) && __is_class(Base) && convertible_to; + +template +concept same_or_derived_from = same_as, Base> || derived_from, Base>; + template struct _tame_helper { using type = T; }; #define TAME_HELPER_IMPL(TRAILING) \ diff --git a/asl/base/meta_tests.cpp b/asl/base/meta_tests.cpp index 65f367a..c221dcf 100644 --- a/asl/base/meta_tests.cpp +++ b/asl/base/meta_tests.cpp @@ -168,6 +168,8 @@ static_assert(!asl::is_member_func_ptr); static_assert(!asl::is_member_func_ptr); static_assert(!asl::is_member_func_ptr); static_assert(asl::is_member_func_ptr); +static_assert(asl::is_member_func_ptr); +static_assert(asl::is_member_func_ptr); static_assert(asl::same_as>); static_assert(asl::same_as>); @@ -250,6 +252,8 @@ static_assert(!asl::convertible_to); static_assert(!asl::convertible_to); static_assert(asl::derived_from); +static_assert(asl::derived_from); +static_assert(asl::derived_from); static_assert(!asl::derived_from); static_assert(!asl::derived_from); static_assert(!asl::derived_from); @@ -257,6 +261,16 @@ static_assert(!asl::derived_from); static_assert(!asl::derived_from); static_assert(!asl::derived_from); +static_assert(asl::same_or_derived_from); +static_assert(asl::same_or_derived_from); +static_assert(asl::same_or_derived_from); +static_assert(!asl::same_or_derived_from); +static_assert(!asl::same_or_derived_from); +static_assert(!asl::same_or_derived_from); +static_assert(!asl::same_or_derived_from); +static_assert(!asl::same_or_derived_from); +static_assert(asl::same_or_derived_from); + static_assert(!asl::is_const); static_assert(asl::is_const); static_assert(!asl::is_const); diff --git a/todo.txt b/todo.txt index 5ea5980..1823626 100644 --- a/todo.txt +++ b/todo.txt @@ -1 +1,2 @@ Separate memory and allocator +Add invoke_t & co -- cgit