Commit 9b876d88 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

FOLLY_INVOKE_MEMBER

Summary: A lambda-expression parallel to `FOLLY_CREATE_MEMBER_INVOKER_SUITE`.

Reviewed By: Gownta

Differential Revision: D32601861

fbshipit-source-id: 8bb5876d800215346b19c42090a1cc13b6aa9042
parent 3fac996e
...@@ -541,6 +541,19 @@ constexpr auto kCpplibVer = 0; ...@@ -541,6 +541,19 @@ constexpr auto kCpplibVer = 0;
#define FOLLY_STORAGE_CONSTEXPR constexpr #define FOLLY_STORAGE_CONSTEXPR constexpr
#endif #endif
// FOLLY_LAMBDA_CONSTEXPR
//
// C++17 permits a lambda to be marked constexpr.
//
// Example:
//
// []() FOLLY_LAMBDA_CONSTEXPR { /* ... */ }
#if FOLLY_CPLUSPLUS >= 201703L
#define FOLLY_LAMBDA_CONSTEXPR constexpr
#else
#define FOLLY_LAMBDA_CONSTEXPR
#endif
#if __cplusplus >= 201703L #if __cplusplus >= 201703L
// folly::coro requires C++17 support // folly::coro requires C++17 support
#if defined(_WIN32) && defined(__clang__) && !defined(LLVM_COROUTINES) #if defined(_WIN32) && defined(__clang__) && !defined(LLVM_COROUTINES)
......
...@@ -32,6 +32,10 @@ ...@@ -32,6 +32,10 @@
#include <folly/Utility.h> #include <folly/Utility.h>
#include <folly/lang/CustomizationPoint.h> #include <folly/lang/CustomizationPoint.h>
#define FOLLY_DETAIL_FORWARD_REF(a) static_cast<decltype(a)&&>(a)
#define FOLLY_DETAIL_FORWARD_BODY(e) \
noexcept(noexcept(e))->decltype(e) { return e; }
/** /**
* include or backport: * include or backport:
* * std::invoke * * std::invoke
...@@ -461,6 +465,36 @@ struct invoke_traits : detail::invoke_traits_base<I> { ...@@ -461,6 +465,36 @@ struct invoke_traits : detail::invoke_traits_base<I> {
FOLLY_MAYBE_UNUSED FOLLY_INLINE_VARIABLE constexpr membername##_fn \ FOLLY_MAYBE_UNUSED FOLLY_INLINE_VARIABLE constexpr membername##_fn \
membername {} membername {}
/***
* FOLLY_INVOKE_MEMBER
*
* An invoker expression resulting in an invocable which, when invoked, invokes
* the member on the object with the given arguments.
*
* Example:
*
* FOLLY_INVOKE_MEMBER(find)(map, key)
*
* Equivalent to:
*
* map.find(key)
*
* But also equivalent to:
*
* std::invoke(FOLLY_INVOKE_MEMBER(find), map, key)
*
* As an implementation detail, the resulting callable is a lambda. This has
* two observable consequences.
* * Since C++17 only, lambda invocations may be marked constexpr.
* * Since C++20 only, lambda definitions may appear in an unevaluated context,
* namely, in an operand to decltype, noexcept, sizeof, or typeid.
*/
#define FOLLY_INVOKE_MEMBER(membername) \
[](auto&& __folly_param_o, auto&&... __folly_param_a) \
FOLLY_LAMBDA_CONSTEXPR FOLLY_DETAIL_FORWARD_BODY( \
FOLLY_DETAIL_FORWARD_REF(__folly_param_o) \
.membername(FOLLY_DETAIL_FORWARD_REF(__folly_param_a)...))
/*** /***
* FOLLY_CREATE_STATIC_MEMBER_INVOKER * FOLLY_CREATE_STATIC_MEMBER_INVOKER
* *
......
...@@ -275,6 +275,18 @@ TEST_F(InvokeTest, member_is_nothrow_invocable_r) { ...@@ -275,6 +275,18 @@ TEST_F(InvokeTest, member_is_nothrow_invocable_r) {
EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int, Obj, int>)); EXPECT_FALSE((traits::is_nothrow_invocable_r_v<int, Obj, int>));
} }
TEST_F(InvokeTest, invoke_member) {
auto test = FOLLY_INVOKE_MEMBER(test);
Obj fn;
EXPECT_TRUE(noexcept(test(fn, 1, 2)));
EXPECT_FALSE(noexcept(test(fn, 1, "2")));
EXPECT_EQ('a', test(fn, 1, 2));
EXPECT_EQ(17, test(fn, 1, "2"));
}
namespace { namespace {
namespace invoker { namespace invoker {
......
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