Reputation: 2097
Here, creator() returns a pointer to X, which I dereference and pass to foo. Since that's an rvalue, move semantics should be used, right? But when I run it, I find that foo(X&) is called.
#include <iostream>
using namespace std;
struct X {
int i;
};
void foo(X& x) {
cout << "foo(X&)" << endl;
}
void foo(X&& x) {
cout << "foo(X&&)" << endl;
}
struct X* creator() {
return new X {5};
}
main() {
X x{5};
foo(*creator()); // prints foo(X&)
}
Upvotes: 1
Views: 66
Reputation: 302827
It's helpful to think of things in terms of identity and movability:
Dereferencing a pointer yields an expression that has an identity, that cannot be moved from, so it's an lvalue. Hence, it matches the X&
overload.
If you want to call the other overload, you will have to annotate the expression to indicate that it's safe to be moved from. This is what std::move
is for. Once you do that, the expression becomes an xvalue and now matches the X&&
overload.
Upvotes: 3
Reputation: 118310
creator()
returns a pointer.
Dereferencing that pointer gets you an lvalue. Pointer dereference results in an lvalue. After all, if p
is a pointer, you can assign to it: *p=some_value
, and you can only assign to an lvalue, therefore it has to be an lvalue.
You are getting confused by two things. It is true that the function returns an rvalue. But you're not passing what the function returns. The function returns a pointer, and you are dereferencing the pointer, which results in an lvalue.
Upvotes: 3