C++ OutputIterator post-increment requirements

我是研究僧i 提交于 2019-12-05 20:12:15

问题


C++ requires that an OutputIterator type X support expressions of the form r++, where r is an instance of X. This postfix increment must be semantically equivalent to:

(*) { X tmp = r; ++r; return tmp; }

and must return a type that is convertible to X const&. In C++11, see 24.2.4 (this is not new, however). In the same section, it says

Algorithms on output iterators should never attempt to pass through the same iterator twice. They should be single pass algorithms.

Given (*), above, say I copy the return value like X a(r++);

  1. Suppose r was dereferencable before incrementing, but was not dereferenced. Is it required that a be dereferencable? If so, must X a(r++); *a = t; perform the same assignment as *r++ = t; would have otherwise? Are there any (other) conditions on a and r ?

  2. Otherwise, suppose r was dereferenced/assigned before incrementing, and its incremented value is (also) dereferencable. Which of the following (if any) are well-defined: (a) *a = t;, (b) ++a; *a = t;, (c) *r = t;?


Also see the follow-up: Dereference-assignment to a doubly incremented OutputIterator


回答1:


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.



来源:https://stackoverflow.com/questions/11876128/c-outputiterator-post-increment-requirements

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!