自定义容器上的C++“周期”迭代器

自定义容器上的C++“周期”迭代器,c++,stl,iterator,containers,C++,Stl,Iterator,Containers,我有一个包含特定类元素向量的类。其主要思想是根据序列元素的一个周期和周期数nperiod生成元素的周期序列,因此我不需要存储所有元素,只需要存储一个周期 类周期容器 { 私人: std::vector elems_;//元素 大小\u t n周期\u;//元素的重复周期_ 公众: 周期容器; PeriodicContainerconst标准::向量和元素,大小和周期; /*...*/ } 是否可以为PeriodicContainer实现自定义迭代器,以便我可以执行类似于半伪代码的操作: Peri

我有一个包含特定类元素向量的类。其主要思想是根据序列元素的一个周期和周期数nperiod生成元素的周期序列,因此我不需要存储所有元素,只需要存储一个周期

类周期容器 { 私人: std::vector elems_;//元素 大小\u t n周期\u;//元素的重复周期_ 公众: 周期容器; PeriodicContainerconst标准::向量和元素,大小和周期; /*...*/ } 是否可以为PeriodicContainer实现自定义迭代器,以便我可以执行类似于半伪代码的操作:

PeriodicContainer container({Class(1), Class(2)}, 4);
for (auto it : container)
  std::cout << it << '\n';

如果您的底层容器只是一个std::vector,那么您就知道它是一个连续的容器——这实际上使这非常容易

您可以从以下内容形成迭代器:

指向正在迭代的容器的指针或引用,以及 当前迭代计数注:不是“索引”。在包装容器大小后,它将用作基础容器运算符[]的索引。 此迭代器的行为很简单:

每个增量只会增加当前计数 每个解引用都返回*elems_u[current_u%elems_uu->size],这将解释周期内的循环。 begin只返回一个计数为0的迭代器,然后 end将返回一个迭代器,其中包含元素的计数_ 下面是一个示例,说明了这可能是一个什么样的问题:

样板 类周期容器运算符 { 公众: 使用值_type=T; 使用reference=T&; 使用指针=T*; 使用差分类型=std::ptrdiff\t; 使用迭代器\u category=std::forward\u迭代器\u标记; PeriodicContainerInteratorsTD::vector*元素,std::大小\u t当前 :elems_{elems}, 当前{current} {} 参考运算符*{ return*elems\[当前元素->大小] } 指针运算符->{ 返回&*elems\[当前元素->大小]; } PeriodicContainerInterator和运算符++常量{ ++电流; 归还*这个; } PeriodicContainerInterator运算符++int常量{ 自动复制=*此; ++电流; 返回副本; } 布尔运算符==常量PeriodicContainerInterator和其他常量{ 返回当前值==其他当前值; } 布尔运算符!=常量周期容器运算符和其他常量{ 返回当前值\!=其他当前值\; } 私人: 标准::向量*元素; 标准::大小\u t电流\u; }; 然后,容器将开始和结束定义为:

周期集装箱运输机开始{ 返回周期ContainerInterator{&elems_,0}; } 周期容器器端{ 返回periodicContainerInterator{&elems,elems->size*nperiod}; } 您可以很容易地将其一直扩展到a,但这需要很多额外的函数,这些函数将使这个答案成堆

如果您不特别需要它作为迭代器,而只是想要一种简单的方法来访问周期序列中的每个元素,那么如果您将它变成一个类似于for_each的调用,而该调用需要回调,那么阅读/理解可能会更容易。例如:

样板 无效forEachFn&&fn { 对于自动i=0;i container.forEach[&]auto&e{ //“e”是每个访问的元素 };
如果您的底层容器只是一个std::vector,那么您就知道它是一个连续的容器——这实际上使这非常容易

您可以从以下内容形成迭代器:

指向正在迭代的容器的指针或引用,以及 当前迭代计数注:不是“索引”。在包装容器大小后,它将用作基础容器运算符[]的索引。 此迭代器的行为很简单:

每个增量只会增加当前计数 每个解引用都返回*elems_u[current_u%elems_uu->size],这将解释周期内的循环。 begin只返回一个计数为0的迭代器,然后 end将返回一个迭代器,其中包含元素的计数_ 下面是一个示例,说明了这可能是一个什么样的问题:

样板 类周期容器运算符 { 公众: 使用值_type=T; 使用reference=T&; 使用指针=T*; 使用差分类型=std::ptrdiff\t; 使用迭代器\u category=std::forward\u迭代器\u标记; PeriodicContainerInteratorsTD::vector*元素,std::大小\u t当前 :elems_{elems}, 当前{current} {} 参考运算符*{ return*elems\[当前元素->大小] } 指针运算符->{ 返回&*elems\[当前元素->大小]; } PeriodicContainerInterator和运算符++常量{ ++电流; 归还*这个; } PeriodicContainerInterator运算符++int常量{ 自动复制= *这,; ++电流; 返回副本; } 布尔运算符==常量PeriodicContainerInterator和其他常量{ 返回当前值==其他当前值; } 接线员=const PeriodicContainerInterator和其他const{ 返回当前值\!=其他当前值\; } 私人: 标准::向量*元素; 标准::大小\u t电流\u; }; 然后,容器将开始和结束定义为:

周期集装箱运输机开始{ 返回周期ContainerInterator{&elems_,0}; } 周期容器器端{ 返回periodicContainerInterator{&elems,elems->size*nperiod}; } 您可以很容易地将其一直扩展到a,但这需要很多额外的函数,这些函数将使这个答案成堆

如果您不特别需要它作为迭代器,而只是想要一种简单的方法来访问周期序列中的每个元素,那么如果您将它变成一个类似于for_each的调用,而该调用需要回调,那么阅读/理解可能会更容易。例如:

样板 无效forEachFn&&fn { 对于自动i=0;i container.forEach[&]auto&e{ //“e”是每个访问的元素 };
如果可以使用range-v3,则可以执行以下操作:

namespace rv = ranges::views;    

std::vector<Class> Container { Class(1), Class(2) };

for (auto it : rv::repeat_n(Container, 4) | rv::join)
    std::cout << it;
而且不必自己编写任何额外的代码。这也适用于任何连续的容器,而不仅仅是std::vector


这里有一个。

如果您可以使用range-v3,您可以执行以下操作:

namespace rv = ranges::views;    

std::vector<Class> Container { Class(1), Class(2) };

for (auto it : rv::repeat_n(Container, 4) | rv::join)
    std::cout << it;
而且不必自己编写任何额外的代码。这也适用于任何连续的容器,而不仅仅是std::vector


下面是一个。

您可以调整任意RandomAccessIterator,使其表现为这样。在这种情况下,只需签入到达末尾的++操作符,然后返回到开头。这是否回答了您的问题?您可以调整任意RandomAccessIterator,使其行为如下。在这种情况下,只需签入到达末尾的++操作符,然后返回到开头。这是否回答了您的问题?您将如何为自定义容器实现这一点,而不是专门为std::vector实现这一点?OP特别将自定义容器放在标题中。基于RandomAccessIterator的实现将更有意义,它将适用于任何提供RandomAccessIterator的容器。另一方面,您应该在构造函数中使用std::vector&并将其转换为指针。您不想接受可为null的参数,那么为什么不使用引用呢?这是自定义容器的迭代器-它是专门根据PeriodicContainer的实现编写的,这就是所要求的。在底层容器上工作的迭代器通常是紧密耦合的。至于参考与参数点:这是一个意见问题。指针并不意味着可为空,而是意味着在调用站点更容易读取,因为这是捕获对象的非所有权生存期,例如&elems_uu,而不是elems_u,对于生存期捕获来说,elems_uu不是那么容易读取。现在我理解了您的方法。以这样一种特定的方式实现周期迭代器这样的泛型概念似乎是违反直觉的,因为它只适用于单个类。但我想这使得这个例子很简单。至于指针与引用约定,指针在技术上总是可以为null的,这总是导致您是否可以传递nullptr的问题。除此之外,这个论点是基于观点的,不值得讨论!我一定会在我的代码中使用它。实际上,我想做一些类似的事情,但由于缺乏经验,我决定在这里提问。但是,您如何为自定义容器而不是专门为std::vector实现这一点?OP特别将自定义容器放在标题中。基于RandomAccessIterator的实现将更有意义,它将适用于任何提供RandomAccessIterator的容器。另一方面,您应该在构造函数中使用std::vector&并将其转换为指针。您不想接受可为null的参数,那么为什么不使用引用呢?这是自定义容器的迭代器-它是专门根据PeriodicContainer的实现编写的,这就是所要求的。在底层容器上工作的迭代器通常是紧密耦合的。至于参考与参数点:这是一个意见问题。指针并不意味着可为空,而是意味着在调用站点更容易读取,因为这是捕获对象的非所有权生存期,例如&elems_uu,而不是elems_u,对于生存期捕获来说,elems_uu不是那么容易读取。现在我理解了您的方法。以这样一种特定的方式实现周期迭代器这样的泛型概念似乎是违反直觉的,因为它只适用于单个类。但我想这使得这个例子很简单。至于指针与引用约定,指针在技术上总是可以为null的,这总是导致您是否可以传递nullptr的问题。除了
这个论点真的是基于观点的,不值得讨论!我一定会在我的代码中使用它。事实上,我想做这样的事情,但由于缺乏经验,我决定在这里提问。