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

发布于 2024-08-11 23:47:37 字数 418 浏览 2 评论 0原文

我有一个物体想要在游戏中连续循环移动。我在 std::vector 中有一系列坐标,我想将其用作路径点。

有什么方法可以使 std::vector::iterator 循环(也称为循环器)?

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

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

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

I have an object that I want to travel in a continuous loop in a game. I have a series of coordinates in a std::vector that I want to use as waypoints.

Is there any way to make an std::vector<T>::iterator cyclic (also known as a circulator)?

The best I can come up with is to have two iterators and then whenever the first iterator is exhausted assign to it the value of the second (which would not be used to do anything else) but I am not even sure it will work - will the assignment operator copy whatever the iterator is using to hold the index or will it merely be referenced (and therefore will be useless after the second round)?

I want the object to travel the waypoint forever (unless it is destroyed but that doesn't happen in that method), but the iterator will only be called once for each frame and must return so that I can update the other objects in the game.

The solution must work on gcc and microsoft compiler (if it isn't possible to write it in standard C++).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

南城旧梦 2024-08-18 23:47:37

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

看一下 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()、< code>equal_to() 和 dereference() 使用向下传递给 iterator_adaptor 基类的基迭代器。

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

Ok, now your problem is clearer :-)

Take a look at boost::iterator_facade and boost::iterator adaptor. They implement the full iterator interface and your cycle_iterator only as to implement a few methods like 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
  };

This probably doesn't compile but should get you started.

Edit:

boost::iterator_adaptor implements the full iterator interface in terms of few functions. It provides default implementations for increment(), decrement(), advance(), distance_to(), equal_to() and dereference() using the base iterator passed down to the iterator_adaptor base class.

If all you need is a forward iterator, only the increment() method must be implemented to wrap around once you reach the end iterator. A cyclical iterator can be bidirectional if you implement decrement() in a similar fashion. If IteratorBase is itself a random access iterator, the cycle iterator can also be random access and method advance and distance_to must be implemented using modulo operations.

苏大泽ㄣ 2024-08-18 23:47:37

boost::iterator 适配器是正确的方法,相信我的话;)

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

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

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

现在 distance_to(j) 对于 cycle_iterator 来说是一个有点有趣的概念code> 及其语义可能会给您带来各种麻烦。这可以通过将适配迭代器的迭代器类别限制为前向或双向来避免。像这样:

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();
}

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

boost::iterator adaptor is the way to go, take my word for it ;)

That being said I want to point out a few pitfalls. I don't think I can edit an existing answer, so bear with me.

Given that your base iterator is going to be a vector you need to be careful which core interface functions you need to implement. If you want your cycle_iterator to be a random access iterator you need all of the following:

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

Now distance_to(j) is a somewhat funny concept for a cycle_iterator and its semantics can get you in all kind of trouble. This can be avoided by restricting the iterator category of the adapted iterator to either forward or bidirectional. Like this:

template <class BaseIterator>
class cycle_iterator
  : public boost::iterator_adaptor<
        cycle_iterator                  // Derived
      , BaseIterator                    // Base
      , boost::use_default              // Value
      , boost::forward_traversal_tag    // CategoryOrTraversal
    >
{ ... };

In this case you only need to implement increment:

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

For a bidirectional you also need decrement:

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

Disclaimer: I did not run this through a compiler, so I am ready to be embarrassed.

御守 2024-08-18 23:47:37

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

网上有很多教程。例如,看看这个博客文章

Derive your own collection from std::vector and provide your own iterator implementation that overrides the increment & decrement operators.

There are plenty of tutorials on the web. For example, take a look at this blog post

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文