How can I, or, can I, pass a template function to async?
Here is the code:
//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;
}
Here are the error messages:
^ a.cpp:13:88: note: candidates are: In file included from a.cpp:1:0: /usr/include/c++/4.8/future:1523:5: note: template std::future::type> std::async(std::launch, _Fn&&, _Args&& ...) async(launch __policy, _Fn&& __fn, _Args&&... __args) ^ /usr/include/c++/4.8/future:1523:5: note: template argument deduction/substitution failed: a.cpp:13:88: note: couldn't deduce template parameter ‘_Fn’ auto r0 = std::async(std::launch::async,std::accumulate,v.begin(),v.end(),double(0.0)); ^ In file included from a.cpp:1:0: /usr/include/c++/4.8/future:1543:5: note: template std::future::type> std::async(_Fn&&, _Args&& ...) async(_Fn&& __fn, _Args&&... __args) ^ /usr/include/c++/4.8/future:1543:5: note: template argument deduction/substitution failed: /usr/include/c++/4.8/future: In substitution of ‘template std::future::type> std::async(_Fn&&, _Args&& ...) [with _Fn = std::launch; _Args = {}]’: a.cpp:13:88: required from here /usr/include/c++/4.8/future:1543:5: error: no type named ‘type’ in ‘class std::result_of’
The problem is that to pass the second argument to std::async
the compiler has to turn the expression &std::accumulate
into a function pointer, but it doesn't know which specialization of the function template you want. To a human it's obvious you want the one that can be called with the remaining arguments to async
, but the compiler doesn't know that and has to evaluate each argument separately.
As PiotrS.'s answer says, you can tell the compiler which std::accumulate
you want with an explicit template argument list or by using a cast, or alternatively you can just use a lambda expression instead:
std::async(std::launch::async,[&] { return std::accumulate(v.begin(), v.end(), 0.0); });
Inside the body of the lambda the compiler performs overload resolution for the call to std::accumulate
and so it works out which std::accumulate
to use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With