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.