Undefined behavior and sequence points reloaded
As others have said, your i += ++i
example works with the user-defined type since you're calling functions, and functions comprise sequence points.
On the other hand, a[++i] = i
is not so lucky assuming that a
is your basic array type, or even a user defined one. The problem you've got here is that we don't know which part of the expression containing i
is evaluated first. It could be that ++i
is evaluated, passed off to operator[]
(or the raw version) in order to retrieve the object there, and then the value of i
gets passed to that (which is after i
was incremented). On the other hand, perhaps the latter side is evaluated first, stored for later assignment, and then the ++i
part is evaluated.
http://www.eelis.net/C++/analogliterals.xhtml Analog literals comes to my mind
unsigned int c = ( o-----o
| !
! !
! !
o-----o ).area;
assert( c == (I-----I) * (I-------I) );
assert( ( o-----o
| !
! !
! !
! !
o-----o ).area == ( o---------o
| !
! !
o---------o ).area );
It looks like the code
i.operator+=(i.operator ++());
Works perfectly fine with regards to sequence points. Section 1.9.17 of the C++ ISO standard says this about sequence points and function evaluation:
When calling a function (whether or not the function is inline), there is a sequence point after the evaluation of all function arguments (if any) which takes place before execution of any expressions or statements in the function body. There is also a sequence point after the copying of a returned value and before the execution of any expressions outside the function.
This would indicate, for example, that the i.operator ++()
as the parameter to operator +=
has a sequence point after its evaluation. In short, because overloaded operators are functions, the normal sequencing rules apply.
Great question, by the way! I really like how you're forcing me to understand all the nuances of a language that I already thought I knew (and thought that I thought that I knew). :-)
I think it's well-defined:
From the C++ draft standard (n1905) §1.9/16:
"There is also a sequence point after the copying of a returned value and before the execution of any expressions outside the function13) . Several contexts in C++ cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit. [ Example: evaluation of a new expression invokes one or more allocation and constructor functions; see 5.3.4. For another example, invocation of a conversion function (12.3.2) can arise in contexts in which no function call syntax appears. — end example ] The sequence points at function-entry and function-exit (as described above) are features of the function calls as evaluated, whatever the syntax of the expression that calls the function might be. "
Note the part I bolded. This means there is indeed a sequence point after the increment function call (i.operator ++()
) but before the compound assignment call (i.operator+=
).