1
votes

We can't bind non-const lvalue reference to an rvalue, but it can be bound to the const one. We can't bind rvalue reference to an lvalue also. Actually the Standard say so:

8.5.3/5.2:

the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference.

But is there a better explanation for the things than "The Standard say so"?

2

2 Answers

3
votes

Because it doesn't make semantic sense.

You can't bind a non-const lvalue reference to an rvalue, because what does it mean to modify an rvalue? By definition nothing else will see the result, so this doesn't make sense.

int& i = 3;
//should change referenced location, but we aren't referencing a memory location
i = 5; 

You can't bind an rvalue reference to an lvalue because rvalue references exist to facilitate destructive optimizations on their referencee. You wouldn't want your objects to be arbitrarily moved out from under you, so the standard doesn't allow it.

void process_string (std::string&&);
std::string foo = "foo";
//foo could be made garbage without us knowing about it
process_string (foo); 
//this is fine
process_string (std::move(foo));
3
votes

Think to some real cases:

#include <vector>

void f1( int& i ){i = 1;}
void f2( const int& i ){i = 1;}
void f3( std::vector<int>&& v ){auto v_move{v};}

int main()
{
    f1(3); // error: how can you set the value of "3" to "1"?
    f2(3); // ok, the compiler extend the life of the rvalue "into" f2
    std::vector<int> v{10};
    f3(v); // error: an innocent looking call to f3 would let your v very different from what you would imagine
    f3(std::vector<int>{10}); // ok, nobody cares if the rvalue passed as an argument get modified
}