From 1a50cb78590fabf164630808f1be23a9bef6bcc7 Mon Sep 17 00:00:00 2001 From: Yedidya Feldblum Date: Mon, 1 Jan 2018 17:05:00 -0800 Subject: [PATCH] invoke and member-invoke tweaks Summary: [Folly] `invoke` and member-`invoke` tweaks. * Direct `static_cast` v.s. `std::forward` is okay. * Implement member-`invoke` in terms of `invoke` and extract most of it to a helper type, minimizing the code directly generated by the preprocessor. Reviewed By: spalamarchuk Differential Revision: D6644119 fbshipit-source-id: e58a83d7ff2dd71b0377d864ef089c34e0239c8d --- folly/functional/Invoke.h | 130 ++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 74 deletions(-) diff --git a/folly/functional/Invoke.h b/folly/functional/Invoke.h index 6dce01c0..850c059a 100644 --- a/folly/functional/Invoke.h +++ b/folly/functional/Invoke.h @@ -47,14 +47,14 @@ namespace folly { // mimic: std::invoke, C++17 template constexpr auto invoke(F&& f, Args&&... args) noexcept( - noexcept(std::forward(f)(std::forward(args)...))) - -> decltype(std::forward(f)(std::forward(args)...)) { - return std::forward(f)(std::forward(args)...); + noexcept(static_cast(f)(static_cast(args)...))) + -> decltype(static_cast(f)(static_cast(args)...)) { + return static_cast(f)(static_cast(args)...); } template constexpr auto invoke(M(C::*d), Args&&... args) - -> decltype(std::mem_fn(d)(std::forward(args)...)) { - return std::mem_fn(d)(std::forward(args)...); + -> decltype(std::mem_fn(d)(static_cast(args)...)) { + return std::mem_fn(d)(static_cast(args)...); } } // namespace folly @@ -162,6 +162,45 @@ struct is_nothrow_invocable_r #endif +namespace folly { +namespace detail { + +template +struct member_invoke_proxy { + public: + template + struct invoke_result : folly::invoke_result {}; + template + using invoke_result_t = folly::invoke_result_t; + template + struct is_invocable : folly::is_invocable {}; + template + struct is_invocable_r : folly::is_invocable_r {}; + template + struct is_nothrow_invocable + : folly::is_nothrow_invocable {}; + template + struct is_nothrow_invocable_r + : folly::is_nothrow_invocable_r {}; + + template + static constexpr auto invoke(O&& o, Args&&... args) noexcept( + noexcept(folly::invoke( + Invoke{}, + static_cast(o), + static_cast(args)...))) + -> decltype(folly::invoke( + Invoke{}, + static_cast(o), + static_cast(args)...)) { + return folly::invoke( + Invoke{}, static_cast(o), static_cast(args)...); + } +}; + +} // namespace detail +} // namespace folly + /*** * FOLLY_CREATE_MEMBER_INVOKE_TRAITS * @@ -219,72 +258,15 @@ struct is_nothrow_invocable_r * traits::is_nothrow_invocable::value // true * traits::is_nothrow_invocable::value // false */ -#define FOLLY_CREATE_MEMBER_INVOKE_TRAITS(classname, membername) \ - struct classname { \ - private: \ - template \ - using v_ = ::folly::void_t; \ - template \ - using result_ = \ - decltype(::std::declval().membername(::std::declval()...)); \ - template \ - struct nothrow_ : std::integral_constant< \ - bool, \ - noexcept(::std::declval().membername( \ - ::std::declval()...))> {}; \ - \ - template \ - struct invoke_result_ {}; \ - template \ - struct invoke_result_>, F, Args...> { \ - using type = result_; \ - }; \ - \ - template \ - struct is_invocable_ : ::std::false_type {}; \ - template \ - struct is_invocable_>, F, Args...> \ - : ::std::true_type {}; \ - \ - template \ - struct is_invocable_r_ : ::std::false_type {}; \ - template \ - struct is_invocable_r_>, R, F, Args...> \ - : ::std::is_convertible, R> {}; \ - \ - template \ - struct is_nothrow_invocable_ : ::std::false_type {}; \ - template \ - struct is_nothrow_invocable_>, F, Args...> \ - : nothrow_ {}; \ - \ - template \ - struct is_nothrow_invocable_r_ : ::std::false_type {}; \ - template \ - struct is_nothrow_invocable_r_>, R, F, Args...> \ - : ::folly::StrictConjunction< \ - ::std::is_convertible, R>, \ - nothrow_> {}; \ - \ - public: \ - template \ - struct invoke_result : invoke_result_ {}; \ - template \ - using invoke_result_t = typename invoke_result::type; \ - template \ - struct is_invocable : is_invocable_ {}; \ - template \ - struct is_invocable_r : is_invocable_r_ {}; \ - template \ - struct is_nothrow_invocable : is_nothrow_invocable_ {}; \ - template \ - struct is_nothrow_invocable_r \ - : is_nothrow_invocable_r_ {}; \ - \ - template \ - static constexpr result_ invoke( \ - F&& f, \ - Args&&... args) noexcept(nothrow_::value) { \ - return std::forward(f).membername(std::forward(args)...); \ - } \ - } +#define FOLLY_CREATE_MEMBER_INVOKE_TRAITS(classname, membername) \ + struct classname##__folly_detail_member_invoke { \ + template \ + constexpr auto operator()(O&& o, Args&&... args) noexcept(noexcept( \ + static_cast(o).membername(static_cast(args)...))) \ + -> decltype( \ + static_cast(o).membername(static_cast(args)...)) { \ + return static_cast(o).membername(static_cast(args)...); \ + } \ + }; \ + struct classname : ::folly::detail::member_invoke_proxy< \ + classname##__folly_detail_member_invoke> {} -- 2.34.1