何时使用 std::invoke 而不是简单地调用可调用的?



据我了解,std::invoke允许我执行以下操作:

std::invoke(f, arg1, arg2, ...);

有没有一种情况比简单地做更有利:

f(arg1, arg2, ...);

如果 invocable 是指向成员函数的指针,则需要执行以下操作之一:

(arg1->*f)(arg2,...);
(arg1.*f)(arg2,...);

取决于arg1是什么。

INVOKE(及其官方库对应物std::invoke)几乎是为了简化这种混乱而设计的。

您将使用std::invoke来支持代码的调用方传递任何可调用对象,而不必使用 lambda 或对std::bind的调用来调整他们的调用站点。

当您创建 lambda 并需要立即调用它时,std::invoke非常有用。它的lambda很大,后面的括号可能很难观察到:

[] (/* args */) {
// many lines here
// ...
} (/* args */)

std::invoke(
[] (/* args */) {
// many lines here
// ...
},
/* args */);

试图在两个答案的基础上添加,一个是给出一个很好的理论解释,另一个是试图提供一个具体的例子。这是为什么std::invoke使事情变得更好的一个很好的理由。

#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;
}
#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 calledn";
}
int main()
{
struct S {
int f1(char c) {
std::cout << "S::f1 calledn";
}
void operator()(char c) {
std::cout << "S::operator() calledn";
}
};
int (S:: * fptr)(char c) = &S::f1;
S  obj;
dosomething(fptr, obj, 'a');
return 0;
}

最新更新