使用 lambda 将可变参数转发给线程

Forward variadic argument to thread with lambda

我无法找到如何将 std::thread() 与 lambda 一起使用。即,具有可变参数的 lambda 通过转发接收参数。例如:

template<typename... T> 
auto foo(T&&... t){
    [](T&&... t){}(std::forward<T>(t)...); // (1)

    return std::thread( // (2) 
        [](T&&... t){},
        std::forward<T>(t)...
    );
}

auto bar(){
    int n=1;
    foo(1); (A)
    foo(n); (B)
}

A.1:编译

A.2:编译

B.1:编译

B.2:不编译

我不明白:

试试

template<typename... T> 
auto foo(T&&... t){
    [](T&&... u){ }(std::forward<T>(t)...); // (1)

    return std::thread( // (2) 
        [](auto &&... u){ },
        std::forward<T>(t)...
    );
}

我的意思是:在 lambda 中,您传递给 std::thread()auto && ... 而不是 T && ...。或者,也许 T const & ....

我不是语言层,也许有人可以纠正我,但在我看来,通用引用和右值引用之间存在冲突。并且 std::thread() 将以下参数的 副本 传递给第一个参数。

当你写

template<typename... T> 
auto foo(T&&... t)

&& 是通用引用,当您调用 foo(1)T... 变为 int,而当您调用 [=24] 时 int & =].

在你得到的函数里面

[](int){ }(std::forward<int>(t)); // (1)

return std::thread( // (2) 
    [](int){ },
    std::forward<int>(t)...
);

万一f(0).

这行得通,因为两个 lambda 都在等待 int 复制,这一直行得通。

但是当你调用 f(n) 时,在 foo() 中你会得到

[](int &){ }(std::forward<int>(t)); // (1)

return std::thread( // (2) 
    [](int &){ },
    std::forward<int>(t)...
);

这适用于第一次调用,因为 lambda 等待 int 左引用变量 (int &) 并获得 int 左引用变量,但没有t 适用于第二次调用,因为 std::threadstd::forward<int>(t)copy 传递给等待左参考。

std::thread 不能简单地将其参数通过引用转发给 lambda,因为这意味着两个线程可能在没有同步的情况下同时访问参数。因此,std::thread 创建参数的临时副本,并将其传递给 lambda。因为它们是临时的,所以它们是右值。这在 A.2 中有效,因为 lambda 的参数是右值引用(因为 Tint,所以 T&&int&&)。它在 B.2 中不起作用,因为 lambda 的参数是左值引用(因为 Tint&,所以 T&&int&)。就像 max66 所说的那样,您可能想在 lambda 中使用 auto&&... 以便它可以接受传递给它的任何内容。