Search code examples
c++operator-overloadinginitializer-list

Why can I use initializer lists on the right-hand side of operator += but not operator+?


This is a follow-up to an earlier question about why I can't use a brace-enclosed initializer as an argument to operator+, which was resolved by looking at this earlier question on the subject.

Consider the following C++ code, which you can try live at ideone.com:

#include <iostream>
#include <initializer_list>
using namespace std;

struct AddInitializerList {
    void operator+= (initializer_list<int> values) {
        // Do nothing   
    }
    
    void operator+ (initializer_list<int> values) {
        // Do nothing
    }
};

int main() {
    AddInitializerList adder;
    adder += {1, 2, 3};  // Totally legit
    adder +  {1, 2, 3};  // Not okay!
    
    return 0;
}

The line in main that uses operator+ with a brace-enclosed initializer list does not compile (and, after asking that earlier question, I now know why this is). However, I'm confused why the code that uses operator+= in main does indeed compile just fine.

I'm confused as to precisely why I can overload += and have it work just fine, while overloading + doesn't seem to work here. Is there a particular provision in the standard that permits brace-enclosed initializers in the context of the += operator but not the + operator? Or is this just a weird compiler quirk?


Solution

  • It is explained in the answer to this question (which is linked from the question you linked to).

    The language grammar only allows a braced list in certain grammatical contexts, not in place of an arbitrary expression. That list includes the right-hand side of assignment operators, but NOT the right-hand side of operators in general.

    += is an assignment operator, + is not.

    The grammar for assignment expressions is:

      assignment-expression:
         conditional-expression
         logical-or-expression assignment-operator initializer-clause
         throw-expression
      assignment-operator: one of
          = *= *= /= %= += -= >>= <<= &= ^= |=