Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dereference-assignment to a doubly incremented OutputIterator

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?

like image 833
ecatmur Avatar asked Nov 04 '22 18:11

ecatmur


1 Answers

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.

like image 145
nknight Avatar answered Nov 12 '22 10:11

nknight