Search code examples
c++assignment-operatorrvalue

why error lvalue required as left operand does not exhibit for strings?


In below code snippet, why line 2 + 3 = 5 statement gives error but next statement of assigning to string concatenation compiles successfully?

#include <string>

int main() {                                                                                                                                                  
   2 + 3 = 5;   //  Error: lvalue required as left operand of assignment                                                                                                                                             
   std::string("2") + std::string("3") = std::string("5");  // Compiles successfully. why?                                                                                                 
   return 0;                                                                                                                                                 
}

My understanding is that left hand side of the expression std::string("2") + std::string("3") = std::string("5") will produce temporary which is rvalue. That means I am assigning to rvalue - just like 2 + 3 = 5. So it should also give lvalue required as left operand of assignment error. But it does not.


Solution

  • Explanation

    For class types, assignment is implemented by copy and move assignment operators. std::string is a class, so

    std::string("2") + std::string("3") = std::string("5")
    

    is just syntactic sugar for

    (std::string("2") + std::string("3")).operator=(std::string("5"))
    

    operator= is a member function. Usually, a member function can be called on both lvalues and rvalues. Therefore, this expression is valid.

    Standard reference

    For non-overloaded operator= (i.e., for int): [expr.ass]/1

    The assignment operator (=) and the compound assignment operators all group right-to-left. All require a modifiable lvalue as their left operand and return an lvalue referring to the left operand. [...]

    For overload operator= (for std::string): [expr.ass]/4

    If the left operand is of class type, the class shall be complete. Assignment to objects of a class is defined by the copy/move assignment operator ([class.copy], [over.ass]).

    (emphasis mine for all)