Search code examples
c++c++11rvalue-referencervaluepass-by-rvalue-reference

Overloading for rvalue?


Below is a code demonstrating the question:

class X {};
X x;
X&& rvalue_ref = std::move(x);
static_assert(std::is_same<decltype(rvalue_ref), X&&>::value, "Different types"); //To be sure that type is X&&
void func(X&) {
    cout << "lvalue reference";
}

void func(X&&) {
    cout << "rvalue reference";
}
int main() {
    func(rvalue_ref);
}

The output:

lvalue reference

Could you please explain the reason for that? We have a variable of the type X&& and an overload for this type but this overload isn't called.


Solution

  • References don't really work like that. Your argument rvalue_ref, despite its type, is an lvalue expression. You would have to do std::move again to make it an rvalue.

    Types and value categories are two separate things, and it can be hard to remember that an expression naming an rvalue reference typed object is not automatically an rvalue expression.

    Consider also:

    void foo(T&& ref)
    {
       bar(ref);             // lvalue arg
       bar(std::move(ref));  // rvalue arg
    }
    

    This is also mentioned on cppreference.com's "Value categories" article:

    Even if the variable's type is rvalue reference, the expression consisting of its name is an lvalue expression