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.