What is exactly happening here? Why is this an error?
void f(int &&);
int && i = 5;
f(i);
Isn\'t it a bit counterintuitiv
There's a basic distinction here between is a and binds a. For example:
void f(int &&);
declares a function accepting a parameter that can only be initialized with an rvalue reference to a (type convertible to) int
.
int && i = 5;
declares an lvalue that can only be initialized with an rvalue reference to a (type convertible to) int
. Thus, in simple terms,
f(i);
tries to pass an lvalue reference to an int
to a function accepting only rvalue references to an int
. So it doesn't compile.
To tell the compiler to cast an lvalue to an rvalue, thereby utilizing move constructors where applicable (though not in the case of an int
), you can use std::move()
.
f(std::move(i));
I see why you are confused. The thing to remember is that whenever you have a variable name, you have an l-value.
So when you say:
int i = 0; // lvalue (has a name i)
And also
int&& i = 0; // lvalue (has a name i)
So what is the difference?
The int&&
can only bind to an r-value so:
int n = 0;
int i = n; // legal
BUT
int n = 0;
int&& i = n; // BAD!! n is not an r-value
However
int&& i = 5; // GOOD!! 5 is an r-value
So when passing i
to f()
in this example you are passing an l-value, not an r-value:
void f(int &&);
int&& i = 5; // i is an l-value
f(i); // won't accept l-value
The situation is actually a little more complicated than I have presented here. If you are interested in a fuller explanation then this reference is quite thorough: http://en.cppreference.com/w/cpp/language/value_category
Does it have a name?
Is it addressable?
If the answer to both is "yes", it's a L-Value.
In this snippet: i
has a name, i
has an address (you can write &i
), so it's a l-value.
f(&&)
gets r-value-reference as a parameter, so you need to turn l-value to r-value reference, which can be done with std::move
.
f(std::move(i));