Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is adding a reference to a rvalue reference not an error?

Tags:

c++

c++11

I have the following typedef:

using int_ref = int&&;

Why does the following code not produce an error (or print false)?

std::cout << is_same< int_ref, int_ref&& >::value; // prints 1

I would expect that int_ref&& gets expanded to int&& && which is obviously not possible. Am I missing something?

like image 573
tobspr Avatar asked Jun 08 '16 11:06

tobspr


People also ask

What are rvalue references good for?

Rvalue references allow programmers to avoid logically unnecessary copying and to provide perfect forwarding functions. They are primarily meant to aid in the design of higer performance and more robust libraries.

Are rvalue references Lvalues?

Whatever has a name is an lvalue(1). So bar is an lvalue. Its type is "rvalue reference to string ", but it's an lvalue of that type. If you want to treat it as an rvalue, you need to apply std::move() to it.

Can you pass an lvalue to an rvalue reference?

In the example, the main function passes an rvalue to f . The body of f treats its named parameter as an lvalue. The call from f to g binds the parameter to an lvalue reference (the first overloaded version of g ). You can cast an lvalue to an rvalue reference.

Can you modify an rvalue?

rvalue references have two properties that are useful: rvalue references extend the lifespan of the temporary object to which they are assigned. Non-const rvalue references allow you to modify the rvalue.


1 Answers

This is due to reference collapsing rules.

Basically, although you can't write a reference to a reference yourself, in some cases (typedefs, template parameters, decltypes) you can add create a reference to a reference type, which collapses as follows:

A& & -> A&
A& && -> A&
A&& & -> A&
A&& && -> A&&

In your case, int_ref is int&&, so int&& && becomes int&&.


The relevant standard quote:

(N3337) [dcl.ref]/6: If a typedef (7.1.3), a type template-parameter (14.3.1), or a decltype-specifier (7.1.6.2) denotes a type TR that is a reference to a type T, an attempt to create the type “lvalue reference to cv TR”creates the type “lvalue reference to T” , while an attempt to create the type “rvalue reference to cv TR”creates the type TR.

like image 95
TartanLlama Avatar answered Oct 18 '22 20:10

TartanLlama