我有一个对象,我想在游戏中连续循环旅行。我在std::vector
中有一系列坐标,我想用作航路点。
有没有办法制作std::vector<T>::iterator
循环(也称为循环器)?
我能想到的最好的是拥有两个迭代器,然后每当第一个迭代器耗尽时,为它分配第二个的值(不会用来做任何其他事情),但我甚至不确定它是否会work - 赋值运算符是否会复制迭代器用于保存索引的任何内容,或仅仅引用它(因此在第二轮之后将无用)?
我希望对象永远地沿着路点行进(除非它被破坏但在该方法中不会发生),但迭代器只会为每个帧调用一次并且必须返回以便我可以更新其他对象在游戏中。
解决方案必须适用于gcc和microsoft编译器(如果无法在标准C ++中编写它)。
答案 0 :(得分:21)
好的,现在你的问题更清楚: - )
看一下boost :: iterator_facade和boost :: iterator适配器。它们只实现了一些方法,比如increment(),decrement():
cycle_iterator
这可能不会编译,但应该让你开始。
编辑:
boost::iterator_adaptor根据少数函数实现完整的迭代器接口。它使用传递给{{的基础迭代器为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
};
,increment()
,decrement()
,advance()
,distance_to()
和equal_to()
提供默认实现。 1}}基类。
如果您只需要一个前向迭代器,那么只有dereference()
方法必须实现,以便在到达结束迭代器时回绕。如果以类似的方式实现iterator_adaptor
,则循环迭代器可以是双向的。如果increment()
本身是一个随机访问迭代器,则循环迭代器也可以是随机访问,方法decrement()
和IteratorBase
必须使用模运算来实现。
答案 1 :(得分:7)
boost::iterator adaptor
是要走的路,接受我的话;)
话虽如此,我想指出一些陷阱。我不认为我可以编辑现有的答案,所以请耐心等待。
鉴于你的基础迭代器将成为一个向量,你需要注意你需要实现哪些核心接口函数。如果您希望cycle_iterator
成为随机访问迭代器,则需要以下所有内容:
increment()
decrement()
advance(n)
distance_to(j)
现在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
>
{ ... };
在这种情况下,您只需要实现增量:
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();
}
免责声明:我没有通过编译器运行,所以我准备好让自己感到尴尬。
答案 2 :(得分:-4)
从std :: vector派生你自己的集合,并提供你自己的迭代器实现来覆盖增量和放大器。减少运营商。
网上有很多教程。例如,请查看this blog post