Search code examples
c++operator-overloadinglanguage-designrvaluetemporary-objects

Why is T() = T() allowed?


I believe the expression T() creates an rvalue (by the Standard). However, the following code compiles (at least on gcc4.0):

class T {};

int main()
{
    T() = T();
}

I know technically this is possible because member functions can be invoked on temporaries and the above is just invoking the operator= on the rvalue temporary created from the first T().

But conceptually this is like assigning a new value to an rvalue. Is there a good reason why this is allowed?

Edit: The reason I find this odd is it's strictly forbidden on built-in types yet allowed on user-defined types. For example, int(2) = int(3) won't compile because that is an "invalid lvalue in assignment".

So I guess the real question is, was this somewhat inconsistent behavior built into the language for a reason? Or is it there for some historical reason? (E.g it would be conceptually more sound to allow only const member functions to be invoked on rvalue expressions, but that cannot be done because that might break some existing code.)


Solution

  • This is why several classes in the Standard library can be implemented. Consider for example std::bitset<>::operator[]

    // bit reference:
    class reference {
      friend class bitset;
      reference();
    public:
      ˜reference();
      reference& operator=(bool x);           // for b[i] = x;
      reference& operator=(const reference&); // for b[i] = b[j];
      bool operator˜() const; // flips the bit
      operator bool() const;  // for x = b[i];
      reference& flip();      // for b[i].flip();
    };
    
    reference operator[](size_t pos); // for b[i];
    

    If you do bits[i] = true you exactly assign some value to an rvalue of class type. The proxy that's returned by operator[] can access the bits which are space efficiently packed into integers.