如何处理多个迭代器类型
How to handle multiple iterator types
我有一个定制的数据结构,可以通过多种方式访问它。我希望尽可能保持这个数据结构符合stl标准。我已经有了很多类型定义,它们为模板参数提供了stl名称。到目前为止,这对我来说是家常便饭。
然而,我不确定如何正确地将迭代器添加到我的数据结构中。我面临的主要问题是,在数据结构上会有多个迭代策略。最简单的用例是遍历所有元素,这可以由符合stl的迭代器在数据结构上很好地处理。但是,也可能需要访问与给定键类似的元素。我还想以一种我可以与STL接口的方式迭代所有这些类似的元素。
这些是我目前为止考虑过的想法:
- 只提供一种类型的迭代器:
这基本上是std::map
所做的。子范围的开始迭代器和结束迭代器由std::map::lower_bound()
和std::map::upper_bound()
提供。
然而,这工作得很好,因为begin()
, end()
, lower_bound()
和upper_bound()
返回的迭代器是兼容的,也就是说,operator==()
可以在这些迭代器上给出一个非常明确的含义。在我的情况下,这将很难得到正确的,或者甚至可能不可能给出一些明确的语义。例如,我可能会得到一些it1==it2
但++it1!=++it2
的情况。我不确定STL是否允许这样做。
- 提供多种类型的迭代器:
更容易提供干净的operator==()
语义。另一方面,Nasty是因为它增加了类型的数量。
- 提供一种类型的迭代器并使用stl::算法进行专门化访问
我不确定这是否可能。迭代器应该以某种方式(直接或在Memento中)保存迭代状态。使用这种方法意味着专门化所有stl::算法并在专门化中直接访问谓词。很可能不可能,如果可能的话,这是一个非常糟糕的主意。
现在我主要选择版本1,即只提供一种类型的迭代器。然而,由于我不清楚如何清理语义,我还没有决定。
你会如何处理这种情况?
标准容器支持两种迭代策略,具有两种迭代器类型:::iterator
和::reverse_iterator
。您可以使用std::reverse_iterator
的构造函数及其成员函数base()
在两者之间进行转换。
根据迭代策略的相似程度,提供到不同迭代器类型的转换可能很容易,也可能不容易。其思想是,结果应该指向目标类型的迭代策略中的"等效位置"。对于反向迭代器,这种等价的定义是,如果在该点插入,结果是相同的。因此,如果rit
是反向迭代器,则vec.insert(rit.base(), ...)
在逆向迭代中插入一个元素"在"rit
之前,也就是说,在容器中rit
所指向的元素之后插入元素。这是非常繁琐的,并且只会在迭代策略完全不相关时变得更糟。但是,如果所有的迭代器类型都是(或者看起来像是)遍历所有元素的"普通"迭代器的包装器,那么就可以根据底层迭代器的位置定义转换。
实际上只有在存在添加或删除容器元素的成员函数时才需要转换,因为您可能不希望必须为每种迭代器类型提供单独的重载(就像标准容器没有为反向迭代器定义insert
和erase
一样)。如果迭代器仅用于指向元素,那么很可能不需要它们。
如果不同的迭代策略都在元素的子集上以正常顺序迭代,则查看boost::filter_iterator
。
我可能会得到一些
it1==it2
但++it1!=++it2
的情况。我是不确定STL是否允许。
如果我理解正确的话,你从thing.normal_begin()
开始得到it1
,从thing.other_policy_begin()
开始得到it2
。标准容器没有定义比较属于不同范围的相同类型的迭代器的结果,所以如果您确实使用了公共类型,那么我认为这将是好的,只要文档明确说明尽管operator==
确实有效,但范围是根据迭代器的来源分开的。
例如,可以有一个skip_iterator
,它将每次调用++
时应该向前移动的步数作为构造函数参数。然后你可以在比较中包含这个整数,这样thing.skip_begin(1) != thing.skip_begin(2)
,或者你可以排除它,这样thing.skip_begin(1) == thing.skip_begin(2)
但是++(++(thing.skip_begin(1))) == ++(thing.skip_begin(2))
。我认为只要有文档就可以,或者你可以证明比较它们是UB,除非它们来自相同的起点。
为什么类型多是个问题?这并不一定意味着更多的代码。例如,您可以创建一个迭代器类型的模板,该模板将迭代策略作为模板参数。然后迭代策略可以提供迭代的实现:
struct iterate_all_policy {
iterate_all_policy(iterator<iterate_all_policy> & it) : it(it) {}
void advance() { /* implement specific advance here */ }
private:
iterator<iterate_all_policy> & it;
}
您可能必须将迭代策略类设置为迭代器类型的朋友。
- 如何在c++迭代器类型中包装std::chrono
- 定义模板参数的迭代器类型
- C++如何乘以包含 std::variant 元素的向量的迭代器?正在执行迭代器类型的转换?
- C++不兼容的迭代器类型
- 如何推导 std::高级迭代器类型?
- 在 stl 容器包装器中定义迭代器类型
- 矢量迭代器类型未知
- STD ::向量迭代器类型和允许的操作
- 检查容器模板类中的迭代器类型
- 如何断言模板参数的类型 STL 迭代器类型
- 检测容器是否具有迭代器类型
- 由set2.begin()返回的迭代器类型
- 序列容器的迭代器类型是什么?
- 如何推断嵌套最多的迭代器类型
- 为什么迭代器类型与矢量容器中的 value_type * 不匹配
- ISO C++禁止声明没有自动迭代器类型的“it”
- 使用的迭代器类型错误
- 列表的迭代器类型
- 如何打印迭代器类型列表<pair<int,int>>::iterator itrator it指向的元素
- 为什么 void* 不是迭代器类型?