-#define FOLLY_CREATE_MEMBER_INVOKE_TRAITS(classname, membername) \
- struct classname { \
- private: \
- template <typename T> \
- using v_ = ::folly::void_t<T>; \
- template <typename F, typename... Args> \
- using result_ = \
- decltype(::std::declval<F>().membername(::std::declval<Args>()...)); \
- template <typename F, typename... Args> \
- struct nothrow_ : std::integral_constant< \
- bool, \
- noexcept(::std::declval<F>().membername( \
- ::std::declval<Args>()...))> {}; \
- \
- template <typename, typename F, typename... Args> \
- struct invoke_result_ {}; \
- template <typename F, typename... Args> \
- struct invoke_result_<v_<result_<F, Args...>>, F, Args...> { \
- using type = result_<F, Args...>; \
- }; \
- \
- template <typename, typename F, typename... Args> \
- struct is_invocable_ : ::std::false_type {}; \
- template <typename F, typename... Args> \
- struct is_invocable_<v_<result_<F, Args...>>, F, Args...> \
- : ::std::true_type {}; \
- \
- template <typename, typename R, typename F, typename... Args> \
- struct is_invocable_r_ : ::std::false_type {}; \
- template <typename R, typename F, typename... Args> \
- struct is_invocable_r_<v_<result_<F, Args...>>, R, F, Args...> \
- : ::std::is_convertible<result_<F, Args...>, R> {}; \
- \
- template <typename, typename F, typename... Args> \
- struct is_nothrow_invocable_ : ::std::false_type {}; \
- template <typename F, typename... Args> \
- struct is_nothrow_invocable_<v_<result_<F, Args...>>, F, Args...> \
- : nothrow_<F, Args...> {}; \
- \
- template <typename, typename R, typename F, typename... Args> \
- struct is_nothrow_invocable_r_ : ::std::false_type {}; \
- template <typename R, typename F, typename... Args> \
- struct is_nothrow_invocable_r_<v_<result_<F, Args...>>, R, F, Args...> \
- : ::folly::StrictConjunction< \
- ::std::is_convertible<result_<F, Args...>, R>, \
- nothrow_<F, Args...>> {}; \
- \
- public: \
- template <typename F, typename... Args> \
- struct invoke_result : invoke_result_<void, F, Args...> {}; \
- template <typename F, typename... Args> \
- using invoke_result_t = typename invoke_result<F, Args...>::type; \
- template <typename F, typename... Args> \
- struct is_invocable : is_invocable_<void, F, Args...> {}; \
- template <typename R, typename F, typename... Args> \
- struct is_invocable_r : is_invocable_r_<void, R, F, Args...> {}; \
- template <typename F, typename... Args> \
- struct is_nothrow_invocable : is_nothrow_invocable_<void, F, Args...> {}; \
- template <typename R, typename F, typename... Args> \
- struct is_nothrow_invocable_r \
- : is_nothrow_invocable_r_<void, R, F, Args...> {}; \
- \
- template <typename F, typename... Args> \
- static constexpr result_<F, Args...> invoke( \
- F&& f, \
- Args&&... args) noexcept(nothrow_<F, Args...>::value) { \
- return std::forward<F>(f).membername(std::forward<Args>(args)...); \
- } \
- }