为非stl容器创建自己的迭代器

时间:2014-04-01 17:46:19

标签: c++ stl iterator

我有一个管理数据的课程。

我希望只返回其中的一部分数据,但由于这是一个多次完成的过程,我不希望只是将数据复制到容器中并返回容器。

如果我可以发送引用或类似的东西,那将是很好的。想到了迭代器。但是因为我使用 Eigen3 Matrix (它没有迭代器(无论如何都是2D矩阵))

我在考虑模拟(?)迭代器的行为, 类似的东西:

typedef unsigned int Index;

class MatrixIterator
{
public:
    MatrixIterator(Eigen::MatrixXd *m, Index min, Index max):
        _col(0), _index(0), _min(min), _max(max), _matrix(m)
    {}

    void operator++ ()   
    {
        if (_index + _min + 1 != _max)
            _index++; 
    }
    void operator--()
    {
        if (_index != _min)
            _index--; 
    }

    double operator*()
    { 
        return _matrix->operator() (_index + _min, _col); 
    }

    void setCol(Index col)  {   _col = col; }

    Index min() {   return _min;    }
    Index max() {   return _max;    }

private:
    // the matrix is 2D we can select
    // on which column we want to iterate
    Index _col;

    // current position
    Index _index;

    // select the range on which the user can iterate
    Index _max;
    Index _min;

    // the matrix on which we want to iterate over
    Eigen::MatrixXd* _matrix;
}
  • 我之前从未真正使用过迭代器,这是正确的吗?
  • 我可以从MatrixIterator继承我的std::iterator,以便stl能够将其理解为通常的迭代器吗?
  • 你知道更好的办法吗?

我读过:

编辑:我想迭代矩阵的一部分(这就是为什么我有_min和_max),我操作的数据是时间序列,所以数据已经被排序。 我认为我们可以将MatrixIterator视为对数据查询的响应。

1 个答案:

答案 0 :(得分:2)

  

我之前从未真正使用过迭代器,它是否正确?

这是一个好的开始。这个想法是正确的,但你遗漏了一些东西。首先,您没有足够的运营商。确保检查reference并提供您可以合理提供的每个操作员(唯一可能有用或无用的是随机访问操作员,因为在这种情况下可能更难实施)。其次,您需要为迭代器类提供iterator traits。这通常是通过在迭代器类中创建必要的嵌套typedef来完成的(您也可以为您的类专门设置std::iterator_traits模板,但我会说这只是在您真的无法添加嵌套的typedef时)。

  

我可以从std::iterator继承我的MatrixIterator,以便stl能够将其理解为通常的迭代器吗?

不,一般来说,你不应该继承std::iterator类。 STL是模板库(通用编程(GP)),因此不使用OOP中的基类继承模型。 STL算法将迭代器作为模板参数,并且通常会根据算法的要求使用它们(或者尽可能地使用与迭代器类型相关联的iterator_category特性)。这是generic programming,而不是面向对象的编程,它是苹果和橘子。

  

你知道更好的方法吗?

嗯,一种方便的方法是使用像boost::iterator_facade这样的类模板(参见ref),它提供了一种自动“填空”机制来创建迭代器。它使用众所周知且非常有用的Curiously Recurring Template Pattern(或简称CRTP)。这很有用,因为实现迭代器所需的所有运算符可能非常冗长和重复,并且通常只依赖于几个核心操作(在使用像{{1这样的CRTP类时,您需要“填写”所有这些操作}})。