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?
Initializer List is used in initializing the data members of a class. The list of members to be initialized is indicated with constructor as a comma-separated list followed by a colon. Following is an example that uses the initializer list to initialize x and y of Point class.
The most common benefit of doing this is improved performance. If the expression whatever is the same type as member variable x_, the result of the whatever expression is constructed directly inside x_ — the compiler does not make a separate copy of the object.
Member initializer list is the place where non-default initialization of these objects can be specified. For bases and non-static data members that cannot be default-initialized, such as members of reference and const-qualified types, member initializers must be specified.
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= *= *= /= %= += -= >>= <<= &= ^= |=
C++14 §5.17/9:
” A braced-init-list may appear on the right-hand side of
- an assignment to a scalar, in which case the initializer list shall have at most a single element. The meaning of
x={v}
, whereT
is the scalar type of the expressionx
, is that ofx=T{v}
. The meaning ofx={}
isx=T{}
.- an assignment to an object of class type, in which case the initializer list is passed as the argument to the assignment operator function selected by overload resolution (13.5.3, 13.3).
This applies to a+=
b via its $5.7/7 equivalence to a=
a+
b (except that a is evaluated only once for +=
). Put another way, due to a comment by M.M., because of the equivalence for the built-in operators +=
is regarded as an assignment operator, and not a special update operator. Hence the quoted text above about “assignment” applies to +=
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With