Dereference-assignment to a doubly incremented OutputIterator
Asked Answered
F

1

6

Per the (excellent) question C++ OutputIterator post-increment requirements, we observe that for a dereferenceable and incrementable value r of OutputIterator type X, and value o of appropriate type, the expression

*r++ = o;

is valid and has equivalent semantics to

X a(r);
++r;
*a = o;

However, is it still the case the a is dereference-assignable if r has been incremented more than once in the intervening period; that is, is this code valid?

X a(r);
++r;
++r;
*a = o;

It's difficult to see how operations on a value can have an effect on the validity of operations on another value, but e.g. InputIterator (24.2.3) has, under the postconditions of ++r:

Any copies of the previous value of r are no longer required either to be dereferenceable or to be in the domain of ==.

Relevant sections: 24.2.2 Iterator, 24.2.4 Output iterators, 17.6.3.1 Template argument requirements.

Also, if this is not required to be valid, are there any situations where exploiting its non-validity would aid in the implementation (w.r.t. efficiency, simplicity) of an OutputIterator type while still observing the existing requirements?

Fluviomarine answered 9/8, 2012 at 15:47 Comment(5)
SGI STL (sgi.com/tech/stl/OutputIterator.html footnote 3) explicitly forbids this behavior, forcing a sequence of alternating increments and dereference-assignments; however, I can't derive that requirement from the C++ standard. Does 'only once' in [24.2.4:2] mean exactly once or at most once?Mitran
This answer: (https://mcmap.net/q/920602/-how-is-it-valid-for-output-iterators) makes me think that this behavior is valid for an ostream_iterator, which only actually increments on assignment, ignoring other increment operations. However, it doesn't seem all OutputIterators must obey those semantics.Mitran
@Mitran very interesting. only once appears 5 times in the standard, at 3.4:1 with a different meaning, and at 5.17:7, 12.8:15, 29.6.5:8 in the sense at most once (but usually once). exactly once and at most once each appear 5 times. Surely if the standard intended the SGI restrictions, they'd have incorporated that language?Fluviomarine
Actually it looks like someone found this in 2004: (open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#485), and the wording in n3066 (open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3066.html) seems to confirm the "alternating increment/dereference" requirement, don't you agree? Strange that this didn't make it into my copy of 14882:2011, when the rest of n3066 did (as far as I can tell).Mitran
@Mitran and a little more digging reveals defect 2035, which was raised after n3225 appeared without the fixes from n3066. So the intent of the standard is clear, it just didn't get in to the published version in time. Post as an answer and I'll accept.Fluviomarine
M
3

This issue was raised in 2004 as defect 485, and the wording in n3066 clarifies the issue, requiring that an output iterator need only support a sequence of alternating increments and dereference/assignments. So in your example, r need not be incrementable after the first ++r, unless there is an intervening dereference/assignment. This behavior is also required by SGI's STL (see footnote 3). As you mentioned above, n3225 appeared without the fixes from n3066, so defect 2035 was raised; but alas the fix did not make it into the published version of C++11 (ISO/IEC 14882:2011).

Furthermore, defect 2035 says that a (from X a(r++);) cannot be used like *a = 0:

"After this operation [i.e., ++r] r is not required to be incrementable and any copies of the previous value of r are no longer required to be dereferenceable or incrementable."

There are situations where this may aid the implementation (in terms of simplicity): see e.g. this question on ostream_iterator, where such (invalid) double increments are ignored simply returning *this; only a dereference/assignment causes the ostream_iterator to actually increment.

Mitran answered 13/8, 2012 at 17:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.