在lambda中完美转发?

Vin*_*ent 7 c++ lambda decltype c++14 forwarding-reference

使用函数,可以编写:

template <class T> void f(T&& x) {myfunction(std::forward<T>(x));}
Run Code Online (Sandbox Code Playgroud)

但是有了lambda,我们没有T:

auto f = [](auto&& x){myfunction(std::forward</*?*/>(x));}
Run Code Online (Sandbox Code Playgroud)

如何在lambda中完美转发?是否decltype(x)可以作为类型std::forward

Ker*_* SB 11

转发绑定到转发引用的lambda参数的规范方法确实是decltype:

auto f = [](auto&& x){
  myfunction(std::forward<decltype(x)>(x));
} //                      ^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

  • 我可能错了,但据我所知,`decltype(x)` 与底层(隐藏)模板参数不同,因为 x 本身始终是左值。因此`std::forward&lt;decltype(x)&gt;(x)` 永远不会因此产生纯右值。 (2认同)

pat*_*ite 9

使用 C++20,您现在可以为 lambda 指定模板参数列表。以下内容直接取自https://en.cppreference.com/w/cpp/language/lambda

auto f = []<typename ...Ts>(Ts&& ...ts) {
    return foo(std::forward<Ts>(ts)...);
};
Run Code Online (Sandbox Code Playgroud)


Yak*_*ont 5

我最喜欢的成语是:

auto f = [](auto&& x){myfunction(decltype(x)(x));}
Run Code Online (Sandbox Code Playgroud)

我读为“x因为类型x被声明为”。

要了解如何工作的,检查时会发生什么xint&&decltype(x)(x)is (int&&)(x),它产生对 的右值引用x。如果x是 an int&,那么我们得到(int&)(x)which 是对引用的 noop 转换。请记住,decltype(x)包括参考类别。

现在,对于auto&&参数,这更短,但等效于:

auto f = [](auto&& x){myfunction(std::forward<decltype(x)>(x));}
Run Code Online (Sandbox Code Playgroud)

替代方案。

对于auto参数:

auto f = [](auto x){myfunction(decltype(x)(x));}
Run Code Online (Sandbox Code Playgroud)

它会产生一个额外的副本,而

auto f = [](auto x){myfunction(std::forward<decltype(x)>(x));}
Run Code Online (Sandbox Code Playgroud)

而是 move-from x

虽然我通常认为 C 风格的强制转换太危险了,decltype(x)(x)但最坏的情况是可以制作一个类型正确的xifx不是auto&&变量的副本。为了简洁起见,有些话要说。

  • decltype 类型转换是一个巧妙的技巧,但我喜欢 `std::forward` 的一点是它创建了一个可读(和 grepable)的提示,表明转发正在进行,并且附近的 `&amp;&amp;` 是一个转发引用。 (2认同)
  • 我同意这一点;简洁是以意义为代价的,IMO。不错的技巧,+1! (2认同)