创建我自己的迭代器

时间:2008-09-29 12:54:06

标签: c++ iterator

我正在努力学习C ++,请原谅我,如果这个问题表明缺乏基础知识,你会发现,事实是,我缺乏基础知识。

我想要一些帮助来解决如何为我创建的类创建迭代器。

我有一个'Shape'类,它有一个Points容器。 我有一个类'Piece'引用一个Shape并定义Shape的位置。 Piece没有Shape,只是引用了Shape。

我希望它看起来像是一个Point的容器,它与它引用的Shape相同,但是添加了Piece的位置的偏移量。

我希望能够遍历Piece的点,就像Piece本身就是一个容器一样。我已经做了一点阅读,但没有找到任何帮助我的东西。我会非常感谢任何指示。

6 个答案:

答案 0 :(得分:61)

/编辑:我知道,这里实际上需要一个自己的迭代器(我先误读了这个问题)。不过,我让下面的代码保持不变,因为它在类似情况下很有用。


这里有一个自己的迭代器吗?也许将所有必需的定义转发到容纳实际点的容器就足够了:

// Your class `Piece`
class Piece {
private:
    Shape m_shape;

public:

    typedef std::vector<Point>::iterator iterator;
    typedef std::vector<Point>::const_iterator const_iterator;

    iterator begin() { return m_shape.container.begin(); }

    const_iterator begin() const { return m_shape.container.begin(); }

    iterator end() { return m_shape.container.end(); }

    const_iterator end() const { return m_shape.const_container.end(); }
}

假设您在内部使用vector,但可以轻松调整类型。

答案 1 :(得分:40)

您应该使用Boost.Iterators。它包含许多模板和概念,用于为现有迭代器实现新的迭代器和适配器。我写过an article about this very topic;它出现在2008年12月的ACCU杂志上。它讨论了一个(IMO)优雅的解决方案,完全解决您的问题:使用Boost.Iterators从对象公开成员集合。

如果只想使用stl,Josuttis book有一章介绍如何实现自己的STL迭代器。

答案 2 :(得分:20)

这里Designing a STL like Custom Container是一篇很好的文章,它解释了如何设计类似容器类的STL以及它的迭代器类的一些基本概念。反向迭代器(稍微强硬)虽然留作练习: - )

HTH,

答案 3 :(得分:14)

您可以阅读此ddj article

基本上,继承自std :: iterator以完成大部分工作。

答案 4 :(得分:1)

问题的解决方案不是创建自己的迭代器,而是使用现有的STL容器和迭代器。将每个形状的点存储在像vector这样的容器中。

class Shape {
    private:
    vector <Point> points;

从那时起你做什么取决于你的设计。最好的方法是迭代Shape中方法中的点。

for (vector <Point>::iterator i = points.begin(); i != points.end(); ++i)
    /* ... */

如果你需要访问Shape之外的点(这可能是设计不足的标记),你可以在Shape方法中创建将返回点的迭代器访问函数(在这种情况下也为点容器创建一个公共typedef) )。请看Konrad Rudolph关于这种方法的详细解答。

答案 5 :(得分:1)

用C ++编写自定义迭代器可能非常冗长和复杂,无法理解。

由于我找不到编写自定义迭代器的最小方法,因此编写this template header可能有所帮助。例如,要使Piece类可迭代:

#include <iostream>
#include <vector>

#include "iterator_tpl.h"

struct Point {
  int x;
  int y;
  Point() {}
  Point(int x, int y) : x(x), y(y) {}
  Point operator+(Point other) const {
    other.x += x;
    other.y += y;
    return other;
  }
};

struct Shape {
  std::vector<Point> vec;
};

struct Piece {
  Shape& shape;
  Point offset;
  Piece(Shape& shape, int x, int y) : shape(shape), offset(x,y) {}

  struct it_state {
    int pos;
    inline void next(const Piece* ref) { ++pos; }
    inline void begin(const Piece* ref) { pos = 0; }
    inline void end(const Piece* ref) { pos = ref->shape.vec.size(); }
    inline Point get(Piece* ref) { return ref->offset + ref->shape.vec[pos]; }
    inline bool cmp(const it_state& s) const { return pos != s.pos; }
  };
  SETUP_ITERATORS(Piece, Point, it_state);
};

然后您就可以将它用作普通的STL容器:

int main() {
  Shape shape;
  shape.vec.emplace_back(1,2);
  shape.vec.emplace_back(2,3);
  shape.vec.emplace_back(3,4);

  Piece piece(shape, 1, 1);

  for (Point p : piece) {
    std::cout << p.x << " " << p.y << std::endl;
    // Output:
    // 2 3
    // 3 4
    // 4 5
  }

  return 0;
}

它还允许添加其他类型的迭代器,如const_iteratorreverse_const_iterator

我希望它有所帮助。