# std::result_of, std::invoke_result

From cppreference.com
< cpp‎ | types

Defined in header `<type_traits>` |  |
template< class > class result_of; // not defined template< class F, class... ArgTypes > class result_of<F(ArgTypes...)>; | (1) | (since C++11) (deprecated in C++17)
template< class F, class... ArgTypes> class invoke_result; | (2) | (since C++17)

Deduces the return type of an INVOKE expression at compile time.

`F` must be a callable type, reference to function, or reference to callable type. Invoking `F` with `ArgTypes...` must be a well-formed expression | (since C++11)
`F` and all types in `ArgTypes` can be any complete type, array of unknown bound, or (possibly cv-qualified) `void` | (since C++14)

### Member types

Member type | Definition
`type` | the return type of the `Callable` type `F` if invoked with the arguments `ArgTypes...`. Only defined if F can be called with the arguments ArgTypes... in unevaluated context. (since C++14)

### Helper types

template< class T > using result_of_t = typename result_of<T>::type; | (1) | (since C++14) (deprecated in C++17)
template< class F, class... ArgTypes> using invoke_result_t = typename invoke_result<F, ArgTypes...>::type; | (2) | (since C++17)

### Possible implementation

    namespace detail {
    template <class F, class... Args>
    inline auto INVOKE(F&& f, Args&&... args) ->
        decltype(forward<F>(f)(forward<Args>(args)...)) {
          return forward<F>(f)(forward<Args>(args)...);
    }

    template <class Base, class T, class Derived>
    inline auto INVOKE(T Base::*pmd, Derived&& ref) ->
        decltype(forward<Derived>(ref).*pmd) {
          return forward<Derived>(ref).*pmd;
    }

    template <class PMD, class Pointer>
    inline auto INVOKE(PMD&& pmd, Pointer&& ptr) ->
        decltype((*forward<Pointer>(ptr)).*forward<PMD>(pmd)) {
          return (*forward<Pointer>(ptr)).*forward<PMD>(pmd);
    }

    template <class Base, class T, class Derived, class... Args>
    inline auto INVOKE(T Base::*pmf, Derived&& ref, Args&&... args) ->
        decltype((forward<Derived>(ref).*pmf)(forward<Args>(args)...)) {
          return (forward<Derived>(ref).*pmf)(forward<Args>(args)...);
    }

    template <class PMF, class Pointer, class... Args>
    inline auto INVOKE(PMF&& pmf, Pointer&& ptr, Args&&... args) ->
        decltype(((*forward<Pointer>(ptr)).*forward<PMF>(pmf))(forward<Args>(args)...)) {
          return ((*forward<Pointer>(ptr)).*forward<PMF>(pmf))(forward<Args>(args)...);
    }
    } // namespace detail

    // Minimal C++11 implementation:
    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>()...));
    };

    // Conforming C++14 implementation (is also a valid C++11 implementation):
    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...> {};

### Notes

As formulated in C++11, the behavior of `std::result_of` is undefined when `INVOKE(std::declval<F>(), std::declval<ArgTypes>()...)` is ill-formed (e.g. when F is not a callable type at all). C++14 changes that to a SFINAE (when F is not callable, `std::result_of<F(ArgTypes...)>` simply doesn't have the `type` member).

The motivation behind `std::result_of` is to determine the result of invoking a `Callable`, in particular if that result type is different for different sets of arguments.

F(Args...) is a function type with `Args...` being the argument types and `F` being the return type. As such, `F` cannot be a function type (but can be a reference to a function type).

### Examples

Run this code

    #include <type_traits>
    #include <iostream>

    struct S {
        double operator()(char, int&);
        float operator()(int) { return 1.0;}
    };

    template<class T>
    typename std::result_of<T(int)>::type f(T& t)
    {
        std::cout << "overload of f for callable T\n";
        return t(0);
    }

    template<class T, class U>
    int f(U u)
    {
        std::cout << "overload of f for non-callable T\n";
        return u;
    }

    int main()
    {
        // the result of invoking S with char and int& arguments is double
        std::result_of<S(char, int&)>::type d = 3.14; // d has type double
        static_assert(std::is_same<decltype(d), double>::value, "");

        // the result of invoking S with int argument is float
        std::result_of<S(int)>::type x = 3.14; // x has type float
        static_assert(std::is_same<decltype(x), float>::value, "");

        // result_of can be used with a pointer to member function as follows
        struct C { double Func(char, int&); };
        std::result_of<decltype(&C::Func)(C, char, int&)>::type g = 3.14;
        static_assert(std::is_same<decltype(g), double>::value, "");

        f<C>(1); // may fail to compile in C++11; calls the non-callable overload in C++14
    }

Output:

    overload of f for non-callable T

### See also

invoke (C++17) | invokes any `Callable` object with given arguments (function template)
is_invocable is_invocable_r is_nothrow_invocable is_nothrow_invocable_r (C++17) | checks if a type can be invoked (as if by std::invoke) with the given argument types (class template)
declval (C++11) | obtains a reference to its argument for use in unevaluated context (function template)

Retrieved from "http://en.cppreference.com/mwiki/index.php?title=cpp/types/result_of&oldid=90847"