I have a function that has a lvalue reference as argument, and I found that I can also pass a rvalue reference to it. However, when I passing the result of std::move to the function, I get an error which tells me that I cannot bind non-const lvalue reference to an rvalue.
#include <iostream> #include <string> template<typename T> void foo(T& a) { } struct A { std::string s; }; int main(int argc,char** argv) { A a{"a"}; A&& ra = std::move(a); foo(ra); // OK foo(std::move(a)); // Error return 0; } I was thinking that std::move also returns a rvalue reference. What is the difference between using an intermediate rvalue reference as argument and directly using the result of std::move as argument?
rais an lvalue expression when used infoo(ra);rais still an lvalue--after all, it has a name, and it's valid to put it on the left hand side of an=.rais the name of a variable and is an lvalue expression.T &&, the actual result of the call has typeT, and "xvalue" value category. (Similarly, returningT &gives an lvalue, and returning non-reference gives a prvalue). But standalone rvalue references (unlike ones returned from a function) don't impose the "xvalue" value category. Like all other variables, they are lvalues. (Or rather, expressions consisting of a variable name are lvalues.)