C ++ OutputIterator后增量需求 [英] C++ OutputIterator post-increment requirements

查看:100
本文介绍了C ++ OutputIterator后增量需求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

C ++要求OutputIterator类型 X 支持 r ++ 形式的表达式,其中 r X 的实例。这个后缀增量在语义上必须等同于:



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



,必须返回可转换为 X const& 的类型。在C ++ 11中,参见24.2.4(这不是新的,但是)。在同一节中,它表示



输出迭代器上的算法不应尝试两次通过相同的迭代器。



给定(*),例如我复制了 X a(r ++);

的返回值


  1. 假设 r 在递增前可解除引用,但未取消引用。是否需要 a 可解除引用?如果是这样,必须 X a(r ++); * a = t; 执行与 * r ++ = t; 相同的赋值否则? a r 是否有其他条件?


  2. 否则,假设 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++);

  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

解决方案

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.

这篇关于C ++ OutputIterator后增量需求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆