C++ 要求 OutputIterator 类型 X
支持 r++
形式的表达式,其中 r
是 X的实例
。此后缀增量必须在语义上等同于:
(*) { X tmp = r;++r;返回 tmp; }
并且必须返回可转换为 X const&
的类型。在 C++11 中,请参阅 24.2.4(但这不是新的)。在同一部分,它说
Algorithms on output iterators should never attempt to pass through the same iterator twice. They should be single pass algorithms.
给定 (*),上面,假设我复制返回值,如 X a(r++);
假设
r
在递增之前是可解引用的,但没有被解引用。是否要求a
是可解引用的?如果是这样,必须X a(r++); *a = t;
执行与*r++ = t;
否则相同的赋值?a
和r
是否有任何(其他)条件?否则,假设
r
在递增之前被取消引用/赋值,并且它的增量值(也)是可取消引用的。以下哪项(如果有的话)是明确定义的:(a)*a = t;
, (b)++a; *a = t;
, (c)*r = t;
?
另见后续:Dereference-assignment to a doubly incremented OutputIterator
最佳答案
正如您所注意到的,r++
具有操作语义
X operator++(int) { X tmp = r; ++r; return tmp; }
我将返回值添加为 X
因为根据 24.2.2:2 Iterator
满足 CopyConstructible
,所以复制是合法的将r++
的返回值构造成X
类型的实例。
接下来,要求*r++ = o
有效;这不同于 { const X &a(r++); *一=o; }
只是增加了一个序列点,与上面操作语义定义中的return tmp;
之后的序列点合并,所以复合语句有与表达式语句具有相同的有效性。通过调用 CopyConstructible
,{ X a(r++); *一=o;
具有相同的有效性和操作语义。
在案例中
*r = o;
X a(r++);
以下内容:
(a)
*a = o
无效,因为迭代器的那个值已经被解除引用分配;(b)
++a; *a = o
无效,因为迭代器的值已经递增,违反了单遍要求,因为只有r
的(新值)需要递增:根据 24.2.4:2 的注释,输出迭代器上的算法永远不应该 尝试两次通过同一个迭代器,尽管没有指定通过在此上下文中的含义;(c)
*r = o
是有效的,因为唯一的区别是*r = o; r++; *r = o
总体上是r
原始值的拷贝的继续存在,根据CopyConstructible
要求对从中复制的值没有语义影响.
另一个有趣的问题是(对于非解引用分配的 r
):
X a(r);
++r;
++r;
*a = o;
标准没有直接涵盖这一点,但从 CopyConstructible
看来它应该是有效的。
关于C++ OutputIterator 后递增要求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11876128/