【发布时间】:2021-04-10 21:07:20
【问题描述】:
我正在处理ReversibleContainer 及其关联的LegacyRandomAccessIterators。它们包装了一个预先存在的数据结构,该结构表示可直接索引的对象集合。我决定让迭代器独立存在,并让默认构造的迭代器代表“结束”:
// constructs an iterator that provides a view of 'data'
the_iterator (thedata *data, difference_type index = 0);
// constructs an iterator representing the end
the_iterator ();
所以我可以这样做例如:
std::for_each(the_iterator(data), the_iterator(), ...);
迭代器完成所有工作。容器非常轻巧。我像这样实现了容器的begin() 和end():
struct the_container {
the_data *data; // <- object wrapped by this container
the_iterator begin () { return the_iterator(data); }
the_iterator end () { return the_iterator(); }
};
我已经让它工作得很好,但在测试中我意识到我搞砸了,它不符合基本的Container 要求,因为:
- 事实证明,对于具有双向迭代器的容器,
end()is required to return a decrementable iterator 当容器非空时,但 - 我的默认构造的结束迭代器不存储关于任何
thedata的任何信息,因此它不能被递减,因为它不知道任何特定集合的“最后一个元素”是什么。李>
所以我现在必须修复容器。我正在考虑的解决方案是(让data->number_of_items 包含项目数):
- 继续允许默认构造的迭代器表示“结束”。
- 还让
the_iterator(data, data->number_of_items)代表“结束”,符合容器要求。这个迭代器是可递减的。
那么容器会这样做:
struct the_container {
the_data *data; // <- object wrapped by this container
the_iterator begin () { return the_iterator(data, 0); }
the_iterator end () { return the_iterator(data, data->number_of_items); }
};
现在,这很好,它满足所有 Container 要求。但是,我现在想知道是否允许我的默认构造的迭代器存在。
那么,我的问题是:虽然 Container 对从 end() 返回的迭代器提出了递减要求,但对于仅代表“结束”的迭代器是否有类似的要求? "的一些数据但不涉及容器的end()?
更正式地说,如果:
-
j是一个双向迭代器 container.empty() == false( j == container.end() ) == true
那么--j 是否需要有效并且需要最终指向容器的最后一个元素?就我而言,这种情况的一个例子是:
the_container container(data); // <- assume data->number_of_items > 0
the_iterator b = container.begin();
the_iterator e = container.end();
the_iterator j;
assert(container.empty() == false);
assert(e == j);
assert(distance(b, e) == distance(b, j));
-- e; // <- this is required to be well-defined
-- j; // <- but is this??
所以,是的,这是我的问题。我担心可能会在例如<algorithm> 可能会假设我的“结束”迭代器之一是可递减的,或者我正在破坏一些我不理解的微妙内容。
【问题讨论】:
-
我希望这个问题有意义;很难用语言表达。
标签: c++ iterator containers c++17 language-lawyer