制作循环迭代器(循环器)的最简单方法?

tom*_*jen 13 c++ stdvector

我有一个对象,我想在游戏中连续循环旅行.我有一系列坐标std::vector,我想用作航点.

有没有办法制作std::vector<T>::iterator循环(也称为循环器)?

我能想到的最好的是拥有两个迭代器,然后每当第一个迭代器耗尽时,为它分配第二个迭代器的值(不会用于做任何其他事情)但我甚至不确定它是否会起作用 - 将赋值运算符复制迭代器用于保存索引的任何内容,还是只引用它(因此在第二轮之后将无用)?

我希望对象永远地沿着路点行进(除非它被破坏但在该方法中不会发生),但迭代器只会为每个帧调用一次并且必须返回以便我可以更新游戏中的其他对象.

该解决方案必须适用于gcc和microsoft编译器(如果无法在标准C++中编写它).

Seb*_*ian 22

好的,现在你的问题更清楚了:-)

看一下boost :: iterator_facade和boost :: iterator适配器.它们实现了完整的迭代器接口,并且cycle_iterator只能实现一些方法,如increment(),decrement():

template<class IteratorBase>
class cycle_iterator 
     : public boost::iterator_adaptor< 
          cycle_iterator,     // the derived class overriding iterator behavior
          IteratorBase,       // the base class providing default behavior
          boost::use_default, // iterator value type, will be IteratorBase::value_type
          std::forward_iterator_tag, // iterator category
          boost::use_default  // iterator reference type
       > 
{
  private:
     IteratorBase m_itBegin;
     IteratorBase m_itEnd;

  public:
     cycle_iterator( IteratorBase itBegin, IteratorBase itEnd ) 
       : iterator_adaptor_(itBegin), m_itBegin(itBegin), m_itEnd(itEnd)
     {}

     void increment() {
        /* Increment the base reference pointer. */
        ++base_reference();

        /* Check if past-the-end element is reached and bring back the base reference to the beginning. */
        if(base_reference() == m_itEnd)
            base_reference() = m_itBegin;
     }

     // implement decrement() and advance() if necessary
  };
Run Code Online (Sandbox Code Playgroud)

这可能不会编译,但应该让你开始.

编辑:

boost :: iterator_adaptor在少数函数方面实现了完整的迭代器接口.它提供默认实现increment(),decrement(),advance(),distance_to(),equal_to()dereference()使用基本的迭代向下传递到iterator_adaptor基类.

如果您只需要一个前向迭代器,则只有在increment()到达结束迭代器后才能实现该方法.如果decrement()以类似的方式实现,循环迭代器可以是双向的.如果IteratorBase它本身是随机访问迭代器,则循环迭代器也可以是随机访问和方法,advance并且distance_to必须使用模运算来实现.


小智 8

boost::iterator adaptor 是要走的路,接受我的话;)

话虽如此,我想指出一些陷阱.我不认为我可以编辑现有的答案,所以请耐心等待.

鉴于您的基础迭代器将成为一个向量,您需要注意您需要实现哪些核心接口函数.如果您希望自己cycle_iterator成为随机访问迭代器,则需要以下所有内容:

increment() 
decrement()
advance(n)
distance_to(j)
Run Code Online (Sandbox Code Playgroud)

现在distance_to(j)是一个有点滑稽的概念cycle_iterator,它的语义可以让你遇到各种麻烦.通过将适配迭代器的迭代器类别限制为正向或双向,可以避免这种情况.像这样:

template <class BaseIterator>
class cycle_iterator
  : public boost::iterator_adaptor<
        cycle_iterator                  // Derived
      , BaseIterator                    // Base
      , boost::use_default              // Value
      , boost::forward_traversal_tag    // CategoryOrTraversal
    >
{ ... };
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您只需要实现增量:

void increment()
{
  if (++this->base_reference() == this->m_itEnd)
  {
    this->base_reference() = this->m_itBegin;
  }
}
Run Code Online (Sandbox Code Playgroud)

对于双向,您还需要减少:

void decrement()
{
  if (this->base_reference() == this->m_itBegin)
  {
    this->base_reference() = this->m_itEnd;
  }
  --this->base_reference();
}
Run Code Online (Sandbox Code Playgroud)

免责声明:我没有通过编译器运行它,所以我准备好让自己感到尴尬.