C++ Can a C++;类导出几个不同的stl样式迭代器?

C++ Can a C++;类导出几个不同的stl样式迭代器?,c++,stl,iterator,C++,Stl,Iterator,我有一个类,它封装了一个奇特的数据结构。为了回答这个问题,我们假设它是一个由东西组成的容器 我们在这个容器中有很多地方迭代Thingys,但是有几种不同的方法可以这样做-它们可以按顺序A或B迭代,也有子集X和Y,所以(比如)有四种方式可以迭代Thingys(按顺序A的子集X,按顺序Y的子集X,等等) 我想创建一个自定义迭代器容器,这样我就可以使用C++基于语法的范围来循环东西可以从一个类导出多个不同的迭代器吗?显然我不能只导出一个迭代器 class Container { ... it

我有一个类,它封装了一个奇特的数据结构。为了回答这个问题,我们假设它是一个由
东西组成的
容器

我们在这个容器中有很多地方迭代
Thingy
s,但是有几种不同的方法可以这样做-它们可以按顺序A或B迭代,也有子集X和Y,所以(比如)有四种方式可以迭代Thingys(按顺序A的子集X,按顺序Y的子集X,等等)

我想创建一个自定义迭代器
容器
,这样我就可以使用C++基于语法的范围来循环
东西可以从一个类导出多个不同的迭代器吗?显然我不能只导出一个迭代器

class Container { 
  ...
  iter begin();
  iter end();
}
因为将有四种不同的
iter
那么,我如何告诉我的范围基于哪种
iter
使用?


我应该补充一点,这是在一个完全对性能至关重要的环境中,因此我们不能容忍回调函数的成本。否则,我将使用map(λ)类型的处理,但在这种情况下,我们需要花费纳秒的时间,如果迭代器引起额外的间接函数调用(因此分支预测失误),我将不得不坚持使用我们目前丑陋的方法来迭代容器。

您可以编写一个范围

template<class It>
struct range_t {
  It s, f;
  It begin() const { return s; }
  It end() const { return f; }
};
template<class It>
range_t<It> range( It s, It f ) { return {std::move(s), std::move(f)}; }
模板
结构范围{
它是s,f;
它的begin()常量{return s;}
It end()常量{return f;}
};
模板
range_t range(It s,It f){return{std::move(s),std::move(f)};}
现在,您公开了一些方法,这些方法为您的各种迭代方式返回适当迭代器类型的
range\t

这些函数可以是成员函数,也可以是无好友函数,具体取决于所需的语法

迭代发生的方式可以在类型系统中进行硬编码,消除任何“回调”开销,
range\u t
足够轻量级,应该完全优化它们

(请注意,上面是一个非常精简的
范围
:如果迭代器是随机访问的,
可能会有
空的
前面
后面
没有
的范围
,甚至
操作符[]
有条件地支持)。

您编写了一个范围

template<class It>
struct range_t {
  It s, f;
  It begin() const { return s; }
  It end() const { return f; }
};
template<class It>
range_t<It> range( It s, It f ) { return {std::move(s), std::move(f)}; }
模板
结构范围{
它是s,f;
它的begin()常量{return s;}
It end()常量{return f;}
};
模板
range_t range(It s,It f){return{std::move(s),std::move(f)};}
现在,您公开了一些方法,这些方法为您的各种迭代方式返回适当迭代器类型的
range\t

这些函数可以是成员函数,也可以是无好友函数,具体取决于所需的语法

迭代发生的方式可以在类型系统中进行硬编码,消除任何“回调”开销,
range\u t
足够轻量级,应该完全优化它们



(请注意,上面是一个非常精简的
范围
:如果迭代器是随机访问的,则真实的范围可能有
空的
前面
后面
没有
的范围
,甚至有条件地支持
操作符[]
).

我想你不仅仅是指常量迭代器和非常量迭代器?但是,例如,正向迭代器与反向迭代器?不幸的是,范围仅适用于仅使用
begin
end
,没有其他任何其他功能。您可以拥有一些特定于目的的代理对象,每个代理对象都会暴露它们自己的开始/结束对
for(auto&x:my_container.some_range())
@KerrekSB如果你把你的评论扩展成一个答案,我可以向上投票。@Someprogrammerdude它更像是“向前”vs“向前”,过滤器x“vs”按照完全不同的结构指定的顺序”@Crashworks:我认为Yakk已经提供了一个更为一般的答案,并将我的建议作为一个特例纳入其中:-)我想你不仅仅是指常量迭代器和非常量迭代器?但是,例如,正向迭代器与反向迭代器?不幸的是,范围仅用于
开始
结束
,其他用途除外。您可以有几个特定于用途的代理对象,每个对象都公开自己的开始/结束对
for(auto&x:my_container.some_range())
@KerrekSB如果你把你的评论扩展成一个答案,我可以向上投票。@Someprogrammerdude它更像是“向前”vs“向前”,过滤器x“vs”按照完全不同的结构指定的顺序”@Crashworks:我认为Yakk已经提供了一个更为一般的答案,并将我的建议作为一个特例纳入其中:-)来结束这个问题:Yakk的建议起了作用,但基于for的范围最终比我们使用的手动
for
循环慢了2倍(从另一个缓冲区过滤的lookaside缓冲区等中查找索引的数组),因此在这种情况下,我们最终不能使用范围。@Crashworks的可能性是,我可以使迭代器版本与手册中可怕的for循环匹配。遗憾的是,NDA阻止我共享具有代表性的代码片段(我试着做的那件脱下来的衣服没有显示出问题)我用一个边框中生成的程序集进行了相当长的一段时间的修整…看来VC++坚持在迭代迭代器对象上非常有力地复制。如果我找到一种方法来复制代码片段中的问题,我会发布一个关于它的博客并回来这里邀请您的反馈。@ CRASHOWORKS,考虑填充MOR。将状态转换为“range”对象(它不必像上面我的迭代器那样赤裸裸),在迭代器中只有在迭代过程中发生变化的东西。pre-C++17
for(:)
循环的唯一缺点是缺少Sentinal选项(因此需要使用“标志”)使用分支成本标记结束迭代器;高度可预测,但会消耗一个分支缓存项)。是的,迭代器应该是optimiz