14

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

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

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

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

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

4

3 回答 3

23

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

看看 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
  };

这可能无法编译,但应该可以帮助您入门。

编辑:

boost::iterator_adaptor用几个函数实现了完整的迭代器接口。increment()它提供了、decrement()advance()、的默认实现distance_to()equal_to()dereference()使用向下传递给iterator_adaptor基类的基迭代器。

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

于 2009-11-23T10:27:49.057 回答
8

boost::iterator adaptor是要走的路,相信我的话;)

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

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

increment() 
decrement()
advance(n)
distance_to(j)

现在distance_to(j)对于 a 来说是一个有点有趣的概念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
    >
{ ... };

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

void increment()
{
  if (++this->base_reference() == this->m_itEnd)
  {
    this->base_reference() = this->m_itBegin;
  }
}

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

void decrement()
{
  if (this->base_reference() == this->m_itBegin)
  {
    this->base_reference() = this->m_itEnd;
  }
  --this->base_reference();
}

免责声明:我没有通过编译器运行它,所以我准备好尴尬了。

于 2009-11-23T18:58:28.810 回答
-4

从 std::vector 派生您自己的集合并提供您自己的迭代器实现来覆盖增量和减量运算符。

网上有很多教程。例如,看看这篇博文

于 2009-11-23T10:42:48.453 回答