3

Please consider the following code:

class a {
public:
    int a;
};

void func1( a &&var1 );

void func2( a &&var2 )
{
    func1(var2);
}

When trying to compile it, gcc returns the following:

question.cpp: In function ‘void func2(a&&)’:
question.cpp:10:14: error: cannot bind ‘a’ lvalue to ‘a&&’
     func1(var);
              ^
question.cpp:6:6: error:   initializing argument 1 of ‘void func1(a&&)’
 void func1( a &&var );
      ^

It seems that var2 is an lvalue, despite it being quite explicitly defined as an rvalue reference. Does the double ampersands lose their meaning once assigned? What is the mechanism that's at work here?

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
Shachar Shemesh
  • 8,193
  • 6
  • 25
  • 57
  • See also: http://stackoverflow.com/questions/28483250/rvalue-reference-is-treated-as-an-lvalue?rq=1 – ecatmur Mar 10 '16 at 10:25

3 Answers3

5

Inside the function implementation, the once-rvalue becomes a regular variable (l-value), to which you can make assignments. If you want to turn it into an rvalue again, you must use std::move, as in:

void func2( a &&var2 ) {
    func1(std::move(var2));
}
Rubens
  • 14,478
  • 11
  • 63
  • 92
4

There is no mechanism at work, just the definitions. var2 is an identifier that denotes a variable. When used as an expression, it becomes id-expression, whose value category is defined as follows, in 5.1.1[expr.prim.general]/8

The result is the entity denoted by the identifier. The result is an lvalue if the entity is a function, variable, or data member and a prvalue otherwise.

var2, the variable, has type rvalue reference to a

var2, the expression, has type a and value category lvalue

(you're not the first person to confuse rvalues and rvalue references)

Cubbi
  • 46,567
  • 13
  • 103
  • 169
2

In func2 you could, theoretically, write a = <something>. Therefore a is an l-value. So the compiler is correct.

Alex Shtoff
  • 2,520
  • 1
  • 25
  • 53
  • What is var2's static type? – Shachar Shemesh May 04 '14 at 17:58
  • I am not aware of the standard formalities, but I believe that the type of var2 is "a reference to a" and its value category is "l-value". When the compiler type-checks your program it checks that it makes sense both in terms of types and in terms of value categories. Those are two separate concepts. – Alex Shtoff May 04 '14 at 18:17