考虑标准中的Forward迭代器的定义(草案n4659,[forward.iterators] /27.2.5):
如果
,类或指针类型X
满足前向迭代器的要求
- 的要求
X
满足输入迭代器(27.2.3),X
满足DefaultConstructible
要求(20.5.3.1),- 如果
X
是可变迭代器,reference
是对T
的引用;如果X
是常量迭代器,reference
是对const T
的引用,- 表97中的表达式是有效的,并具有指示的语义和
X
类型的对象提供多次通过保证,如下所述。 [注意省略] 如果符合以下条件,则a
的两个可解除引用的迭代器b
和X
提供多次通过保证:
a == b
隐含++a == ++b
和X
是指针类型,或者表达式(void)++X(a), *a
等同于表达式*a
。[注意:
a == b
暗示++a == ++b
的要求(对于输入和输出迭代器不是这样)并且通过可变迭代器去除对赋值数量的限制(适用)输出迭代器)允许使用带前向迭代器的多通道单向算法。 - 结束说明][表97省略]
- 如果
a
和b
相同,则a
和b
都可以取消引用,否则两者都不可取消引用。- 如果
a
和b
都可以取消引用,那么a == b
当且仅当*a
和*b
绑定到同一个对象时。
多次通过保证的目的似乎似乎是允许代码如下:
*iter <---------------------------------------------------
X iter_copy(iter); |
/* do something with iter_copy */ |
++iter_copy; ... ++iter_copy; |
/* iter has not changed, and *iter now is equivalent |
* to *iter before the operations on iter_copy */ |
*iter <---------------------------------------------------
然而,正式地说,多次通过保证似乎只暗示执行iter副本并递增副本会使*iter
保持不变,而后续的第二个增量iter_copy
可能会更改*iter
现在你的第一个想法可能就是&#34; duh,感应!&#34;,但它似乎达不到预期的结果;它说的是,如果我们复制iter_copy
并增加 副本,那么*iter_copy
就会保持不变,但它对原始*iter
没有任何说明。
问题:是否可以证明指定的多次通过保证意味着什么?
答案 0 :(得分:2)
当然,可能提出一个满足所有前向迭代器保证的类型,但不是完全多遍的。
class Evil {
int* p;
size_t idx;
public:
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = int;
using pointer = int*;
using reference = int&;
Evil() : p(nullptr), idx(0) { }
Evil(int* p, size_t idx) : p(p), idx(idx) { }
Evil(Evil const& ) = default;
Evil& operator=(Evil const& ) = default;
~Evil() = default;
// only p participates in comparison
bool operator==(Evil const& rhs) const {
return p == rhs.p && idx % 2 == rhs.idx % 2;
}
bool operator!=(Evil const& rhs) const { return !(*this == rhs); }
// incrementing is sort of destructive
Evil& operator++() {
++idx;
++p[idx % 2];
return *this;
}
Evil operator++(int) {
auto tmp = *this;
++*this;
return tmp;
}
int& operator*() { return p[idx % 2]; }
};
让我们完成要求:
a == b
暗示++a == ++b
。校验。 operator++()
甚至不会影响平等。 (void)*a, *a
相当于*a
。检查,解除引用不具有破坏性。(void)++X(a), *a
相当于*a
。校验。递增一个会更改 other int,而不是此迭代器当前“指向”的那个。所以这个条件也成立了。 a == b
iff *a
和*b
绑定到同一个对象。校验。 但是,(void)++++X(a), *a
绝对不等同于*a
。你会得到相同的int
,它只会是一个更大的。
我可以想出一个不符合保证的滑稽不切实际的迭代器这一事实可能表明实际的实际的迭代器也不符合保证。那里有很多C ++。