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> {
struct classname \
: 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
*
......@@ -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
*
......@@ -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 detail_tag_invoke_fn {
......
......@@ -35,7 +35,11 @@ struct Fn {
int volatile x_ = 17;
};
FOLLY_CREATE_MEMBER_INVOKER(test_invoker, test);
namespace invoker {
FOLLY_CREATE_MEMBER_INVOKER_SUITE(test);
}
struct Obj {
char test(int, int) noexcept { return 'a'; }
......@@ -78,9 +82,13 @@ namespace unswappable {
FOLLY_MAYBE_UNUSED AltSwappableRet swap(AltSwappable&, AltSwappable&);
} // namespace unswappable
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 invoker {
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
......@@ -132,7 +140,7 @@ TEST_F(InvokeTest, is_nothrow_invocable_r) {
}
TEST_F(InvokeTest, free_invoke) {
using traits = folly::invoke_traits<go_invoker>;
using traits = folly::invoke_traits<decltype(invoker::go)>;
x::Obj x_;
y::Obj y_;
......@@ -145,7 +153,7 @@ TEST_F(InvokeTest, free_invoke) {
}
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((
......@@ -153,7 +161,7 @@ TEST_F(InvokeTest, free_invoke_result) {
}
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<y::Obj, char const*>));
......@@ -162,7 +170,7 @@ TEST_F(InvokeTest, free_is_invocable) {
}
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<char, y::Obj, char const*>));
......@@ -171,7 +179,7 @@ TEST_F(InvokeTest, free_is_invocable_r) {
}
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_FALSE((traits::is_nothrow_invocable_v<y::Obj, char const*>));
......@@ -180,7 +188,7 @@ TEST_F(InvokeTest, free_is_nothrow_invocable) {
}
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_FALSE((traits::is_nothrow_invocable_r_v<char, y::Obj, char const*>));
......@@ -189,7 +197,7 @@ TEST_F(InvokeTest, free_is_nothrow_invocable_r) {
}
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 b = 4;
......@@ -214,7 +222,7 @@ TEST_F(InvokeTest, free_invoke_swap) {
}
TEST_F(InvokeTest, member_invoke) {
using traits = folly::invoke_traits<test_invoker>;
using traits = folly::invoke_traits<decltype(invoker::test)>;
Obj fn;
......@@ -226,7 +234,7 @@ TEST_F(InvokeTest, member_invoke) {
}
TEST_F(InvokeTest, member_invoke_result) {
using traits = folly::invoke_traits<test_invoker>;
using traits = folly::invoke_traits<invoker::test_fn>;
EXPECT_TRUE(
(std::is_same<char, traits::invoke_result_t<Obj, int, char>>::value));
......@@ -236,7 +244,7 @@ TEST_F(InvokeTest, member_invoke_result) {
}
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*>));
......@@ -244,7 +252,7 @@ TEST_F(InvokeTest, member_is_invocable) {
}
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*>));
......@@ -252,7 +260,7 @@ TEST_F(InvokeTest, member_is_invocable_r) {
}
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_FALSE((traits::is_nothrow_invocable_v<Obj, int, char*>));
......@@ -260,14 +268,22 @@ TEST_F(InvokeTest, member_is_nothrow_invocable) {
}
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_FALSE((traits::is_nothrow_invocable_r_v<int, Obj, int, char*>));
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) {
struct HasStat {
......@@ -278,7 +294,7 @@ TEST_F(InvokeTest, static_member_invoke) {
}
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>));
......@@ -301,7 +317,7 @@ TEST_F(InvokeTest, static_member_invoke) {
TEST_F(InvokeTest, static_member_no_invoke) {
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<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