C ++ OutputIterator后增量需求 [英] C++ OutputIterator post-increment requirements
问题描述
C ++要求OutputIterator类型 X
支持 r ++
形式的表达式,其中 r
是 X
的实例。这个后缀增量在语义上必须等同于:
(*) {X tmp = r; ++ r; return tmp; }
,必须返回可转换为 X const&
的类型。在C ++ 11中,参见24.2.4(这不是新的,但是)。在同一节中,它表示
输出迭代器上的算法不应尝试两次通过相同的迭代器。
给定(*),例如我复制了 X a(r ++);
-
假设
r
在递增前可解除引用,但未取消引用。是否需要a
可解除引用?如果是这样,必须X a(r ++); * a = t;
执行与* r ++ = t;
相同的赋值否则?a
和r
是否有其他条件? -
否则,假设
r
在递增前被取消引用/分配,其递增值也是可解除引用的。以下哪一项(如果有)是明确定义的:(a)
* a = t;
,(b)++一个; * a = t;
,(c)* r = t;
?
另请参阅后续:对双倍递增的OutputIterator的引用赋值
正如你所说, code>具有操作语义
X运算符++(int){X tmp = r; ++ r; return tmp; }
我已将返回值添加为 X
因为根据24.2.2:2 Iterator
满足 CopyConstructible
,因此它是合法的构造返回值 r ++
到 X
的实例。
, * r ++ = o
需要有效;这不同于 {const X& a(r ++); * a = o; }
仅在添加序列点时与 return tmp;
在操作语义上面的定义,因此复合语句与expression语句具有相同的有效性。通过调用 CopyConstructible
, {X a(r ++); * a = o;
<$ p $ p>
* 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;
* a = o;
这不是标准直接覆盖,而是 CopyConstructible
它似乎应该是有效的。
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++);
Suppose
r
was dereferencable before incrementing, but was not dereferenced. Is it required thata
be dereferencable? If so, mustX a(r++); *a = t;
perform the same assignment as*r++ = t;
would have otherwise? Are there any (other) conditions ona
andr
?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
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 ofr
, which perCopyConstructible
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.
这篇关于C ++ OutputIterator后增量需求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!