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));