Commit 808c845b authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

FOLLY_CREATE_FREE_INVOKER, FOLLY_CREATE_MEMBER_INVOKER

Summary:
[Folly] `FOLLY_CREATE_FREE_INVOKER` and `FOLLY_CREATE_MEMBER_INVOKER` to replace `FOLLY_CREATE_FREE_INVOKE_TRAITS` and `FOLLY_CREATE_MEMBER_INVOKE_TRAITS`.

New approach: just emit an invoker object. For the traits, just use the normal traits instead of rewriting them, or use `invoke_traits` to get an invoke-traits type specialized to the invoker.

Reviewed By: vitaut

Differential Revision: D18079121

fbshipit-source-id: 8258c36b8ba6ee62a8ecc104cd1b6281d313960f
parent 3de8f357
......@@ -41,10 +41,10 @@ namespace folly {
namespace detail {
namespace member {
FOLLY_CREATE_MEMBER_INVOKE_TRAITS(lock, lock);
FOLLY_CREATE_MEMBER_INVOKE_TRAITS(try_lock_for, try_lock_for);
FOLLY_CREATE_MEMBER_INVOKE_TRAITS(lock_shared, lock_shared);
FOLLY_CREATE_MEMBER_INVOKE_TRAITS(lock_upgrade, lock_upgrade);
FOLLY_CREATE_MEMBER_INVOKER(lock, lock);
FOLLY_CREATE_MEMBER_INVOKER(try_lock_for, try_lock_for);
FOLLY_CREATE_MEMBER_INVOKER(lock_shared, lock_shared);
FOLLY_CREATE_MEMBER_INVOKER(lock_upgrade, lock_upgrade);
} // namespace member
/**
......@@ -86,7 +86,7 @@ class LockInterfaceDispatcher {
private:
// assert that the mutex type has basic lock and unlock functions
static_assert(
member::lock::is_invocable<Mutex>::value,
folly::is_invocable<member::lock, Mutex>::value,
"The mutex type must support lock and unlock functions");
using duration = std::chrono::milliseconds;
......@@ -94,11 +94,11 @@ class LockInterfaceDispatcher {
public:
static constexpr bool has_lock_unique = true;
static constexpr bool has_lock_timed =
member::try_lock_for::is_invocable<Mutex, duration>::value;
folly::is_invocable<member::try_lock_for, Mutex, duration>::value;
static constexpr bool has_lock_shared =
member::lock_shared::is_invocable<Mutex>::value;
folly::is_invocable<member::lock_shared, Mutex>::value;
static constexpr bool has_lock_upgrade =
member::lock_upgrade::is_invocable<Mutex>::value;
folly::is_invocable<member::lock_upgrade, Mutex>::value;
};
/**
......
......@@ -667,12 +667,12 @@ struct AllocatorHasTrivialDeallocate<CxxAllocatorAdaptor<T, Alloc>>
namespace detail {
// note that construct and destroy here are methods, not short names for
// the constructor and destructor
FOLLY_CREATE_MEMBER_INVOKE_TRAITS(AllocatorConstruct_, construct);
FOLLY_CREATE_MEMBER_INVOKE_TRAITS(AllocatorDestroy_, destroy);
FOLLY_CREATE_MEMBER_INVOKER(AllocatorConstruct_, construct);
FOLLY_CREATE_MEMBER_INVOKER(AllocatorDestroy_, destroy);
template <typename Void, typename Alloc, typename... Args>
struct AllocatorCustomizesConstruct_
: AllocatorConstruct_::template is_invocable<Alloc, Args...> {};
: folly::is_invocable<AllocatorConstruct_, Alloc, Args...> {};
template <typename Alloc, typename... Args>
struct AllocatorCustomizesConstruct_<
......@@ -682,7 +682,7 @@ struct AllocatorCustomizesConstruct_<
template <typename Void, typename Alloc, typename... Args>
struct AllocatorCustomizesDestroy_
: AllocatorDestroy_::template is_invocable<Alloc, Args...> {};
: folly::is_invocable<AllocatorDestroy_, Alloc, Args...> {};
template <typename Alloc, typename... Args>
struct AllocatorCustomizesDestroy_<
......
......@@ -296,41 +296,16 @@ struct invoke_traits : detail::invoke_traits_base<Invoke> {
BOOST_PP_TUPLE_TO_LIST((__VA_ARGS__))))
/***
* FOLLY_CREATE_FREE_INVOKE_TRAITS
* FOLLY_CREATE_FREE_INVOKER
*
* Used to create traits container, bound to a specific free-invocable name,
* with the following member traits types and aliases:
*
* * invoke_result
* * invoke_result_t
* * is_invocable
* * is_invocable_v
* * is_invocable_r
* * is_invocable_r_v
* * is_nothrow_invocable
* * is_nothrow_invocable_v
* * is_nothrow_invocable_r
* * is_nothrow_invocable_r_v
*
* The container also has a static member function:
*
* * invoke
*
* And a member type alias:
*
* * invoke_type
*
* These members have behavior matching the behavior of C++17's corresponding
* invocation traits types, aliases, and functions, but substituting canonical
* invocation with member invocation.
* Used to create an invoker type bound to a specific free-invocable name.
*
* Example:
*
* FOLLY_CREATE_FREE_INVOKE_TRAITS(foo_invoke_traits, foo);
* FOLLY_CREATE_FREE_INVOKER(foo_invoker, foo);
*
* The traits container type `foo_invoke_traits` is generated in the current
* namespace and has the listed member types and aliases. They may be used as
* follows:
* The type `foo_invoker` is generated in the current namespace and may be used
* as follows:
*
* namespace Deep {
* struct CanFoo {};
......@@ -338,7 +313,7 @@ struct invoke_traits : detail::invoke_traits_base<Invoke> {
* int foo(CanFoo&&, Car&&) noexcept { return 2; }
* }
*
* using traits = foo_invoke_traits;
* using traits = folly::invoke_traits<foo_invoker>;
*
* traits::invoke(Deep::CanFoo{}, Car{}) // 2
*
......@@ -365,7 +340,7 @@ struct invoke_traits : detail::invoke_traits_base<Invoke> {
* and alternate definitions in the namespaces of its arguments, the primary
* definitions may automatically be found as follows:
*
* FOLLY_CREATE_FREE_INVOKE_TRAITS(swap_invoke_traits, swap, std);
* FOLLY_CREATE_FREE_INVOKER(swap_invoker, swap, std);
*
* In this case, `swap_invoke_traits::invoke(int&, int&)` will use the primary
* definition found in `namespace std` relative to the current namespace, which
......@@ -376,12 +351,12 @@ struct invoke_traits : detail::invoke_traits_base<Invoke> {
* void swap(HasData&, HasData&) { throw 7; }
* }
*
* using traits = swap_invoke_traits;
* using traits = invoke_traits<swap_invoker>;
*
* HasData a, b;
* traits::invoke(a, b); // throw 7
*/
#define FOLLY_CREATE_FREE_INVOKE_TRAITS(classname, funcname, ...) \
#define FOLLY_CREATE_FREE_INVOKER(classname, funcname, ...) \
namespace classname##__folly_detail_invoke_ns { \
FOLLY_MAYBE_UNUSED void funcname( \
::folly::detail::invoke_private_overload&); \
......@@ -396,52 +371,26 @@ struct invoke_traits : detail::invoke_traits_base<Invoke> {
}; \
} \
struct classname \
: ::folly::invoke_traits< \
classname##__folly_detail_invoke_ns::__folly_detail_invoke_obj> {}
: classname##__folly_detail_invoke_ns::__folly_detail_invoke_obj {}
/***
* FOLLY_CREATE_MEMBER_INVOKE_TRAITS
*
* Used to create traits container, bound to a specific member-invocable name,
* with the following member traits types and aliases:
*
* * invoke_result
* * invoke_result_t
* * is_invocable
* * is_invocable_v
* * is_invocable_r
* * is_invocable_r_v
* * is_nothrow_invocable
* * is_nothrow_invocable_v
* * is_nothrow_invocable_r
* * is_nothrow_invocable_r_v
*
* The container also has a static member function:
*
* * invoke
*
* And a member type alias:
*
* * invoke_type
* FOLLY_CREATE_MEMBER_INVOKER
*
* These members have behavior matching the behavior of C++17's corresponding
* invocation traits types, aliases, and functions, but substituting canonical
* invocation with member invocation.
* Used to create an invoker type bound to a specific member-invocable name.
*
* Example:
*
* FOLLY_CREATE_MEMBER_INVOKE_TRAITS(foo_invoke_traits, foo);
* FOLLY_CREATE_MEMBER_INVOKER(foo_invoker, foo);
*
* The traits container type `foo_invoke_traits` is generated in the current
* namespace and has the listed member types and aliases. They may be used as
* follows:
* The type `foo_invoker` is generated in the current namespace and may be used
* as follows:
*
* struct CanFoo {
* int foo(Bar&) { return 1; }
* int foo(Car&&) noexcept { return 2; }
* };
*
* using traits = foo_invoke_traits;
* using traits = folly::invoke_traits<foo_invoker>;
*
* traits::invoke(CanFoo{}, Car{}) // 2
*
......@@ -464,8 +413,8 @@ struct invoke_traits : detail::invoke_traits_base<Invoke> {
* traits::is_nothrow_invocable_v<int, CanFoo, Car&&> // true
* traits::is_nothrow_invocable_v<char*, CanFoo, Car&&> // false
*/
#define FOLLY_CREATE_MEMBER_INVOKE_TRAITS(classname, membername) \
struct classname##__folly_detail_member_invoke { \
#define FOLLY_CREATE_MEMBER_INVOKER(classname, membername) \
struct classname { \
template <typename O, typename... Args> \
constexpr auto operator()(O&& o, Args&&... args) const noexcept(noexcept( \
static_cast<O&&>(o).membername(static_cast<Args&&>(args)...))) \
......@@ -473,6 +422,4 @@ struct invoke_traits : detail::invoke_traits_base<Invoke> {
static_cast<O&&>(o).membername(static_cast<Args&&>(args)...)) { \
return static_cast<O&&>(o).membername(static_cast<Args&&>(args)...); \
} \
}; \
struct classname \
: ::folly::invoke_traits<classname##__folly_detail_member_invoke> {}
}
......@@ -41,7 +41,7 @@ struct Fn {
int volatile x_ = 17;
};
FOLLY_CREATE_MEMBER_INVOKE_TRAITS(test_invoke_traits, test);
FOLLY_CREATE_MEMBER_INVOKER(test_invoker, test);
struct Obj {
char test(int, int) noexcept {
......@@ -90,9 +90,9 @@ namespace unswappable {
FOLLY_MAYBE_UNUSED AltSwappableRet swap(AltSwappable&, AltSwappable&);
} // namespace unswappable
FOLLY_CREATE_FREE_INVOKE_TRAITS(go_invoke_traits, go);
FOLLY_CREATE_FREE_INVOKE_TRAITS(swap_invoke_traits, swap, std, unswappable);
FOLLY_CREATE_FREE_INVOKE_TRAITS(unused_invoke_traits, definitely_unused_name_);
FOLLY_CREATE_FREE_INVOKER(go_invoker, go);
FOLLY_CREATE_FREE_INVOKER(swap_invoker, swap, std, unswappable);
FOLLY_CREATE_FREE_INVOKER(unused_invoker, definitely_unused_name_);
} // namespace
......@@ -144,7 +144,7 @@ TEST_F(InvokeTest, is_nothrow_invocable_r) {
}
TEST_F(InvokeTest, free_invoke) {
using traits = go_invoke_traits;
using traits = folly::invoke_traits<go_invoker>;
x::Obj x_;
y::Obj y_;
......@@ -157,7 +157,7 @@ TEST_F(InvokeTest, free_invoke) {
}
TEST_F(InvokeTest, free_invoke_result) {
using traits = go_invoke_traits;
using traits = folly::invoke_traits<go_invoker>;
EXPECT_TRUE((std::is_same<int, traits::invoke_result_t<x::Obj, int>>::value));
EXPECT_TRUE((
......@@ -165,7 +165,7 @@ TEST_F(InvokeTest, free_invoke_result) {
}
TEST_F(InvokeTest, free_is_invocable) {
using traits = go_invoke_traits;
using traits = folly::invoke_traits<go_invoker>;
EXPECT_TRUE((traits::is_invocable_v<x::Obj, int>));
EXPECT_TRUE((traits::is_invocable_v<y::Obj, char const*>));
......@@ -174,7 +174,7 @@ TEST_F(InvokeTest, free_is_invocable) {
}
TEST_F(InvokeTest, free_is_invocable_r) {
using traits = go_invoke_traits;
using traits = folly::invoke_traits<go_invoker>;
EXPECT_TRUE((traits::is_invocable_r_v<int, x::Obj, int>));
EXPECT_TRUE((traits::is_invocable_r_v<char, y::Obj, char const*>));
......@@ -183,7 +183,7 @@ TEST_F(InvokeTest, free_is_invocable_r) {
}
TEST_F(InvokeTest, free_is_nothrow_invocable) {
using traits = go_invoke_traits;
using traits = folly::invoke_traits<go_invoker>;
EXPECT_TRUE((traits::is_nothrow_invocable_v<x::Obj, int>));
EXPECT_FALSE((traits::is_nothrow_invocable_v<y::Obj, char const*>));
......@@ -192,7 +192,7 @@ TEST_F(InvokeTest, free_is_nothrow_invocable) {
}
TEST_F(InvokeTest, free_is_nothrow_invocable_r) {
using traits = go_invoke_traits;
using traits = folly::invoke_traits<go_invoker>;
EXPECT_TRUE((traits::is_nothrow_invocable_r_v<int, x::Obj, int>));
EXPECT_FALSE((traits::is_nothrow_invocable_r_v<char, y::Obj, char const*>));
......@@ -201,7 +201,7 @@ TEST_F(InvokeTest, free_is_nothrow_invocable_r) {
}
TEST_F(InvokeTest, free_invoke_swap) {
using traits = swap_invoke_traits;
using traits = folly::invoke_traits<swap_invoker>;
int a = 3;
int b = 4;
......@@ -226,7 +226,7 @@ TEST_F(InvokeTest, free_invoke_swap) {
}
TEST_F(InvokeTest, member_invoke) {
using traits = test_invoke_traits;
using traits = folly::invoke_traits<test_invoker>;
Obj fn;
......@@ -238,7 +238,7 @@ TEST_F(InvokeTest, member_invoke) {
}
TEST_F(InvokeTest, member_invoke_result) {
using traits = test_invoke_traits;
using traits = folly::invoke_traits<test_invoker>;
EXPECT_TRUE(
(std::is_same<char, traits::invoke_result_t<Obj, int, char>>::value));
......@@ -248,7 +248,7 @@ TEST_F(InvokeTest, member_invoke_result) {
}
TEST_F(InvokeTest, member_is_invocable) {
using traits = test_invoke_traits;
using traits = folly::invoke_traits<test_invoker>;
EXPECT_TRUE((traits::is_invocable_v<Obj, int, char>));
EXPECT_TRUE((traits::is_invocable_v<Obj, int, char*>));
......@@ -256,7 +256,7 @@ TEST_F(InvokeTest, member_is_invocable) {
}
TEST_F(InvokeTest, member_is_invocable_r) {
using traits = test_invoke_traits;
using traits = folly::invoke_traits<test_invoker>;
EXPECT_TRUE((traits::is_invocable_r_v<int, Obj, int, char>));
EXPECT_TRUE((traits::is_invocable_r_v<int, Obj, int, char*>));
......@@ -264,7 +264,7 @@ TEST_F(InvokeTest, member_is_invocable_r) {
}
TEST_F(InvokeTest, member_is_nothrow_invocable) {
using traits = test_invoke_traits;
using traits = folly::invoke_traits<test_invoker>;
EXPECT_TRUE((traits::is_nothrow_invocable_v<Obj, int, char>));
EXPECT_FALSE((traits::is_nothrow_invocable_v<Obj, int, char*>));
......@@ -272,7 +272,7 @@ TEST_F(InvokeTest, member_is_nothrow_invocable) {
}
TEST_F(InvokeTest, member_is_nothrow_invocable_r) {
using traits = test_invoke_traits;
using traits = folly::invoke_traits<test_invoker>;
EXPECT_TRUE((traits::is_nothrow_invocable_r_v<int, Obj, int, char>));
EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int, Obj, int, char*>));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment