#include #include using namespace std; template

Why does "std :: async" not work as expected?

#include <thread> #include <functional> #include <utility> using namespace std; template<typename Callable, typename... Args> void Async(Callable&& fn, Args&&... args) { auto fn_wrapper = [](Callable&& fn, Args&&... args) { invoke(forward<Callable>(fn), forward<Args>(args)...); }; // ok fn_wrapper(forward<Callable>(fn), forward<Args>(args)...); // ok async(forward<Callable>(fn), forward<Args>(args)...); // error : no matching function for call to 'async' async(fn_wrapper, forward<Callable>(fn), forward<Args>(args)...); } void f(int, int) {} int main() { Async(f, 1, 2); this_thread::sleep_for(1min); } 

The following code is in order:

  fn_wrapper(forward<Callable>(fn), forward<Args>(args)...); 

The following code is also in order:

  async(forward<Callable>(fn), forward<Args>(args)...); 

However, the following code is NOT ok:

  // error : no matching function for call to 'async' async(fn_wrapper, forward<Callable>(fn), forward<Args>(args)...); 

The latter case cannot compile with the following error:

 main.cpp:27:5: fatal error: no matching function for call to 'async' async(fn_wrapper, ^~~~~ main.cpp:36:5: note: in instantiation of function template specialization 'Async<void (&)(int, int), int, int>' requested here Async(f, 1, 2); ^ [...] /usr/local/bin/../lib/gcc/x86_64-pc-linux-gnu/6.3.0/../../../../include/c++/6.3.0/future:1739:5: note: candidate template ignored: substitution failure [with _Fn = (lambda at main.cpp:12:9) &, _Args = <void (&)(int, int), int, int>]: no type named 'type' in 'std::result_of<(lambda at main.cpp:12:9) (void (*)(int, int), int, int)>' async(_Fn&& __fn, _Args&&... __args) 

Why does the latter case not work?

+6
source share
1 answer

Perfect Redirection ( && ) only works in the context of a pattern. But your lambda is not a template. So, (Callable&& fn, Args&&... args) just clicks && on each argument and actually means "pass by rvalue by reference", which is not going to improve correctly.

But more importantly, std::async calls the functor as INVOKE(DECAY(std::forward<F>(f)), DECAY(std::forward<Args>(args))...) , so the inferred parameter types functors actually decompose Callable and Args .

Try using this shell:

  auto fn_wrapper = [](auto&& fn, auto&&... args) { invoke(forward<decltype(fn)>(fn), forward<decltype(args)>(args)...); }; 
+7
source

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


All Articles