【发布时间】:2012-12-13 01:51:22
【问题描述】:
ForwardIterators 必须是 OutputIterators 吗?我当前的 STL 实现(VS2012)从 input_iterator_tag 和 output_iterator_tag 派生 forward_iterator_tag,但我在标准 [N3485] 中找不到这个要求。
【问题讨论】:
标签: c++ iterator-traits
ForwardIterators 必须是 OutputIterators 吗?我当前的 STL 实现(VS2012)从 input_iterator_tag 和 output_iterator_tag 派生 forward_iterator_tag,但我在标准 [N3485] 中找不到这个要求。
【问题讨论】:
标签: c++ iterator-traits
在 C++11 中,不,前向迭代器不需要是输出迭代器。输出迭代器要求就像迭代器可以拥有的一组额外要求,而不管它满足的其余迭代器要求如何。前向迭代器只需要是输入迭代器(§24.2.5/1):
如果满足以下条件,则类或指针类型 X 满足前向迭代器的要求:
- X 满足输入迭代器的要求
- ...
事实上,前向迭代器只有当它是一个可复制分配类型序列的可变迭代器时才满足输出迭代器要求†。
† 或一个常量迭代器,指向具有可变成员定义的operator=(...) const 的类型序列。
更重要的是,迭代器标签由标准专门定义为(§24.4.3/2):
namespace std {
struct input_iterator_tag { };
struct output_iterator_tag { };
struct forward_iterator_tag: public input_iterator_tag { };
struct bidirectional_iterator_tag: public forward_iterator_tag { };
struct random_access_iterator_tag: public bidirectional_iterator_tag { };
}
如您所见,forward_iterator_tag 应该只继承自 input_iterator_tag。
在 C++03 中,声明前向迭代器满足输入和输出迭代器的要求:
前向迭代器满足输入和输出迭代器的所有要求,并且可以在指定任何一种时使用。
但是这在下面的段落中是矛盾的,指出常量前向迭代器不能满足输出迭代器的要求:
除了它的类别之外,前向、双向或随机访问迭代器也可以是可变的或恒定的,具体取决于表达式 *i 的结果是作为引用还是作为对常量的引用。常量迭代器不满足输出迭代器的要求,表达式 *i(对于常量迭代器 i)的结果不能用于需要左值的表达式中。
但是,迭代器标签的定义与 C++11 中的相同。这个矛盾的措辞有一个defect report,但它被关闭为不是缺陷,因为第一个引用在该部分的“介绍性文本”中,并且将来可能会被改写(确实如此)。
SGI definition of a forward iterator 是对输入和输出迭代器的改进(感谢 cmets 中的@BenVoigt)。
不过,如果我们看一下implementation of the iterator tags,我们会发现forward_iterator_tag 仍然只继承自input_iterator_tag。
看起来这在过去是一个相当混乱的领域,但如果 VS2012 将 forward_iterator_tag 定义为继承自 output_- 和 input_iterator_tag,我只能假设这是一个错误。
【讨论】: