The following does not compile:
#include <iostream>
using namespace std;
int x = 5;
int && f () { return std::move(x); }
int g(int & y) { return y; }
int main() {
g(f());
return 0;
}
It's clear to me why prvalues (unnamed temporaries) do not bind to non-const lvalue references -- it does not make sense to modify them, as they will soon disappear. Yet why do xvalues not bind to non-const lvalue references?
If a function returns int &&
, the referenced object can't be temporary, otherwise we would get a dangling reference. Hence if an int &&
is returned, that's, in my understanding, a reference with the additional guarantee that it's safe to move from it.
Edit: Wording corrected: "Values" bind to "references" and not vice versa.
Second edit: The following compiles -- I do not see the conceptual difference, besides y now being an lvalue. Yet it still references x. I understand why this should compile and the above shouldn't, by the language specification. I do not, however, understand the reason behind it. Why does mere aliasing change the picture?
#include <iostream>
using namespace std;
int x = 5;
int && f () { return std::move(x); }
int g(int & y) { return y; }
int main() {
int && y = f(); // reference!
g(y); // compiles
// check that y indeed references x
y = 7;
std::cout << x << std::endl; // prints 7, of course
return 0;
}
Third edit: In short, what's the idea behind not allowing
int && f() { ... }
int g (int & y) { ...}
g(f());
yet allowing
int && f() { ... }
int g (int & y) { ...}
int & k (int && y) { return y; }
g(k(f()));
auto f( int&& x ) -> int&& { return move(x); }
– Cheers and hth. - Alfstruct A { int x; };
,A().x
is an xvalue, per CWG DR 616. – T.C.