As I understand, std::invoke allows me to do something like:
std::invoke(f, arg1, arg2, ...);
Is there a scenario when it's more advantageous than simply doing:
f(arg1, arg2, ...);
As I understand, std::invoke allows me to do something like:
std::invoke(f, arg1, arg2, ...);
Is there a scenario when it's more advantageous than simply doing:
f(arg1, arg2, ...);
If the invocable is a pointer to a member function, then you need to do one of these:
(arg1->*f)(arg2,...);
(arg1.*f)(arg2,...);
Depending on what arg1 is.
INVOKE (and its official library counterpart std::invoke) was pretty much designed to simplify such messes.
You'd use std::invoke to support the caller of your code passing any callable, and not having to adapt their call site with a lambda or a call to std::bind.
std::invoke can be useful when you create a lambda and need to call it immediately. It the lambda is big, parentheses after it can be hard to observe:
[] (/* args */) {
// many lines here
// ...
} (/* args */)
vs
std::invoke(
[] (/* args */) {
// many lines here
// ...
},
/* args */);
#include <iostream>
#include <functional>
template< class Callable, typename ... Args>{}
//f(args...); // if arg1 is a class object pointer
// we should use it like this(arg1.*f)(args...);
std::invoke(f, args...); // now every thing is ok
}
void foo(char c) {
std::cout << "foo called\n";
}
int main()
{
struct S {
int f1(char c) {
std::cout << "S::f1 called\n";
}
void operator()(char c) {
std::cout << "S::operator() called\n";
}
};
int (S:: * fptr)(char c) = &S::f1;
S obj;
dosomething(fptr, obj, 'a');
return 0;
}
Trying to add on top of the two answers, one is giving a good theoretical explanation and the other is trying to provide a concrete example. Here is a good reason of why does std::invoke makes things better.
#include <functional>
#include <iostream>
struct foo
{
void echo(){std::cout << "foo" << std::endl;};
};
int main()
{
////
// Vanilla version of invoking .echo()
foo(f);
f.echo();
////
// Pointer to *class* member function version
void (foo::* pf)() = &foo::echo;
foo obj;
(obj.*pf)(); // ugly
// instead do ...
std::invoke(pf, obj);
// obj->echo(); <-- does not compile
return 0;
}