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

FOLLY_CREATE_STATIC_MEMBER_INVOKER

Summary: [Folly] `FOLLY_CREATE_STATIC_MEMBER_INVOKER`, for creating invoker types which can invoke class static members.

Reviewed By: vitaut

Differential Revision: D18035183

fbshipit-source-id: 2bcab988f684042b26843d5fe0a13ad7c549e43a
parent a0776ffe
......@@ -424,3 +424,55 @@ struct invoke_traits : detail::invoke_traits_base<Invoke> {
return static_cast<O&&>(o).membername(static_cast<Args&&>(args)...); \
} \
}
/***
* FOLLY_CREATE_STATIC_MEMBER_INVOKER
*
* Used to create an invoker type template bound to a specific static-member-
* invocable name.
*
* Example:
*
* FOLLY_CREATE_STATIC_MEMBER_INVOKER(foo_invoker, foo);
*
* The type template `foo_invoker` is generated in the current namespace and
* may be used as follows:
*
* struct CanFoo {
* static int foo(Bar&) { return 1; }
* static int foo(Car&&) noexcept { return 2; }
* };
*
* using traits = folly::invoke_traits<foo_invoker<CanFoo>>;
*
* traits::invoke(Car{}) // 2
*
* traits::invoke_result<Bar&> // has member
* traits::invoke_result_t<Bar&> // int
* traits::invoke_result<Bar&&> // empty
* traits::invoke_result_t<Bar&&> // error
*
* traits::is_invocable_v<Bar&> // true
* traits::is_invocable_v<Bar&&> // false
*
* traits::is_invocable_r_v<int, Bar&> // true
* traits::is_invocable_r_v<char*, Bar&> // false
*
* traits::is_nothrow_invocable_v<Bar&> // false
* traits::is_nothrow_invocable_v<Car&&> // true
*
* traits::is_nothrow_invocable_v<int, Bar&> // false
* traits::is_nothrow_invocable_v<char*, Bar&> // false
* traits::is_nothrow_invocable_v<int, Car&&> // true
* traits::is_nothrow_invocable_v<char*, Car&&> // false
*/
#define FOLLY_CREATE_STATIC_MEMBER_INVOKER(classname, membername) \
template <typename T> \
struct classname { \
template <typename... Args> \
FOLLY_ERASE constexpr auto operator()(Args&&... args) const \
noexcept(noexcept(T::membername(static_cast<Args&&>(args)...))) \
-> decltype(T::membername(static_cast<Args&&>(args)...)) { \
return T::membername(static_cast<Args&&>(args)...); \
} \
}
......@@ -278,3 +278,38 @@ TEST_F(InvokeTest, member_is_nothrow_invocable_r) {
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);
TEST_F(InvokeTest, static_member_invoke) {
struct HasStat {
static char stat(int, int) noexcept {
return 'a';
}
static int volatile&& stat(int, char const*) {
static int volatile x_ = 17;
return std::move(x_);
}
static float stat(float, float) {
return 3.14;
}
};
using traits = folly::invoke_traits<stat_invoker<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_FALSE((traits::is_invocable_v<int>));
EXPECT_TRUE((traits::is_invocable_r_v<int, int, char>));
EXPECT_TRUE((traits::is_invocable_r_v<int, int, char*>));
EXPECT_FALSE((traits::is_invocable_r_v<int, int>));
EXPECT_TRUE((traits::is_nothrow_invocable_v<int, char>));
EXPECT_FALSE((traits::is_nothrow_invocable_v<int, char*>));
EXPECT_FALSE((traits::is_nothrow_invocable_v<int>));
EXPECT_TRUE((traits::is_nothrow_invocable_r_v<int, int, char>));
EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int, int, char*>));
EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int, 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