【问题标题】:using std::async with template functions将 std::async 与模板函数一起使用
【发布时间】:2014-09-12 18:49:31
【问题描述】:

我怎样才能将模板函数传递给异步?

代码如下:

//main.cpp
#include <future>
#include <vector>
#include <iostream>
#include <numeric>

int
main
    ()
{      
    std::vector<double> v(16,1);

    auto r0 =  std::async(std::launch::async,std::accumulate,v.begin(),v.end(),double(0.0));

    std::cout << r0.get() << std::endl;
    return 0;
}

以下是错误消息:

^ a.cpp:13:88: 注意:候选人是: 在 a.cpp:1:0 包含的文件中: /usr/include/c++/4.8/future:1523:5: 注意:模板 std::future::type> std::async(std::launch, _Fn&&, _Args&& ...) 异步(启动 __policy,_Fn&& __fn,_Args&&... __args) ^ /usr/include/c++/4.8/future:1523:5:注意:模板参数推导/替换失败: a.cpp:13:88:注意:无法推断模板参数“_Fn” auto r0 = std::async(std::launch::async,std::accumulate,v.begin(),v.end(),double(0.0)); ^ 在 a.cpp:1:0 包含的文件中: /usr/include/c++/4.8/future:1543:5: 注意:模板 std::future::type> std::async(_Fn&&, _Args&& ...) 异步(_Fn&& __fn,_Args&&... __args) ^ /usr/include/c++/4.8/future:1543:5:注意:模板参数推导/替换失败: /usr/include/c++/4.8/future: 代替'template std::future::type> std::async(_Fn&&, _Args&& ...) [with _Fn = std::launch; _Args = {}]’: a.cpp:13:88: 从这里需要 /usr/include/c++/4.8/future:1543:5: 错误:‘class std::result_of’中没有名为‘type’的类型

【问题讨论】:

标签: c++ algorithm c++11 templates stdasync


【解决方案1】:

问题在于,要将第二个参数传递给std::async,编译器必须将表达式&amp;std::accumulate 转换为函数指针,但它不知道您想要的函数模板的特化。对人类来说,很明显你想要一个可以用 async 的剩余参数调用的那个,但是编译器不知道这一点,并且必须单独评估每个参数。

正如 PiotrS. 的回答所说,您可以使用显式模板参数列表或使用强制转换来告诉编译器您想要哪个 std::accumulate,或者您也可以只使用 lambda 表达式:

std::async(std::launch::async,[&] { return std::accumulate(v.begin(), v.end(), 0.0); });

在 lambda 的主体内,编译器对std::accumulate 的调用执行重载解析,因此它会确定使用哪个std::accumulate

【讨论】:

    【解决方案2】:

    您必须通过显式传递模板参数或使用static_cast 来消除可能的实例化之间的歧义,因此:

    auto r0 = std::async(std::launch::async
                         , &std::accumulate<decltype(v.begin()), double>
                         , v.begin()
                         , v.end()
                         , 0.0);
    

    或:

    auto r0 = std::async(std::launch::async
           , static_cast<double(*)(decltype(v.begin()), decltype(v.end()), double)>(&std::accumulate)
           , v.begin()
           , v.end()
           , 0.0);
    

    【讨论】:

      猜你喜欢
      • 2012-05-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-14
      • 1970-01-01
      • 2018-10-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多