3
 string s = "hello";
 s + s = s; //compiles with no error/warnings

I was expecting a compilation error given rvalues are temporary values and can't be appear as an assigned value in an expression.

Samboy786
  • 101
  • 1
  • 8
  • Why not ok? Assigning to rvalue was never forbidden. – 273K Mar 16 '23 at 01:29
  • 1
    @AShelly No, `s + s = s;` is parsed as `(s + s) = s;`. – Evg Mar 16 '23 at 01:30
  • This is valid only for user defined types. For builtin types you can't do it. – Evg Mar 16 '23 at 01:30
  • @273K Trying to understand why its not forbidden. What if I accidentally swap l/r values in the assignment ? – Samboy786 Mar 16 '23 at 01:33
  • 1
    @Samboy786 Then your program logic is wrong. You have the same problem when you have two lvalue operands: Both `a = b` and `b = a` are then valid, but have different meaning. – user17732522 Mar 16 '23 at 01:43
  • What is bad in swap? `std::string().swap(s)` is good as `s.swap(std::string())`. `s.operator=()` looks similar to `s.swap()` from C++ point of view. – 273K Mar 16 '23 at 02:13
  • @273K Its bad if I am working with strings. s = (s + s) is quiet different from (s+s) = s. But again, my question has been answered in a different post (marked dupe here) and it shows how I can disable this behavior for an arbitrary class. – Samboy786 Mar 16 '23 at 02:22

1 Answers1

4

std::string is a class type and so = resolves to a normal member function call, i.e. (s + s).operator=(s).

You wouldn't expect member function calls on rvalues to fail generally and only since C++11 is there syntax to restrict member functions to lvalue arguments to the implicit object parameters.

For backwards-compatibility std::string::operator= was of course not modified to be restricted to lvalues and even for new library additions it is very uncommon to restrict operator= to lvalues. There isn't really much harm in allowing rvalues and it is occasionally useful, for example:

std::string a;
//...

std::string() = std::move(a);

This is supposed to "encourage" the temporary std::string to take the memory resources from the moved-from a and then release them when it is destroyed at the end of the expression. (Although std::string().swap(a) would be be a better choice in this case.)

Ultimately the answer is simply because the language designers at the time decided it that way.


I was expecting a compilation error given rvalues are temporary values and can't be appear as an assigned value in an expression.

This is simply wrong. Thinking of rvalue/lvalue as what can be on the left-hand side of a = is way too simplistic and at best applies only to non-class types.

user17732522
  • 53,019
  • 2
  • 56
  • 105
  • thank you for your inputs. I can see this was marked dupe of another question which explains how I can disable this behavior (assigning r value to l value) for an arbitrary class. – Samboy786 Mar 16 '23 at 02:12