满足迭代器需求
Iterator requirements satisfaction
考虑以下类:
template <class T>
struct X {
T& operator*() & { return t; }
T& operator*() && = delete;
X& operator++() { return *this; }
T t;
};
此类是否满足C++标准对迭代器概念的要求?此类的对象是可增量和可取消引用的。但是禁止取消引用右值对象。
int main() {
X<int> x;
*x; // ok
*X<int>(); // fail. But is it really necessary for Iterator by Standard?
}
严格阅读标准;[iterator.iterators]/2 (§24.2.2/2) 确实暗示了有资格作为迭代器X
类型;
。
a
和b
表示类型为X
或const X
的值。
r
表示值为X&
...在以下情况下,类型
X
满足迭代器要求:
X 满足
CopyConstructible
、CopyAssignable
和Destructible
要求([utility.arg.requirements]),并且X
类型的左值是可交换的([swappable.requirements]),并且表(如下)中的表达式有效,并具有指示的语义。
*r
(r
可取消引用)++r
(返回X&
)
给定代码;
template <class T>
struct X {
T& operator*() & { return t; }
T& operator*() && = delete;
X& operator++() { return *this; }
T t;
};
int main()
{
X<int> x;
++x;
int i = *x;
X<int> y(x);
using std::swap;
std::swap(x, y);
}
当然,似乎确实满足了这些要求。
然而,故事还在继续,如上所述的迭代器概念未被列为标准 §24.2.1/2 中的迭代器类别之一;
该国际标准根据对迭代器定义的操作定义了五类迭代器:输入迭代器、输出迭代器、前向迭代器、双向迭代器和随机访问迭代器......
它们都定义了X
类型无法编译的操作*a
和*r++
;
int j = *x++; // fails to compile even with the inclusion of the post increment operator
const X<int> xc {};
int ic = *x1; // no const overloads
为了使迭代器在定义的类别之一中可用,它需要包含更多成员,用于取消引用const
值、左值和右值、后增量等。本着标准的精神;
迭代器是指针的泛化,允许C++程序以统一的方式处理不同的数据结构(容器)。
这里对重载成员和运算符的指导是,可以/应该添加它们以强制遵守并优化(如果可能)通用指针语义的实现 - 而不是不允许语义;限制语义可能会产生意想不到的后果。
好吧,该标准没有说明rvalue
引用的迭代器。甚至无法识别其成员被其引用类型重载的迭代器。但是您的代码似乎可以接受成为迭代器*,因为在定义迭代器的要求时...
引用最新的 C++14 标准草案第 24.2.2 节(重点是我的)
24.2.2.2: 在以下情况下,X 类型满足迭代器要求:
— X 满足 可复制、可复制可分配和可破坏要求 (17.6.3.1) 和 X 类型的左值可交换 (17.6.3.2),并且
— 表 106 中的表达式是有效的,并且具有指示的语义。
*r : r 可取消引用
++r : r 是可递增的
除此之外,迭代器没有额外的约束。
* 原因,假设生成的X<typename ...>
满足第一个列出的条件
- 使用std::multimap迭代器创建std::list
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- C++中带有List类的迭代器Segfault
- 如何在c++迭代器类型中包装std::chrono
- 集合上的输出迭代器:assign和increment迭代器
- Boost Spirit,获取迭代器内部语义动作
- 对于set上的循环-获取next元素迭代器
- 为什么output_editor Concept不需要output_e迭代器标记
- c++17文件系统::recursive_directory迭代器()在mac上没有给出这样的目录,但在windows上
- 使用迭代器时如何访问对象在向量中的位置?
- std::vector::迭代器是否可以合法地作为指针
- 跟随整数索引列表的自定义类迭代器
- 不明白迭代器,引用和指针失效,一个例子
- 我可以使用反向迭代器作为ForwardIt吗
- ESP8266单片机矢量迭代器的C++问题
- 如何在C++中将迭代器作为函数参数传递
- 是否应避免从非常量迭代器转换为常量迭代器?
- 新的迭代器需求
- 满足迭代器需求
- 迭代器需求明显不一致