5

In C++11, if I try to do this:

int x = 5;

int && y = x;

It will fail to compile, with an error telling that an r-value reference cannot bind to an lvalue.

However if I do:

int x = 5;

auto && y = x;

It compiles with no errors. Why is it happening? I tried to get the type of y but typeid() takes away the reference attributes. Does auto && automatically collapses to a & or && depending on what is being assigned?

Nawaz
  • 353,942
  • 115
  • 666
  • 851
Jorge González Lorenzo
  • 1,722
  • 1
  • 19
  • 28

3 Answers3

9

In the first case int && y, the variable y can bind to only rvalue which x is not.

In the second case auto && y however, the variable y can bind to anything, as the type of y would be deduced anyway — and reference-collapsing will be applied accordingly — which is why your code compiles:

auto && y = x;

Since x is an lvalue, auto is deduced to be int&, hence it becomes:

int& && y = x;

and after reference-collapsing, it becomes:

int & y = x;

which is fine.


To understand it in more detail, read about:

  • Universal Reference (or Forwarding Reference, as it has been proposed to improve the terminology)

  • Reference Collapsing

Hope that helps.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
  • The draft working paper for the C++ standard defines the term _forwarding reference_ in 14.8.2.1 [temp.deduct.call] paragraph 3 (i.e., a corresponding proposal was accepted at some point). – Dietmar Kühl Dec 11 '15 at 17:05
  • @DietmarKühl, thanks!!! I have been fighting with improper 'universal reference' for some time. – SergeyA Dec 11 '15 at 17:06
2

int&& is an r-value reference to int. Whereas auto&& is a universal reference.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
2

In the second example, auto (in auto&&) would be anything which would make the code well-formed. In this case, int& && is well-formed, since int& && collapses to int& - thus all work well.

SergeyA
  • 61,605
  • 5
  • 78
  • 137