Search code examples
c++lvalue-to-rvalue

Is the right operand of an assignment always converted to an rvalue?


I would like a clarification about this particular case:

class Test
{
    Test& operator=(const Test& copy)
    {
      ...
    }

    Test() = default;
}

Test a;
Test b;
b = a; //Is "a" converted to an rvalue?

"a" is an lvalue, however it is now the righthand operand of the assignment. Does it mean it gets converted to an rvalue?

This code doesn't compile:

class Test
{
    Test& operator=(Test&& copy) 
    {
      ...
    }

    Test() = default;
}

Test a;
Test b;
a = b; //Error

But this one does:

class Test
{
    Test& operator=(Test& copy) 
    {
      ...
    }

    Test() = default;
}

Test a;
Test b;
a = b; //OK

Since an lvalue reference cannot bind to an rvalue, does it mean a conversion is not happening here? If that is the case, when does an implicit lvalue-to-rvalue conversion happen? (Other than the case of the operator+ with primitive types)


Solution

  • "a" is an lvalue, however it is now the righthand operand of the assignment. Does it mean it gets converted to an rvalue?

    In short, yes. In all versions and drafts of the C++ standard, one of the standard conversions is called the "lvalue-to-rvalue" conversion.

    That is applied in the first case you describe.

    Since an lvalue reference cannot bind to an rvalue, does it mean a conversion is not happening here? If that is the case, when does an implicit lvalue-to-rvalue conversion happen? (Other than the case of the operator+ with primitive types)

    In the second case, you have declared/defined an operator=(Test &&) that accepts an rvalue reference, which suppresses generation of an operator=(const Test &). In C++11 and later, declaring a operator=(Test &&) without one of operator=(Test &) or operator(const Test &) prevents using an lvalue on the right hand side (as in your example, a = b).

    Which does, indirectly, mean a lvalue-to-rvalue conversion is not employed in this case.