为什么“ std :: async”不能按预期工作?

xmllmx
#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);
}

可以使用以下代码:

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

以下代码也可以:

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

但是,以下代码不正确

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

最后一种情况无法编译,并出现以下错误:

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)

为什么最后一种情况不起作用?

生锈的

完美转发(&&)仅在模板参数上下文中有效。但是您的lambda不是模板。因此,(Callable&& fn, Args&&... args)&&对每个参数都打耳光,实际上意味着“通过右值引用传递”,这不能正确地进行完美转发。

但更重要的是,std::async调用函数对象为INVOKE(DECAY(std::forward<F>(f)), DECAY(std::forward<Args>(args))...),所以推导的仿函数的参数类型实际上是腐烂 CallableArgs

尝试使用此包装器:

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章