Rivand Asked:2020-06-29 14:39:18 +0000 UTC2020-06-29 14:39:18 +0000 UTC 2020-06-29 14:39:18 +0000 UTC 为什么需要 std::invoke ? 772 我现在看到在第 17 个标准中有一个新的模板功能std::invoke。我很高兴,因为。我认为它与 .NET 中的相同invoke,但在查找了有关它的信息后,我并没有完全理解为什么需要它。我知道它会调用仿函数和 lambda,但这与它们的直接调用有何不同?能否像.NETstd::invoke中的对应线程那样在特定线程中进行此调用? c++ 3 个回答 Voted user7860670 2020-06-29T16:09:37Z2020-06-29T16:09:37Z 关键std::invoke是以一致的方式调用类的普通方法和非静态方法。这在编写模板时主要有用。下面是一个紧凑函数模板的示例,它包装了对另一个函数的调用: template<typename F, typename V1, typename V2> auto foo(F f, V1 v1, V2 v2) -> void { ::std::invoke(f, v1, v2); } 使用示例: inline auto bar(int v1, int v2) -> void { ::std::cout << v1 << " " << v2 << ::std::endl; } class Bar { private: int m_v; public: explicit Bar(int v): m_v{v} {} public: auto bar(int v2) -> void { ::std::cout << m_v << " " << v2 << ::std::endl; } }; int main() { int v1{12}; int v2{23}; foo(&bar, v1, v2); // вызов обычного метода Bar b{12}; foo(&Bar::bar, b, v2); // вызов нестатического метода класса по ссылке foo(&Bar::bar, &b, v2); // вызов нестатического метода класса по указателю } 如果不使用::std::invoke它,您将不得不独立实现调用非静态类方法的选项: template<typename F, typename V1, typename V2> auto foo(F f, V1 v1, V2 v2) -> ::std::enable_if_t < not ::std::is_member_function_pointer_v<F> > { f(v1, v2); } template<typename F, typename V1, typename V2> auto foo(F f, V1 v1, V2 v2) -> ::std::enable_if_t < ::std::is_member_function_pointer_v<F> and not ::std::is_pointer_v<V1> > { (v1.*f)(v2); } template<typename F, typename V1, typename V2> auto foo(F f, V1 v1, V2 v2) -> ::std::enable_if_t < ::std::is_member_function_pointer_v<F> and ::std::is_pointer_v<V1> > { (v1->*f)(v2); } Best Answer Chorkov 2020-06-29T15:36:40Z2020-06-29T15:36:40Z std::invoke需要统一调用仿函数(包括lambda)、函数指针和类成员函数指针。后者具有与常规函子的语法不匹配的特定调用语法: (obj->*mem_fn_ptr)( args... ); 如果您正在编写一个 type 的函数std::async,并且您需要实现对所有可调用对象的支持,那么将它们传递到一个包中invoke比为每种情况编写单独的模板实现更容易。这样的语法糖。 标准中没有.NET 的类似物invoke,因为没有消息处理周期,因此不可能“向线程发送任务”。如果您只需要异步执行,std::async请使用WinAPI函数或窗口库的函数(Qt、wxWidgets ...),或者组织“手动”消息循环并将包装的任务推送到适当的队列中。std::thread Pavel Mayorov 2020-06-29T15:42:27Z2020-06-29T15:42:27Z 这与直接调用不同,不是所有可以调用的东西都可以std::invoke直接调用。 简而言之,该调用std::invoke(f, arg0, args...)尝试进行以下调用之一: (arg0.*f)(args...); (arg0.get().*f)(args...); ((*arg0).*f)(args...); arg0.*f arg0.get().*f; (*arg0).*f; f(arg0, args...); std::invoke当您编写可与任何给定 Callable 对象一起使用的通用代码时,需要使用。 至于在后台线程中调用函数,为了这些目的发明了一个函数std::async。
关键
std::invoke是以一致的方式调用类的普通方法和非静态方法。这在编写模板时主要有用。下面是一个紧凑函数模板的示例,它包装了对另一个函数的调用:使用示例:
如果不使用
::std::invoke它,您将不得不独立实现调用非静态类方法的选项:std::invoke需要统一调用仿函数(包括lambda)、函数指针和类成员函数指针。后者具有与常规函子的语法不匹配的特定调用语法:如果您正在编写一个 type 的函数
std::async,并且您需要实现对所有可调用对象的支持,那么将它们传递到一个包中invoke比为每种情况编写单独的模板实现更容易。这样的语法糖。标准中没有.NET 的类似物
invoke,因为没有消息处理周期,因此不可能“向线程发送任务”。如果您只需要异步执行,std::async请使用WinAPI函数或窗口库的函数(Qt、wxWidgets ...),或者组织“手动”消息循环并将包装的任务推送到适当的队列中。std::thread这与直接调用不同,不是所有可以调用的东西都可以
std::invoke直接调用。简而言之,该调用
std::invoke(f, arg0, args...)尝试进行以下调用之一:std::invoke当您编写可与任何给定 Callable 对象一起使用的通用代码时,需要使用。至于在后台线程中调用函数,为了这些目的发明了一个函数
std::async。