Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why adding `const` makes the universal reference as rvalue

I have been reading about the universal references in Scott's last master piece about the c++11 and 14 with that being said despite an argument assigned to either lvalue or an rvalue type reference parameter there is something in between called universal reference which could deduced to either l/rvalue based on the type trait of an argument that passed . I could understand what makes the parameter as an universal reference but the one thing that doesn't clear to me is why adding const to the type parameter const T&& p make the p as rvalue:

template<typename T> void f(T&& param); // param is an universal reference  template<typename T> void f(const T&& param); // param is an rvalue reference 

Does the const do more than this when assigned to the reference parameter.

like image 705
RaGa__M Avatar asked Aug 07 '16 14:08

RaGa__M


People also ask

What is a const rvalue reference?

You probably haven't seen any practical code that uses const rvalue references ( const T&& ). And that's not really surprising. The main purpose of rvalue references is to allow us to move objects instead of copying them. And moving the state of an object implies modification.

What is a universal reference?

Universal reference was a term Scott Meyers coined to describe the concept of taking an rvalue reference to a cv-unqualified template parameter, which can then be deduced as either a value or an lvalue reference.

Can R values be const?

If you could pass an r-value by (non-const) reference, you could also be able to assign to it from inside the function. Therefore the rule that if r-values are to be passed by reference, this has to be a const reference.

Is an rvalue reference an Xvalue?

To answer the titular question, "rvalue reference" is a kind of type, while "xvalue" is a kind of expression. They are not. Rvalue references are types, types are not expressions and so cannot be "considered lvalue".


1 Answers

The official name is not universal reference, but forwarding reference. The Standard states that only rvalue references to cv-unqualified template parameters fall in this category:

14.8.2.1 Deducing template arguments from a function call [temp.deduct.call]

3 If P is a cv-qualified type, the top level cv-qualifiers of P’s type are ignored for type deduction. If P is a reference type, the type referred to by P is used for type deduction. 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. [ Example:

template <class T> int f(T&& heisenreference); template <class T> int g(const T&&); int i; int n1 = f(i); // calls f<int&>(int&) int n2 = f(0); // calls f<int>(int&&) int n3 = g(i); // error: would call g<int>(const int&&), which                // would bind an rvalue reference to an lvalue 

— end example ]

Allowing const T&& to behave as forwarding references, would make it impossible to overload a template function who takes only an rvalue reference as parameter.

Update: as @HowardHinnant mentions in the comments, const T&& does have its uses (see also this Q&A).

like image 141
TemplateRex Avatar answered Oct 01 '22 05:10

TemplateRex