Std :: merge does not work with std :: async

I want to combine two vectors into a separate stream

int main() { vector<int> a(100); vector<int> b(100); vector<int> c(200); std::async(std::launch::async, std::merge, a.begin(), a.end(), b.begin(), b.end(), c.begin()); } 

It does not compile

 main.cpp: In function 'int main()': main.cpp:17:25: error: no matching function for call to 'async(std::launch, <unresolved overloaded function type>, std::vector<int>::iterator, std::vector<int>::iterator, std::vector<int>::iterator, std::vector<int>::iterator, std::vector<int>::iterator)' c.begin()) ^ In file included from main.cpp:4:0: /usr/include/c++/6.2.1/future:1709:5: note: candidate: template<class _Fn, class ... _Args> std::future<typename std::result_of<typename std::decay<_Tp>::type(typename std::decay<_BoundArgs>::type ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) async(launch __policy, _Fn&& __fn, _Args&&... __args) ^~~~~ /usr/include/c++/6.2.1/future:1709:5: note: template argument deduction/substitution failed: main.cpp:17:25: note: couldn't deduce template parameter '_Fn' c.begin()) ^ In file included from main.cpp:4:0: /usr/include/c++/6.2.1/future:1739:5: note: candidate: template<class _Fn, class ... _Args> std::future<typename std::result_of<typename std::decay<_Tp>::type(typename std::decay<_BoundArgs>::type ...)>::type> std::async(_Fn&&, _Args&& ...) async(_Fn&& __fn, _Args&&... __args) ^~~~~ /usr/include/c++/6.2.1/future:1739:5: note: template argument deduction/substitution failed: /usr/include/c++/6.2.1/future: In substitution of 'template<class _Fn, class ... _Args> std::future<typename std::result_of<typename std::decay<_Tp>::type(typename std::decay<_BoundArgs>::type ...)>::type> std::async(_Fn&&, _Args&& ...) [with _Fn = std::launch; _Args = {}]': main.cpp:17:25: required from here /usr/include/c++/6.2.1/future:1739:5: error: no type named 'type' in 'class std::result_of<std::launch()>' 

On the other hand, if I call

 std::merge(a.begin(), a.end(), b.begin(), b.end(), c.begin()); 

Everything works perfectly. If I use lambda, too.

Why?

+5
source share
1 answer

std::merge is a template function. Getting a pointer to a template function requires explicitly specifying template parameters:

 std::async(std::launch::async, &std::merge<decltype(a.begin()), decltype(b.begin()), decltype(c.begin())>, a.begin(), a.end(), b.begin(), b.end(), c.begin()); 

Using lambda here is probably the cleanest and most readable solution:

 auto merger = [&a, &b, &c] { return std::merge(a.begin(), a.end(), b.begin(), b.end(), c.begin()); }; std::async(std::launch::async, merger); 

In C ++ 14, you can use a common lambda to pass arguments directly to std::async . (It is doubtful whether this solution is better than capturing a , b and c .) Example:

 auto merger = [](auto&&... xs) { return std::merge(std::forward<decltype(xs)>(xs)...); }; std::async(std::launch::async, merger, a.begin(), a.end(), b.begin(), b.end(), c.begin()); 
+10
source

Source: https://habr.com/ru/post/1261389/


All Articles