# std::invoke

From cppreference.com
< cpp‎ | utility‎ | functional

Defined in header `<functional>` |  |
template< class F, class... Args> std::invoke_result_t<F, Args...> invoke(F&& f, Args&&... args) noexcept(/* see below */); |  | (since C++17)

Invoke the `Callable` object `f` with the parameters `args`. As by INVOKE(std::forward<F>(f), std::forward<Args>(args)...).

where INVOKE(f, t1, t2, ..., tN) is defined as follows:

- if `f` is a pointer to member function of class `T`:

  - If std::is_base_of<T, std::decay_t<decltype(t1)>>::value is true, then INVOKE(f, t1, t2, ..., tN) is equivalent to (t1.*f)(t2, ..., tN)
  - otherwise, if std::decay_t<decltype(t1)> is a specialization of std::reference_wrapper, then INVOKE(f, t1, t2, ..., tN) is equivalent to (t1.get().*f)(t2, ..., tN)
  - otherwise, if `t1` does not satisfy the previous items, then INVOKE(f, t1, t2, ..., tN) is equivalent to ((*t1).*f)(t2, ..., tN).

- otherwise, if N == 1 and `f` is a pointer to data member of class `T`:

  - If std::is_base_of<T, std::decay_t<decltype(t1)>>::value is true, then INVOKE(f, t1) is equivalent to t1.*f
  - otherwise, if std::decay_t<decltype(t1)> is a specialization of std::reference_wrapper, then INVOKE(f, t1) is equivalent to t1.get().*f
  - otherwise, if `t1` does not satisfy the previous items, then INVOKE(f, t1) is equivalent to (*t1).*f

- otherwise, INVOKE(f, t1, t2, ..., tN) is equivalent to f(t1, t2, ..., tN) (that is, `f` is a `FunctionObject`)

### Parameters

f | - | `Callable` object to be invoked
args | - | arguments to pass to `f`

### Exceptions

`noexcept` specification:
noexcept(std::is_nothrow_invocable_v<F, Args...>)

### Possible implementation

    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 T>
    constexpr bool is_reference_wrapper_v = is_reference_wrapper<T>::value;

    template <class Base, class T, class Derived, class... Args>
    auto INVOKE(T Base::*pmf, Derived&& ref, Args&&... args)
        noexcept(noexcept((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...)))
     -> std::enable_if_t<std::is_function_v<T> &&
                         std::is_base_of_v<Base, std::decay_t<Derived>>,
        decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...))>
    {
          return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...);
    }

    template <class Base, class T, class RefWrap, class... Args>
    auto INVOKE(T Base::*pmf, RefWrap&& ref, Args&&... args)
        noexcept(noexcept((ref.get().*pmf)(std::forward<Args>(args)...)))
     -> std::enable_if_t<std::is_function_v<T> &&
                         is_reference_wrapper_v<std::decay_t<RefWrap>>,
        decltype((ref.get().*pmf)(std::forward<Args>(args)...))>

    {
          return (ref.get().*pmf)(std::forward<Args>(args)...);
    }

    template <class Base, class T, class Pointer, class... Args>
    auto INVOKE(T Base::*pmf, Pointer&& ptr, Args&&... args)
        noexcept(noexcept(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...)))
     -> std::enable_if_t<std::is_function_v<T> &&
                         !is_reference_wrapper_v<std::decay_t<Pointer>> &&
                         !std::is_base_of_v<Base, std::decay_t<Pointer>>,
        decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...))>
    {
          return ((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...);
    }

    template <class Base, class T, class Derived>
    auto INVOKE(T Base::*pmd, Derived&& ref)
        noexcept(noexcept(std::forward<Derived>(ref).*pmd))
     -> std::enable_if_t<!std::is_function_v<T> &&
                         std::is_base_of_v<Base, std::decay_t<Derived>>,
        decltype(std::forward<Derived>(ref).*pmd)>
    {
          return std::forward<Derived>(ref).*pmd;
    }

    template <class Base, class T, class RefWrap>
    auto INVOKE(T Base::*pmd, RefWrap&& ref)
        noexcept(noexcept(ref.get().*pmd))
     -> std::enable_if_t<!std::is_function_v<T> &&
                         is_reference_wrapper_v<std::decay_t<RefWrap>>,
        decltype(ref.get().*pmd)>
    {
          return ref.get().*pmd;
    }

    template <class Base, class T, class Pointer>
    auto INVOKE(T Base::*pmd, Pointer&& ptr)
        noexcept(noexcept((*std::forward<Pointer>(ptr)).*pmd))
     -> std::enable_if_t<!std::is_function_v<T> &&
                         !is_reference_wrapper_v<std::decay_t<Pointer>> &&
                         !std::is_base_of_v<Base, std::decay_t<Pointer>>,
        decltype((*std::forward<Pointer>(ptr)).*pmd)>
    {
          return (*std::forward<Pointer>(ptr)).*pmd;
    }

    template <class F, class... Args>
    auto INVOKE(F&& f, Args&&... args)
        noexcept(noexcept(std::forward<F>(f)(std::forward<Args>(args)...)))
     -> std::enable_if_t<!std::is_member_pointer_v<std::decay_t<F>>,
        decltype(std::forward<F>(f)(std::forward<Args>(args)...))>
    {
          return std::forward<F>(f)(std::forward<Args>(args)...);
    }
    } // namespace detail

    template< class F, class... ArgTypes >
    auto invoke(F&& f, ArgTypes&&... args)
        // exception specification for QoI
        noexcept(noexcept(detail::INVOKE(std::forward<F>(f), std::forward<ArgTypes>(args)...)))
     -> decltype(detail::INVOKE(std::forward<F>(f), std::forward<ArgTypes>(args)...))
    {
        return detail::INVOKE(std::forward<F>(f), std::forward<ArgTypes>(args)...);
    }

### Example

Implement the basic functionality of std::mem_fn.

Run this code

    #include <functional>
    template< class PM >
    class mem_fn_t {
        PM p;
    public:
        mem_fn_t(PM p):p(p){}
        template<class... Args>
        decltype(auto) operator()(Args&&... args) {
            return std::invoke(p, std::forward<Args>(args)...);
        }
    };

    template< class R, class T >
    auto mem_fn(R T::* pm){
        mem_fn_t<R T::*> t {pm};
        return t;
    }

### See also

mem_fn (C++11) | creates a function object out of a pointer to a member (function template)
result_of invoke_result (C++11)(deprecated in C++17)(C++17) | deduces the result type of invoking a callable object with a set of arguments (class 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)
apply (C++17) | calls a function with a tuple of arguments (function template)

Retrieved from "http://en.cppreference.com/mwiki/index.php?title=cpp/utility/functional/invoke&oldid=92023"
Category:

- conditionally noexcept