C++ requires that an OutputIterator type X
support expressions of the form r++
, where r
is an instance of X
. This postfix inc
As you note, r++
has operational semantics
X operator++(int) { X tmp = r; ++r; return tmp; }
I've added the return value as X
because per 24.2.2:2 Iterator
satisfies CopyConstructible
, so it is legitimate to copy construct the return value of r++
into an instance of type X
.
Next, *r++ = o
is required to be valid; this differs from { const X &a(r++); *a = o; }
only in the addition of a sequence point, which merges with the sequence point after return tmp;
in the operational semantics definition above, so the compound statement has the same validity as the expression statement. By invoking CopyConstructible
, { X a(r++); *a = o; }
has the same validity and operational semantics.
In the case
*r = o;
X a(r++);
the following hold:
(a) *a = o
is invalid because that value of the iterator has already been dereference-assigned;
(b) ++a; *a = o
is invalid because that value of the iterator has already been incremented, violating the single-pass requirement, as only (the new value of) r
is required to be incrementable: per the note to 24.2.4:2, Algorithms on output iterators should never
attempt to pass through the same iterator twice, although it's not specified what pass through means in this context;
(c) *r = o
is valid, because the only difference to *r = o; r++; *r = o
overall is the continued existence of a copy of the original value of r
, which per CopyConstructible
requirements has no semantic effect on the value copied from.
Another interesting question is (for a non-dereference-assigned r
):
X a(r);
++r;
++r;
*a = o;
This isn't covered by the standard directly, but from CopyConstructible
it appears it should be valid.