Adrian
Adrian

Reputation: 10911

Why is using move semantics in this way invalid?

I was tracking down a compilation error when I came to this case:

struct Y        
{               
  int&& y;      
  Y(int&& y)    
    : y(y)      
  {             
  }             
};              

struct ZZ {};   
struct Z        
{               
  ZZ&& z;       
  Z(ZZ&& z)     
    : z(z)      
  {             
  }             
};

These both fail stating:

exec.cpp: In constructor ‘Y::Y(int&&)’:
exec.cpp:57:10: error: invalid initialization of reference of type ‘int&&’ from expression of type ‘int’
exec.cpp: In constructor ‘Z::Z(ZZ&&)’:
exec.cpp:67:10: error: invalid initialization of reference of type ‘ZZ&&’ from expression of type ‘ZZ’

But I'm not exactly sure why. What is wrong here?

I'm using g++4.5.3 with -std=gnu++0x option, but it also occurs with -std=c++0x option.

Upvotes: 1

Views: 121

Answers (2)

Anything which has a name is an l-value. This means that the constructor parameter y is a l-value (of type r-value reference to int), because it has a name, "y".

Use std::move(y) to turn it back into a r-value.

Upvotes: 2

Kerrek SB
Kerrek SB

Reputation: 476960

You need to say : y(std::move(y)). That's the only way to get an expression that can bind to an rvalue reference. Just the naked expression y is an lvalue.

(Note that it's very dangerous and hard to make correct to store reference class members.)

Upvotes: 2

Related Questions