Search code examples
c++rvalue-referencervaluelvalue-to-rvaluepass-by-rvalue-reference

Why the rvalue reference parameter cannot be passed between functions directly?


My code is as follows:

#include <iostream>
using namespace std;

class A{
public:
    void sendByRvalue(string&& str){
        cout << str << endl;
    }
};

class B{
private:
    A a;
    void send(string&& str){
        a.sendByRvalue(str);
    }
public:
    void run(const string& str){
        send("run " + str + "\n");
    } 
}; 

int main(void){
    string str("hello world");
    B b;
    b.run(str);
    return 0;
}

When I compile the code shown above, I got some compile errors: enter image description here

It seems that the str in B::send function has been changed to lvalue. Then I change the implement of B::send, like:

class B{
private:
    A a;
    void send(string&& str){
        cout << boolalpha << is_rvalue_reference<decltype(str)>::value << endl;
        a.sendByRvalue(std::move(str));
    }
public:
    void run(const string& str){
        send("run " + str + "\n");
    } 
}; 

Everything goes well, but the output of this program made me confuse more. The output is as follows: enter image description here

Why the parameter str is a rvalue reference but I cannot pass it to the function A::sendByRvalue directly without std::move ?


Solution

  • str is a named rvalue reference, which is treated in the language as an lvalue. rvalues are only xvalues or prvalues, and str is neither.

    A note from the standard, on the xvalue rules:

    In general, the effect of this rule is that named rvalue references are treated as lvalues and unnamed rvalue references to objects are treated as xvalues; rvalue references to functions are treated as lvalues whether named or not.

    struct A {
    int m;
    };
    A&& operator+(A, A);
    A&& f();
    
    A a;
    A&& ar = static_cast<A&&>(a);
    

    The expressions f(), f().m, static_­cast<A&&>(a), and a + a are xvalues. The expression ar is an lvalue.