在 lambda 中完美转发?

Perfect forwarding in a lambda?

有了函数,可以这样写:

template <class T> void f(T&& x) {myfunction(std::forward<T>(x));}

但是对于 lambda,我们没有 T:

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

如何在 lambda 中进行完美转发? decltype(x) 是否与 std::forward 中的类型相同?

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

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

我最喜欢的成语是:

auto f = [](auto&& x){myfunction(decltype(x)(x));}

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

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

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

auto f = [](auto&& x){myfunction(std::forward<decltype(x)>(x));}

备选方案。

对于auto个参数:

auto f = [](auto x){myfunction(decltype(x)(x));}

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

auto f = [](auto x){myfunction(std::forward<decltype(x)>(x));}

而是从 x.

移动

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

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

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