8

我怎样才能,或者,我可以将模板函数传递给异步?

这是代码:

//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'的类型
4

2 回答 2

13

问题是要将第二个参数传递给std::async编译器,必须将表达式&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使用哪个。

于 2014-09-12T19:08:24.173 回答
7

您必须通过显式传递模板参数或使用来消除可能的实例化之间的歧义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);
于 2014-09-12T18:58:10.783 回答