Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why use invoke helper rather than just call functor?

Tags:

c++

c++17

functor

As shown in the 'possible implementation' of std::apply we see that the standard library function std::invoke is used to invoke the callable object F.

Is it needed in this situation? if so, for what reason?

What are the benefits of writing:

template<typename F, typename ... Args>
decltype(auto) func(F &&f, Args &&... args){
    return std::invoke(std::forward<F>(f), std::forward<Args>(args)...);
}

over:

template<typename F, typename ... Args>
decltype(auto) func(F &&f, Args &&... args){
    return std::forward<F>(f)(std::forward<Args>(args)...);
}

?

like image 594
RamblingMad Avatar asked Aug 05 '15 16:08

RamblingMad


2 Answers

A pointer to member is Callable, and invoke (or INVOKE, as that soon-to-be-seven-bullet-point construct is known in the Standard)'s magic handles this case (well, four and soon to be six cases actually), while the function call syntax doesn't.

like image 65
T.C. Avatar answered Nov 20 '22 18:11

T.C.


I want to complement T.C.'s answer with a syntactic example:

struct X {
  int x;
  int foo(int a) const { return a + x; }
};

and you have an X object and a pointer to a member function, e.g.:

X obj = X{1000};
auto fn = &X::foo;

and need to call func.

  • With the call syntax, this won't work:

    func_call(fn, obj, 24); // compiler error
    

    error: must use '.' or '->' to call pointer-to-member function in [...]

    Instead you have to work around it:

    func_call([obj, fn](int a) { return (obj.*fn)(a); }, 24);
    
  • If you had the invoke method, you could just have written:

    func_invoke(fn, obj, 24);
    
like image 36
bolov Avatar answered Nov 20 '22 17:11

bolov