From c9df9a83e83f13d7f948db63a888987c159fb0ac Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sat, 8 Dec 2018 10:39:05 +0700 Subject: [PATCH 1/2] add is_invocable --- .gitignore | 1 + README.md | 4 ++ invoke.hpp | 24 +++++++++ tests.cpp | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 184 insertions(+) diff --git a/.gitignore b/.gitignore index 2300a2d..eb695eb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ build/* +.vscode/* CMakeLists.txt.user diff --git a/README.md b/README.md index 307a258..32d3ac0 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,10 @@ Analog of [std::invoke](https://en.cppreference.com/w/cpp/utility/functional/inv Analog of [std::invoke_result](https://en.cppreference.com/w/cpp/types/result_of) from C++17 +### `invoke_hpp::is_invocable` + +Analog of [std::is_invocable](https://en.cppreference.com/w/cpp/types/is_invocable) from C++17 + ### `invoke_hpp::apply(F&& f, Tuple&& args)` Analog of [std::apply](https://en.cppreference.com/w/cpp/utility/apply) from C++17 diff --git a/invoke.hpp b/invoke.hpp index d365795..e1bbdb4 100644 --- a/invoke.hpp +++ b/invoke.hpp @@ -183,6 +183,30 @@ namespace invoke_hpp using invoke_result_t = typename invoke_result::type; } +// +// is_invocable +// + +namespace invoke_hpp +{ + namespace impl + { + struct is_invocable_impl_tag {}; + + template < typename Void, typename F, typename... Args > + struct is_invocable_impl + : std::false_type {}; + + template < typename F, typename... Args > + struct is_invocable_impl>, F, Args...> + : std::true_type {}; + } + + template < typename F, typename... Args > + struct is_invocable + : impl::is_invocable_impl {}; +} + // // apply // diff --git a/tests.cpp b/tests.cpp index b712ec2..8954086 100644 --- a/tests.cpp +++ b/tests.cpp @@ -41,6 +41,9 @@ namespace return v; } }; + + class obj2_t { + }; } TEST_CASE("invoke"){ @@ -100,6 +103,16 @@ TEST_CASE("invoke_result"){ int, inv::invoke_result_t>::value, "unit test fail"); + static_assert( + std::is_same< + int, + inv::invoke_result_t>::value, + "unit test fail"); + static_assert( + std::is_same< + const int&, + inv::invoke_result_t>::value, + "unit test fail"); } SECTION("invoke_result_members"){ static_assert( @@ -140,6 +153,148 @@ TEST_CASE("invoke_result"){ std::is_same, int>>::value, "unit test fail"); + + static_assert( + std::is_same>::value, + "unit test fail"); + static_assert( + std::is_same>::value, + "unit test fail"); + static_assert( + std::is_same, const int&>>::value, + "unit test fail"); + } +} + +TEST_CASE("is_invocable"){ + SECTION("is_invocable_functions"){ + static_assert( + inv::is_invocable::value, + "unit test fail"); + static_assert( + inv::is_invocable::value, + "unit test fail"); + static_assert( + inv::is_invocable::value, + "unit test fail"); + } + SECTION("is_not_invocable_functions"){ + static_assert( + !inv::is_invocable::value, + "unit test fail"); + static_assert( + !inv::is_invocable::value, + "unit test fail"); + static_assert( + !inv::is_invocable::value, + "unit test fail"); + } + SECTION("is_invocable_members"){ + static_assert( + inv::is_invocable::value, + "unit test fail"); + static_assert( + inv::is_invocable::value, + "unit test fail"); + static_assert( + inv::is_invocable>::value, + "unit test fail"); + + static_assert( + inv::is_invocable::value, + "unit test fail"); + static_assert( + inv::is_invocable::value, + "unit test fail"); + static_assert( + inv::is_invocable>::value, + "unit test fail"); + + static_assert( + inv::is_invocable::value, + "unit test fail"); + static_assert( + inv::is_invocable::value, + "unit test fail"); + static_assert( + inv::is_invocable, int>::value, + "unit test fail"); + } + SECTION("is_not_invocable_members"){ + static_assert( + !inv::is_invocable::value, + "unit test fail"); + static_assert( + !inv::is_invocable::value, + "unit test fail"); + static_assert( + !inv::is_invocable*>::value, + "unit test fail"); + + static_assert( + !inv::is_invocable::value, + "unit test fail"); + static_assert( + !inv::is_invocable::value, + "unit test fail"); + static_assert( + !inv::is_invocable>::value, + "unit test fail"); + + static_assert( + !inv::is_invocable::value, + "unit test fail"); + static_assert( + !inv::is_invocable::value, + "unit test fail"); + static_assert( + !inv::is_invocable, int>::value, + "unit test fail"); + } + SECTION("is_invocable_objects"){ + static_assert( + inv::is_invocable::value, + "unit test fail"); + static_assert( + inv::is_invocable::value, + "unit test fail"); + static_assert( + inv::is_invocable>::value, + "unit test fail"); + + static_assert( + inv::is_invocable::value, + "unit test fail"); + static_assert( + inv::is_invocable::value, + "unit test fail"); + static_assert( + inv::is_invocable>::value, + "unit test fail"); + } + SECTION("is_not_invocable_objects"){ + static_assert( + !inv::is_invocable::value, + "unit test fail"); + static_assert( + !inv::is_invocable::value, + "unit test fail"); + static_assert( + !inv::is_invocable::value, + "unit test fail"); + + static_assert( + !inv::is_invocable::value, + "unit test fail"); + static_assert( + !inv::is_invocable::value, + "unit test fail"); + static_assert( + !inv::is_invocable>::value, + "unit test fail"); } } From 6cb369ffa1c01daa346ef8b08414193a77ea34c5 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Sat, 8 Dec 2018 12:49:35 +0700 Subject: [PATCH 2/2] add is_invocable_r --- README.md | 16 ++++-- invoke.hpp | 22 +++++--- tests.cpp | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 186 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 32d3ac0..ae1d996 100644 --- a/README.md +++ b/README.md @@ -34,18 +34,26 @@ ### `invoke_hpp::invoke(F&& f, Args&&... args)` -Analog of [std::invoke](https://en.cppreference.com/w/cpp/utility/functional/invoke) from C++17 +Analog of [`std::invoke`](https://en.cppreference.com/w/cpp/utility/functional/invoke) from C++17 ### `invoke_hpp::invoke_result` -Analog of [std::invoke_result](https://en.cppreference.com/w/cpp/types/result_of) from C++17 +Analog of [`std::invoke_result`](https://en.cppreference.com/w/cpp/types/result_of) from C++17 + +### `invoke_hpp::invoke_result_t` + +Analog of [`std::invoke_result_t`](https://en.cppreference.com/w/cpp/types/result_of) from C++17 ### `invoke_hpp::is_invocable` -Analog of [std::is_invocable](https://en.cppreference.com/w/cpp/types/is_invocable) from C++17 +Analog of [`std::is_invocable`](https://en.cppreference.com/w/cpp/types/is_invocable) from C++17 + +### `invoke_hpp::is_invocable_r` + +Analog of [`std::is_invocable_r`](https://en.cppreference.com/w/cpp/types/is_invocable) from C++17 ### `invoke_hpp::apply(F&& f, Tuple&& args)` -Analog of [std::apply](https://en.cppreference.com/w/cpp/utility/apply) from C++17 +Analog of [`std::apply`](https://en.cppreference.com/w/cpp/utility/apply) from C++17 ## [License (MIT)](./LICENSE.md) diff --git a/invoke.hpp b/invoke.hpp index e1bbdb4..1224e7b 100644 --- a/invoke.hpp +++ b/invoke.hpp @@ -191,20 +191,26 @@ namespace invoke_hpp { namespace impl { - struct is_invocable_impl_tag {}; + struct is_invocable_r_impl_tag {}; - template < typename Void, typename F, typename... Args > - struct is_invocable_impl + template < typename Void, typename R, typename F, typename... Args > + struct is_invocable_r_impl : std::false_type {}; - template < typename F, typename... Args > - struct is_invocable_impl>, F, Args...> - : std::true_type {}; + template < typename R, typename F, typename... Args > + struct is_invocable_r_impl>, R, F, Args...> + : std::conditional_t< + std::is_void::value, + std::true_type, + std::is_convertible, R>> {}; } + template < typename R, typename F, typename... Args > + struct is_invocable_r + : impl::is_invocable_r_impl {}; + template < typename F, typename... Args > - struct is_invocable - : impl::is_invocable_impl {}; + using is_invocable = is_invocable_r; } // diff --git a/tests.cpp b/tests.cpp index 8954086..72d4e13 100644 --- a/tests.cpp +++ b/tests.cpp @@ -298,6 +298,166 @@ TEST_CASE("is_invocable"){ } } +TEST_CASE("is_invocable_r"){ + SECTION("is_invocable_r_functions"){ + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + } + SECTION("is_not_invocable_r_functions"){ + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + } + SECTION("is_invocable_r_members"){ + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r>::value, + "unit test fail"); + + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r>::value, + "unit test fail"); + static_assert( + inv::is_invocable_r>::value, + "unit test fail"); + + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r, int>::value, + "unit test fail"); + static_assert( + inv::is_invocable_r, int>::value, + "unit test fail"); + } + SECTION("is_not_invocable_r_members"){ + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r>::value, + "unit test fail"); + + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r>::value, + "unit test fail"); + + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r, obj2_t>::value, + "unit test fail"); + } + SECTION("is_invocable_r_objects"){ + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r>::value, + "unit test fail"); + static_assert( + inv::is_invocable_r>::value, + "unit test fail"); + + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r::value, + "unit test fail"); + static_assert( + inv::is_invocable_r>::value, + "unit test fail"); + static_assert( + inv::is_invocable_r>::value, + "unit test fail"); + } + SECTION("is_not_invocable_r_objects"){ + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r, obj2_t>::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r, obj2_t>::value, + "unit test fail"); + + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r>::value, + "unit test fail"); + static_assert( + !inv::is_invocable_r>::value, + "unit test fail"); + } +} + TEST_CASE("apply"){ SECTION("apply_functions"){ inv::apply(simple_static_function, std::make_tuple());