Commit 6bc74fbd authored by Michael Park's avatar Michael Park Committed by Facebook GitHub Bot

Fix eagerness bug in FOLLY_CREATE_STATIC_MEMBER_INVOKER

Summary:
This patch performs SFINAE-friendly invocation in `FOLLY_CREATE_STATIC_MEMBER_INVOKER` in order for invocability tests to return `false` in the situation where the member is not even available. For example, given:
```
FOLLY_CREATE_STATIC_MEMBER_INVOKER(foo_invoker, foo);
```
With this diff, something like `std::is_invocable_v<foo_invoker, HasNoFoo>` yields `false` rather than a compilation error.
This brings `FOLLY_CREATE_STATIC_MEMBER_INVOKER` in line with `FOLLY_CREATE_FREE_INVOKER` and `FOLLY_CREATE_MEMBER_INVOKER`.

Reviewed By: yfeldblum

Differential Revision: D25878262

fbshipit-source-id: 150ae6b2c71941317bc02de20720fed014639bf5
parent 69ab6ff9
...@@ -476,11 +476,11 @@ struct invoke_traits : detail::invoke_traits_base<I> { ...@@ -476,11 +476,11 @@ struct invoke_traits : detail::invoke_traits_base<I> {
#define FOLLY_CREATE_STATIC_MEMBER_INVOKER(classname, membername) \ #define FOLLY_CREATE_STATIC_MEMBER_INVOKER(classname, membername) \
template <typename T> \ template <typename T> \
struct classname { \ struct classname { \
template <typename... Args> \ template <typename... Args, typename U = T> \
FOLLY_MAYBE_UNUSED FOLLY_ERASE constexpr auto operator()(Args&&... args) \ FOLLY_MAYBE_UNUSED FOLLY_ERASE constexpr auto operator()(Args&&... args) \
const noexcept(noexcept(T::membername(static_cast<Args&&>(args)...))) \ const noexcept(noexcept(U::membername(static_cast<Args&&>(args)...))) \
-> decltype(T::membername(static_cast<Args&&>(args)...)) { \ -> decltype(U::membername(static_cast<Args&&>(args)...)) { \
return T::membername(static_cast<Args&&>(args)...); \ return U::membername(static_cast<Args&&>(args)...); \
} \ } \
} }
......
...@@ -298,6 +298,24 @@ TEST_F(InvokeTest, static_member_invoke) { ...@@ -298,6 +298,24 @@ TEST_F(InvokeTest, static_member_invoke) {
EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int, int>)); EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int, int>));
} }
TEST_F(InvokeTest, static_member_no_invoke) {
struct HasNoStat {};
using traits = folly::invoke_traits<stat_invoker<HasNoStat>>;
EXPECT_FALSE((traits::is_invocable_v<>));
EXPECT_FALSE((traits::is_invocable_v<int>));
EXPECT_FALSE((traits::is_invocable_r_v<int>));
EXPECT_FALSE((traits::is_invocable_r_v<int, int>));
EXPECT_FALSE((traits::is_nothrow_invocable_v<>));
EXPECT_FALSE((traits::is_nothrow_invocable_v<int>));
EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int>));
EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int, int>));
}
namespace { namespace {
struct TestCustomisationPointFn { struct TestCustomisationPointFn {
......
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