std::result_of, std::invoke_result_C++中文网
class result_of; // 不定义
template< class F, class... ArgTypes >
class result_of<F(ArgTypes...)>;
namespace detail { template <class T> struct is_reference_wrapper : std::false_type {}; template <class U> struct is_reference_wrapper<std::reference_wrapper<U>> : std::true_type {}; template <class Base, class T, class Derived, class... Args> auto INVOKE(T Base::*pmf, Derived&& ref, Args&&... args) -> typename std::enable_if<std::is_function<T>::value && std::is_base_of<Base, typename std::decay<Derived>::type>::value, decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...))>::type; template <class Base, class T, class RefWrap, class... Args> auto INVOKE(T Base::*pmf, RefWrap&& ref, Args&&... args) -> typename std::enable_if<std::is_function<T>::value && is_reference_wrapper<typename std::decay<RefWrap>::type>::value, decltype((ref.get().*pmf)(std::forward<Args>(args)...))>::type; template <class Base, class T, class Pointer, class... Args> auto INVOKE(T Base::*pmf, Pointer&& ptr, Args&&... args) -> typename std::enable_if<std::is_function<T>::value && !is_reference_wrapper<typename std::decay<Pointer>::type>::value && !std::is_base_of<Base, typename std::decay<Pointer>::type>::value, decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...))>::type; template <class Base, class T, class Derived> auto INVOKE(T Base::*pmd, Derived&& ref) -> typename std::enable_if<!std::is_function<T>::value && std::is_base_of<Base, typename std::decay<Derived>::type>::value, decltype(std::forward<Derived>(ref).*pmd)>::type; template <class Base, class T, class RefWrap> auto INVOKE(T Base::*pmd, RefWrap&& ref) -> typename std::enable_if<!std::is_function<T>::value && is_reference_wrapper<typename std::decay<RefWrap>::type>::value, decltype(ref.get().*pmd)>::type; template <class Base, class T, class Pointer> auto INVOKE(T Base::*pmd, Pointer&& ptr) -> typename std::enable_if<!std::is_function<T>::value && !is_reference_wrapper<typename std::decay<Pointer>::type>::value && !std::is_base_of<Base, typename std::decay<Pointer>::type>::value, decltype((*std::forward<Pointer>(ptr)).*pmd)>::type; template <class F, class... Args> auto INVOKE(F&& f, Args&&... args) -> typename std::enable_if<!std::is_member_pointer<typename std::decay<F>::type>::value, decltype(std::forward<F>(f)(std::forward<Args>(args)...))>::type; } // namespace detail // 最小 C++11 实现: template <class> struct result_of; template <class F, class... ArgTypes> struct result_of<F(ArgTypes...)> { using type = decltype(detail::INVOKE(std::declval<F>(), std::declval<ArgTypes>()...)); }; // 符合 C++14 的实现(亦为合法的 C++11 实现): namespace detail { template <typename AlwaysVoid, typename, typename...> struct invoke_result { }; template <typename F, typename...Args> struct invoke_result<decltype(void(detail::INVOKE(std::declval<F>(), std::declval<Args>()...))), F, Args...> { using type = decltype(detail::INVOKE(std::declval<F>(), std::declval<Args>()...)); }; } // namespace detail template <class> struct result_of; template <class F, class... ArgTypes> struct result_of<F(ArgTypes...)> : detail::invoke_result<void, F, ArgTypes...> {}; template <class F, class... ArgTypes> struct invoke_result : detail::invoke_result<void, F, ArgTypes...> {};
在 C++11 中规范时, std::result_of 的行为在 INVOKE(std::declval<F>(), std::declval<ArgTypes>()...) 为病式时(例如 F 完全不可调用时)未定义。 C++14 更改为 SFINAE ( F 不可调用时, std::result_of<F(ArgTypes...)> 简单地无 type 成员)。
F(Args...) 是以 Args... 为参数而以 F 为返回类型的函数类型。因而, std::result_of 承受了许多怪异,导致它在 C++17 中被 std::invoke_result 取代而被弃用:
为避免这些怪异,常以 F 和 Args... 的引用类型使用 result_of 。例如: