问题
With a function, one can write:
template <class T> void f(T&& x) {myfunction(std::forward<T>(x));}
but with a lambda, we don't have T
:
auto f = [](auto&& x){myfunction(std::forward</*?*/>(x));}
How to do perfect-forwarding in a lambda? Does decltype(x)
work as the type in std::forward
?
回答1:
The canonical way to forward a lambda argument that was bound to a forwarding reference is indeed with decltype
:
auto f = [](auto&& x){
myfunction(std::forward<decltype(x)>(x));
} // ^^^^^^^^^^^
回答2:
My favorite idiom for this is:
auto f = [](auto&& x){myfunction(decltype(x)(x));}
which I read as "x
as the type x
was declared as".
To see how this works, examine what happens when x
is an int&&
. decltype(x)(x)
is (int&&)(x)
, which produces an rvalue reference to x
. If x
is an int&
, then we get (int&)(x)
which is a noop cast to a reference. Remember, decltype(x)
includes the reference category.
Now, for auto&&
parameters this is shorter but equivalent to:
auto f = [](auto&& x){myfunction(std::forward<decltype(x)>(x));}
the alternative.
For auto
parameters:
auto f = [](auto x){myfunction(decltype(x)(x));}
it induces an extra copy, while
auto f = [](auto x){myfunction(std::forward<decltype(x)>(x));}
instead moves-from x
.
While I usually treat C-style casts as being too dangerous, decltype(x)(x)
can at worst make a type-correct copy of x
if x
is not an auto&&
variable. And there is something to be said for the brevity of it.
来源:https://stackoverflow.com/questions/42799208/perfect-forwarding-in-a-lambda