From 88b9c801cea358c86c6136c310edd688b6a5fe22 Mon Sep 17 00:00:00 2001 From: Agustin K-ballo Berge Date: Mon, 27 Jul 2020 11:14:26 -0300 Subject: [PATCH 1/2] Add invoke_r to benchmarks --- benchmark/CMakeLists.txt | 3 ++- benchmark/callable.cpp.in | 4 +++- benchmark/function.cpp.in | 4 +++- benchmark/member_function.cpp.in | 4 +++- benchmark/member_object.cpp.in | 4 +++- 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt index 68f6990..97704ae 100644 --- a/benchmark/CMakeLists.txt +++ b/benchmark/CMakeLists.txt @@ -133,7 +133,8 @@ foreach(_benchmark ${_benchmarks}) CASES 1 "plain call" 2 "std::invoke" - 3 "eggs::invoke") + 3 "eggs::invoke" + 4 "eggs::invoke_r") target_link_libraries(benchmark.${_benchmark} Eggs::Invoke) set_property(TARGET benchmark.${_benchmark} PROPERTY FOLDER "benchmark") diff --git a/benchmark/callable.cpp.in b/benchmark/callable.cpp.in index 4c02018..30c0bc6 100644 --- a/benchmark/callable.cpp.in +++ b/benchmark/callable.cpp.in @@ -1,6 +1,6 @@ #if BENCHMARK == 2 #include -#elif BENCHMARK == 3 +#elif BENCHMARK == 3 || BENCHMARK == 4 #include #endif @@ -29,6 +29,8 @@ static void benchmark() std::invoke(callable{}, 0, 1, 2); #elif BENCHMARK == 3 eggs::invoke(callable{}, 0, 1, 2); +#elif BENCHMARK == 4 + eggs::invoke_r(callable{}, 0, 1, 2); #endif } diff --git a/benchmark/function.cpp.in b/benchmark/function.cpp.in index 0ec88d0..2365203 100644 --- a/benchmark/function.cpp.in +++ b/benchmark/function.cpp.in @@ -1,6 +1,6 @@ #if BENCHMARK == 2 #include -#elif BENCHMARK == 3 +#elif BENCHMARK == 3 || BENCHMARK == 4 #include #endif @@ -16,6 +16,8 @@ static void benchmark() std::invoke(fun, 0, 1, 2); #elif BENCHMARK == 3 eggs::invoke(fun, 0, 1, 2); +#elif BENCHMARK == 4 + eggs::invoke_r(fun, 0, 1, 2); #endif } diff --git a/benchmark/member_function.cpp.in b/benchmark/member_function.cpp.in index bdaa547..e45c135 100644 --- a/benchmark/member_function.cpp.in +++ b/benchmark/member_function.cpp.in @@ -1,6 +1,6 @@ #if BENCHMARK == 2 #include -#elif BENCHMARK == 3 +#elif BENCHMARK == 3 || BENCHMARK == 4 #include #endif @@ -19,6 +19,8 @@ static void benchmark() std::invoke(&mem::fun, mem{}, 0, 1, 2); #elif BENCHMARK == 3 eggs::invoke(&mem::fun, mem{}, 0, 1, 2); +#elif BENCHMARK == 4 + eggs::invoke_r(&mem::fun, mem{}, 0, 1, 2); #endif } diff --git a/benchmark/member_object.cpp.in b/benchmark/member_object.cpp.in index 6b5e320..c894d24 100644 --- a/benchmark/member_object.cpp.in +++ b/benchmark/member_object.cpp.in @@ -1,6 +1,6 @@ #if BENCHMARK == 2 #include -#elif BENCHMARK == 3 +#elif BENCHMARK == 3 || BENCHMARK == 4 #include #endif @@ -19,6 +19,8 @@ static void benchmark() std::invoke(&mem::obj, mem{}); #elif BENCHMARK == 3 eggs::invoke(&mem::obj, mem{}); +#elif BENCHMARK == 4 + eggs::invoke_r(&mem::obj, mem{}); #endif } From 074d6acea295003c3dff655ba6fc09919402cc71 Mon Sep 17 00:00:00 2001 From: Agustin K-ballo Berge Date: Mon, 27 Jul 2020 14:26:42 -0300 Subject: [PATCH 2/2] Reduce invoke_r instantiations --- include/eggs/invoke.hpp | 38 ++++++++------------------------------ test/invoke.cpp | 1 + test/is_invocable.cpp | 1 + 3 files changed, 10 insertions(+), 30 deletions(-) diff --git a/include/eggs/invoke.hpp b/include/eggs/invoke.hpp index e0b3bcb..a8ed6eb 100644 --- a/include/eggs/invoke.hpp +++ b/include/eggs/invoke.hpp @@ -126,42 +126,20 @@ namespace eggs { namespace detail (static_cast<::eggs::detail::invoke>(F)(__VA_ARGS__)) // `INVOKE(f, t1, t2, ..., tN)` implicitly converted to `R`. - template ::type> - struct invoke_r - { - private: - static R conversion(R) noexcept; + template + R invoke_r_conv(R) noexcept; - public: - template - static constexpr auto call(F&& f, Args&&... args) - noexcept(noexcept(conversion( - EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)))) - -> decltype(conversion( - EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) - { - return EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...); - } - }; + template + auto invoke_r(std::false_type, F&& f, Ts&&... ts) + -> decltype(detail::invoke_r_conv(EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(ts)...))); // `static_cast(INVOKE(f, t1, t2, ..., tN))` if `R` is _cv_ `void`. template - struct invoke_r - { - template - static constexpr auto call(F&& f, Args&&... args) - noexcept(noexcept( - EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) - -> decltype(static_cast( - EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...))) - { - return static_cast( - EGGS_INVOKE(EGGS_FWD(f), EGGS_FWD(args)...)); - } - }; + void invoke_r(std::true_type, ...); #define EGGS_INVOKE_R(R, F, ...) \ - (::eggs::detail::invoke_r::call(F, __VA_ARGS__)) + (static_cast( \ + std::is_void{}, F, __VA_ARGS__))>(EGGS_INVOKE(F, __VA_ARGS__))) }} // namespace eggs::detail diff --git a/test/invoke.cpp b/test/invoke.cpp index f7be3d6..05cfc35 100644 --- a/test/invoke.cpp +++ b/test/invoke.cpp @@ -612,6 +612,7 @@ void test_fun_obj() CHECK_SCOPE(test_not_invocable(f)); CHECK_SCOPE(test_not_invocable(f, 40, 41)); + CHECK_SCOPE(test_not_invocable_r(f, 40)); } } diff --git a/test/is_invocable.cpp b/test/is_invocable.cpp index a546a10..3ed4518 100644 --- a/test/is_invocable.cpp +++ b/test/is_invocable.cpp @@ -299,6 +299,7 @@ int main() CHECK_SCOPE(test_not_invocable()); CHECK_SCOPE(test_not_invocable()); + CHECK_SCOPE(test_not_invocable()); } return test_report();