add is_invocable_r

This commit is contained in:
2018-12-08 12:49:35 +07:00
parent c9df9a83e8
commit 6cb369ffa1
3 changed files with 186 additions and 12 deletions

View File

@@ -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<F, Args...>`
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<F, Args...>`
Analog of [`std::invoke_result_t`](https://en.cppreference.com/w/cpp/types/result_of) from C++17
### `invoke_hpp::is_invocable<F, Args...>`
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<R, F, Args...>`
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)

View File

@@ -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<void_t<is_invocable_impl_tag, invoke_result_t<F, Args...>>, F, Args...>
: std::true_type {};
template < typename R, typename F, typename... Args >
struct is_invocable_r_impl<void_t<is_invocable_r_impl_tag, invoke_result_t<F, Args...>>, R, F, Args...>
: std::conditional_t<
std::is_void<R>::value,
std::true_type,
std::is_convertible<invoke_result_t<F, Args...>, R>> {};
}
template < typename R, typename F, typename... Args >
struct is_invocable_r
: impl::is_invocable_r_impl<void, R, F, Args...> {};
template < typename F, typename... Args >
struct is_invocable
: impl::is_invocable_impl<void, F, Args...> {};
using is_invocable = is_invocable_r<void, F, Args...>;
}
//

160
tests.cpp
View File

@@ -298,6 +298,166 @@ TEST_CASE("is_invocable"){
}
}
TEST_CASE("is_invocable_r"){
SECTION("is_invocable_r_functions"){
static_assert(
inv::is_invocable_r<void, decltype(simple_static_function)>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(simple_static_function_r)>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(simple_static_function_r)>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<const int&, decltype(simple_static_function_r_with_arg), const int&>::value,
"unit test fail");
}
SECTION("is_not_invocable_r_functions"){
static_assert(
!inv::is_invocable_r<void, decltype(simple_static_function), int>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int, decltype(simple_static_function_r), obj_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<const int&, decltype(simple_static_function_r_with_arg), const obj2_t&>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int, decltype(simple_static_function)>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int*, decltype(simple_static_function_r)>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<obj_t, decltype(simple_static_function_r_with_arg), const int&>::value,
"unit test fail");
}
SECTION("is_invocable_r_members"){
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::member), obj_t>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::member), obj_t*>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::member), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::member_r), obj_t>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::member_r), obj_t*>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::member_r), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::member_r), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::member_r_with_arg), obj_t, int>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::member_r_with_arg), obj_t*, int>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::member_r_with_arg), std::reference_wrapper<obj_t>, int>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::member_r_with_arg), std::reference_wrapper<obj_t>, int>::value,
"unit test fail");
}
SECTION("is_not_invocable_r_members"){
static_assert(
!inv::is_invocable_r<int, decltype(&obj_t::member), obj_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int*, decltype(&obj_t::member), obj_t*>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<obj_t, decltype(&obj_t::member), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<obj_t, decltype(&obj_t::member_r), obj_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int*, decltype(&obj_t::member_r), obj_t*>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int, decltype(&obj_t::member_r), std::reference_wrapper<obj2_t>>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<obj_t, decltype(&obj_t::member_r_with_arg), obj_t, int>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int*, decltype(&obj_t::member_r_with_arg), obj_t*, int>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int, decltype(&obj_t::member_r_with_arg), std::reference_wrapper<obj_t>, obj2_t>::value,
"unit test fail");
}
SECTION("is_invocable_r_objects"){
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::value), obj_t>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::value), obj_t*>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::value), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::value), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::value_c), obj_t>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::value_c), obj_t*>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<int, decltype(&obj_t::value_c), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
inv::is_invocable_r<void, decltype(&obj_t::value_c), std::reference_wrapper<obj_t>>::value,
"unit test fail");
}
SECTION("is_not_invocable_r_objects"){
static_assert(
!inv::is_invocable_r<obj_t, decltype(&obj_t::value), obj_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int*, decltype(&obj_t::value), obj_t*>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int, decltype(&obj_t::value), std::reference_wrapper<obj_t>, obj2_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<void, decltype(&obj_t::value), std::reference_wrapper<obj_t>, obj2_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<obj_t, decltype(&obj_t::value_c), obj_t>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<int*, decltype(&obj_t::value_c), obj_t*>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<obj2_t, decltype(&obj_t::value_c), std::reference_wrapper<obj_t>>::value,
"unit test fail");
static_assert(
!inv::is_invocable_r<void, decltype(&obj_t::value_c), std::reference_wrapper<obj_t**>>::value,
"unit test fail");
}
}
TEST_CASE("apply"){
SECTION("apply_functions"){
inv::apply(simple_static_function, std::make_tuple());