The distinction between rvalue references and forwarding references was made clear enough in this example by Scott Meyers:
Widget&& var1 = someWidget; // here, “&&” means rvalue reference (1) auto&& var2 = var1; // here, “&&” does not mean rvalue reference (2) template<typename T> void f(std::vector<T>&& param); // here, “&&” means rvalue reference (3) template<typename T> void f(T&& param); // here, “&&”does not mean rvalue reference (4)
Essentially the distinction happens when we have a deducible context, hence case (3) explicitly states that we have a vector<...>&&
whereas the T
in case (4) is to be deduced and (after applying reference collapsing rules) categorized in terms of "value category".
But what happens with a bit more complex pattern matching? Take the following case for example :
template <template <class...> class Tuple, class... Ts> void f(Tuple<Ts...>&& arg) { }
What does &&
mean here ?
I understand that a forwarding reference is "an rvalue reference to a cv-unqualified template parameter", such as in. template <class T> void foo(T&& ); which means the above function can take both l-value and r-value reference.
A forwarding reference is an rvalue reference to a cv-unqualified template parameter. If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction. Hence, the two mean the same thing, and the current C++ standard term is forwarding reference.
A reference variable declaration is any simple declaration whose declarator has the form. & attr(optional) declarator. (1) && attr(optional) declarator.
What is Perfect Forwarding. Perfect forwarding allows a template function that accepts a set of arguments to forward these arguments to another function whilst retaining the lvalue or rvalue nature of the original function arguments.
In your last example, arg
is an rvalue reference.
A forwarding reference is an rvalue reference to a cv-unqualified template parameter
and Tuple<Ts...>
is not a template parameter.
(Citation from [temp.deduct.call].)
It is a rvalue reference, not a forwarding reference.
The easiest way to be sure is to try to pass an lvalue, if it fails, then it is a rvalue reference, if not, then a forwarding reference:
template<typename... Ts> struct foo {}; //f function definition int main() { foo<int, double> bar; f(bar); // fails! Cannot bind lvalue to rvalue reference f(foo<int, double>{}); // ok, rvalue is passed }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With