Commit 3b4f9dfc authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

invoker suites

Summary:
A new pattern which creates an invoker type and a variable, both named for the member, with the type suffixed with `_fn` and the instance unsuffixed. Applied to free-invokers, member-invokers, and static-member invokers.

Automatic mangling as this does is not great but this is intended to be used selectively.

Changes the existing unit-tests to use the invoker variables generated by the invoker-suite macros, since the invoker variables depend on the invoker types and the generation of both depends on the invoker macros. So everything gets tested transitively.

Reviewed By: luciang

Differential Revision: D29190157

fbshipit-source-id: 72d8fb622c4c99bae48efc3e5e9f0bd411d6a813
parent 16837f09
...@@ -380,6 +380,20 @@ struct invoke_traits : detail::invoke_traits_base<I> { ...@@ -380,6 +380,20 @@ struct invoke_traits : detail::invoke_traits_base<I> {
struct classname \ struct classname \
: classname##__folly_detail_invoke_ns::__folly_detail_invoke_obj {} : classname##__folly_detail_invoke_ns::__folly_detail_invoke_obj {}
/***
* FOLLY_CREATE_FREE_INVOKER_SUITE
*
* Used to create an invoker type and associated variable bound to a specific
* free-invocable name. The invoker variable is named like the free-invocable
* name and the invoker type is named with a suffix of _fn.
*
* See FOLLY_CREATE_FREE_INVOKER.
*/
#define FOLLY_CREATE_FREE_INVOKER_SUITE(membername, ...) \
FOLLY_CREATE_FREE_INVOKER(membername##_fn, membername, __VA_ARGS__); \
FOLLY_MAYBE_UNUSED FOLLY_INLINE_VARIABLE constexpr membername##_fn \
membername {}
/*** /***
* FOLLY_CREATE_MEMBER_INVOKER * FOLLY_CREATE_MEMBER_INVOKER
* *
...@@ -433,6 +447,20 @@ struct invoke_traits : detail::invoke_traits_base<I> { ...@@ -433,6 +447,20 @@ struct invoke_traits : detail::invoke_traits_base<I> {
} \ } \
} }
/***
* FOLLY_CREATE_MEMBER_INVOKER_SUITE
*
* Used to create an invoker type and associated variable bound to a specific
* member-invocable name. The invoker variable is named like the member-
* invocable name and the invoker type is named with a suffix of _fn.
*
* See FOLLY_CREATE_MEMBER_INVOKER.
*/
#define FOLLY_CREATE_MEMBER_INVOKER_SUITE(membername) \
FOLLY_CREATE_MEMBER_INVOKER(membername##_fn, membername); \
FOLLY_MAYBE_UNUSED FOLLY_INLINE_VARIABLE constexpr membername##_fn \
membername {}
/*** /***
* FOLLY_CREATE_STATIC_MEMBER_INVOKER * FOLLY_CREATE_STATIC_MEMBER_INVOKER
* *
...@@ -485,6 +513,22 @@ struct invoke_traits : detail::invoke_traits_base<I> { ...@@ -485,6 +513,22 @@ struct invoke_traits : detail::invoke_traits_base<I> {
} \ } \
} }
/***
* FOLLY_CREATE_STATIC_MEMBER_INVOKER_SUITE
*
* Used to create an invoker type template and associated variable template
* bound to a specific static-member-invocable name. The invoker variable
* template is named like the static-member-invocable name and the invoker type
* template is named with a suffix of _fn.
*
* See FOLLY_CREATE_STATIC_MEMBER_INVOKER.
*/
#define FOLLY_CREATE_STATIC_MEMBER_INVOKER_SUITE(membername) \
FOLLY_CREATE_STATIC_MEMBER_INVOKER(membername##_fn, membername); \
template <typename T> \
FOLLY_MAYBE_UNUSED FOLLY_INLINE_VARIABLE constexpr membername##_fn<T> \
membername {}
namespace folly { namespace folly {
namespace detail_tag_invoke_fn { namespace detail_tag_invoke_fn {
......
...@@ -35,7 +35,11 @@ struct Fn { ...@@ -35,7 +35,11 @@ struct Fn {
int volatile x_ = 17; int volatile x_ = 17;
}; };
FOLLY_CREATE_MEMBER_INVOKER(test_invoker, test); namespace invoker {
FOLLY_CREATE_MEMBER_INVOKER_SUITE(test);
}
struct Obj { struct Obj {
char test(int, int) noexcept { return 'a'; } char test(int, int) noexcept { return 'a'; }
...@@ -78,9 +82,13 @@ namespace unswappable { ...@@ -78,9 +82,13 @@ namespace unswappable {
FOLLY_MAYBE_UNUSED AltSwappableRet swap(AltSwappable&, AltSwappable&); FOLLY_MAYBE_UNUSED AltSwappableRet swap(AltSwappable&, AltSwappable&);
} // namespace unswappable } // namespace unswappable
FOLLY_CREATE_FREE_INVOKER(go_invoker, go); namespace invoker {
FOLLY_CREATE_FREE_INVOKER(swap_invoker, swap, std, unswappable);
FOLLY_CREATE_FREE_INVOKER(unused_invoker, definitely_unused_name_); FOLLY_CREATE_FREE_INVOKER_SUITE(go);
FOLLY_CREATE_FREE_INVOKER_SUITE(swap, std, unswappable);
FOLLY_CREATE_FREE_INVOKER_SUITE(no_such_thing);
} // namespace invoker
} // namespace } // namespace
...@@ -132,7 +140,7 @@ TEST_F(InvokeTest, is_nothrow_invocable_r) { ...@@ -132,7 +140,7 @@ TEST_F(InvokeTest, is_nothrow_invocable_r) {
} }
TEST_F(InvokeTest, free_invoke) { TEST_F(InvokeTest, free_invoke) {
using traits = folly::invoke_traits<go_invoker>; using traits = folly::invoke_traits<decltype(invoker::go)>;
x::Obj x_; x::Obj x_;
y::Obj y_; y::Obj y_;
...@@ -145,7 +153,7 @@ TEST_F(InvokeTest, free_invoke) { ...@@ -145,7 +153,7 @@ TEST_F(InvokeTest, free_invoke) {
} }
TEST_F(InvokeTest, free_invoke_result) { TEST_F(InvokeTest, free_invoke_result) {
using traits = folly::invoke_traits<go_invoker>; using traits = folly::invoke_traits<decltype(invoker::go)>;
EXPECT_TRUE((std::is_same<int, traits::invoke_result_t<x::Obj, int>>::value)); EXPECT_TRUE((std::is_same<int, traits::invoke_result_t<x::Obj, int>>::value));
EXPECT_TRUE(( EXPECT_TRUE((
...@@ -153,7 +161,7 @@ TEST_F(InvokeTest, free_invoke_result) { ...@@ -153,7 +161,7 @@ TEST_F(InvokeTest, free_invoke_result) {
} }
TEST_F(InvokeTest, free_is_invocable) { TEST_F(InvokeTest, free_is_invocable) {
using traits = folly::invoke_traits<go_invoker>; using traits = folly::invoke_traits<decltype(invoker::go)>;
EXPECT_TRUE((traits::is_invocable_v<x::Obj, int>)); EXPECT_TRUE((traits::is_invocable_v<x::Obj, int>));
EXPECT_TRUE((traits::is_invocable_v<y::Obj, char const*>)); EXPECT_TRUE((traits::is_invocable_v<y::Obj, char const*>));
...@@ -162,7 +170,7 @@ TEST_F(InvokeTest, free_is_invocable) { ...@@ -162,7 +170,7 @@ TEST_F(InvokeTest, free_is_invocable) {
} }
TEST_F(InvokeTest, free_is_invocable_r) { TEST_F(InvokeTest, free_is_invocable_r) {
using traits = folly::invoke_traits<go_invoker>; using traits = folly::invoke_traits<decltype(invoker::go)>;
EXPECT_TRUE((traits::is_invocable_r_v<int, x::Obj, int>)); EXPECT_TRUE((traits::is_invocable_r_v<int, x::Obj, int>));
EXPECT_TRUE((traits::is_invocable_r_v<char, y::Obj, char const*>)); EXPECT_TRUE((traits::is_invocable_r_v<char, y::Obj, char const*>));
...@@ -171,7 +179,7 @@ TEST_F(InvokeTest, free_is_invocable_r) { ...@@ -171,7 +179,7 @@ TEST_F(InvokeTest, free_is_invocable_r) {
} }
TEST_F(InvokeTest, free_is_nothrow_invocable) { TEST_F(InvokeTest, free_is_nothrow_invocable) {
using traits = folly::invoke_traits<go_invoker>; using traits = folly::invoke_traits<decltype(invoker::go)>;
EXPECT_TRUE((traits::is_nothrow_invocable_v<x::Obj, int>)); EXPECT_TRUE((traits::is_nothrow_invocable_v<x::Obj, int>));
EXPECT_FALSE((traits::is_nothrow_invocable_v<y::Obj, char const*>)); EXPECT_FALSE((traits::is_nothrow_invocable_v<y::Obj, char const*>));
...@@ -180,7 +188,7 @@ TEST_F(InvokeTest, free_is_nothrow_invocable) { ...@@ -180,7 +188,7 @@ TEST_F(InvokeTest, free_is_nothrow_invocable) {
} }
TEST_F(InvokeTest, free_is_nothrow_invocable_r) { TEST_F(InvokeTest, free_is_nothrow_invocable_r) {
using traits = folly::invoke_traits<go_invoker>; using traits = folly::invoke_traits<decltype(invoker::go)>;
EXPECT_TRUE((traits::is_nothrow_invocable_r_v<int, x::Obj, int>)); 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*>)); EXPECT_FALSE((traits::is_nothrow_invocable_r_v<char, y::Obj, char const*>));
...@@ -189,7 +197,7 @@ TEST_F(InvokeTest, free_is_nothrow_invocable_r) { ...@@ -189,7 +197,7 @@ TEST_F(InvokeTest, free_is_nothrow_invocable_r) {
} }
TEST_F(InvokeTest, free_invoke_swap) { TEST_F(InvokeTest, free_invoke_swap) {
using traits = folly::invoke_traits<swap_invoker>; using traits = folly::invoke_traits<decltype(invoker::swap)>;
int a = 3; int a = 3;
int b = 4; int b = 4;
...@@ -214,7 +222,7 @@ TEST_F(InvokeTest, free_invoke_swap) { ...@@ -214,7 +222,7 @@ TEST_F(InvokeTest, free_invoke_swap) {
} }
TEST_F(InvokeTest, member_invoke) { TEST_F(InvokeTest, member_invoke) {
using traits = folly::invoke_traits<test_invoker>; using traits = folly::invoke_traits<decltype(invoker::test)>;
Obj fn; Obj fn;
...@@ -226,7 +234,7 @@ TEST_F(InvokeTest, member_invoke) { ...@@ -226,7 +234,7 @@ TEST_F(InvokeTest, member_invoke) {
} }
TEST_F(InvokeTest, member_invoke_result) { TEST_F(InvokeTest, member_invoke_result) {
using traits = folly::invoke_traits<test_invoker>; using traits = folly::invoke_traits<invoker::test_fn>;
EXPECT_TRUE( EXPECT_TRUE(
(std::is_same<char, traits::invoke_result_t<Obj, int, char>>::value)); (std::is_same<char, traits::invoke_result_t<Obj, int, char>>::value));
...@@ -236,7 +244,7 @@ TEST_F(InvokeTest, member_invoke_result) { ...@@ -236,7 +244,7 @@ TEST_F(InvokeTest, member_invoke_result) {
} }
TEST_F(InvokeTest, member_is_invocable) { TEST_F(InvokeTest, member_is_invocable) {
using traits = folly::invoke_traits<test_invoker>; using traits = folly::invoke_traits<decltype(invoker::test)>;
EXPECT_TRUE((traits::is_invocable_v<Obj, int, char>)); EXPECT_TRUE((traits::is_invocable_v<Obj, int, char>));
EXPECT_TRUE((traits::is_invocable_v<Obj, int, char*>)); EXPECT_TRUE((traits::is_invocable_v<Obj, int, char*>));
...@@ -244,7 +252,7 @@ TEST_F(InvokeTest, member_is_invocable) { ...@@ -244,7 +252,7 @@ TEST_F(InvokeTest, member_is_invocable) {
} }
TEST_F(InvokeTest, member_is_invocable_r) { TEST_F(InvokeTest, member_is_invocable_r) {
using traits = folly::invoke_traits<test_invoker>; using traits = folly::invoke_traits<decltype(invoker::test)>;
EXPECT_TRUE((traits::is_invocable_r_v<int, Obj, int, char>)); EXPECT_TRUE((traits::is_invocable_r_v<int, Obj, int, char>));
EXPECT_TRUE((traits::is_invocable_r_v<int, Obj, int, char*>)); EXPECT_TRUE((traits::is_invocable_r_v<int, Obj, int, char*>));
...@@ -252,7 +260,7 @@ TEST_F(InvokeTest, member_is_invocable_r) { ...@@ -252,7 +260,7 @@ TEST_F(InvokeTest, member_is_invocable_r) {
} }
TEST_F(InvokeTest, member_is_nothrow_invocable) { TEST_F(InvokeTest, member_is_nothrow_invocable) {
using traits = folly::invoke_traits<test_invoker>; using traits = folly::invoke_traits<decltype(invoker::test)>;
EXPECT_TRUE((traits::is_nothrow_invocable_v<Obj, int, char>)); EXPECT_TRUE((traits::is_nothrow_invocable_v<Obj, int, char>));
EXPECT_FALSE((traits::is_nothrow_invocable_v<Obj, int, char*>)); EXPECT_FALSE((traits::is_nothrow_invocable_v<Obj, int, char*>));
...@@ -260,14 +268,22 @@ TEST_F(InvokeTest, member_is_nothrow_invocable) { ...@@ -260,14 +268,22 @@ TEST_F(InvokeTest, member_is_nothrow_invocable) {
} }
TEST_F(InvokeTest, member_is_nothrow_invocable_r) { TEST_F(InvokeTest, member_is_nothrow_invocable_r) {
using traits = folly::invoke_traits<test_invoker>; using traits = folly::invoke_traits<decltype(invoker::test)>;
EXPECT_TRUE((traits::is_nothrow_invocable_r_v<int, Obj, int, char>)); EXPECT_TRUE((traits::is_nothrow_invocable_r_v<int, Obj, int, char>));
EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int, Obj, int, char*>)); EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int, Obj, int, char*>));
EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int, Obj, int>)); EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int, Obj, int>));
} }
FOLLY_CREATE_STATIC_MEMBER_INVOKER(stat_invoker, stat); namespace {
namespace invoker {
FOLLY_CREATE_STATIC_MEMBER_INVOKER_SUITE(stat);
}
} // namespace
TEST_F(InvokeTest, static_member_invoke) { TEST_F(InvokeTest, static_member_invoke) {
struct HasStat { struct HasStat {
...@@ -278,7 +294,7 @@ TEST_F(InvokeTest, static_member_invoke) { ...@@ -278,7 +294,7 @@ TEST_F(InvokeTest, static_member_invoke) {
} }
static float stat(float, float) { return 3.14; } static float stat(float, float) { return 3.14; }
}; };
using traits = folly::invoke_traits<stat_invoker<HasStat>>; using traits = folly::invoke_traits<decltype(invoker::stat<HasStat>)>;
EXPECT_TRUE((traits::is_invocable_v<int, char>)); EXPECT_TRUE((traits::is_invocable_v<int, char>));
EXPECT_TRUE((traits::is_invocable_v<int, char>)); EXPECT_TRUE((traits::is_invocable_v<int, char>));
...@@ -301,7 +317,7 @@ TEST_F(InvokeTest, static_member_invoke) { ...@@ -301,7 +317,7 @@ TEST_F(InvokeTest, static_member_invoke) {
TEST_F(InvokeTest, static_member_no_invoke) { TEST_F(InvokeTest, static_member_no_invoke) {
struct HasNoStat {}; struct HasNoStat {};
using traits = folly::invoke_traits<stat_invoker<HasNoStat>>; using traits = folly::invoke_traits<decltype(invoker::stat<HasNoStat>)>;
EXPECT_FALSE((traits::is_invocable_v<>)); EXPECT_FALSE((traits::is_invocable_v<>));
EXPECT_FALSE((traits::is_invocable_v<int>)); EXPECT_FALSE((traits::is_invocable_v<int>));
......
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