如何为我的集合类提供类似迭代器的STL?

时间:2010-11-08 16:04:08

标签: c++ templates iterator

  

可能重复:
  How to correctly implement custom iterators and const_iterators ?

我真的想为我所拥有的实体集合类提供类似于迭代器的STL。作为奖励,如果迭代器可以很容易地重用于我得到的其他集合类,我会喜欢它。问题是我曾经试图通过STL跋涉,但那对我来说太复杂了。关于如何做到这一点的任何建议?它不需要像STL迭代器那么复杂,但如果我可以说MyCollection::iterator it = o_MyCollection.begin()等我就会喜欢它。 :)

作为第二个问题,如果我将它传递给像for_each这样的常用算法,这个迭代器的基本要求是什么?

1 个答案:

答案 0 :(得分:3)

假设您的集合是一个由整数索引的列表,我在自定义STL集合中使用的这个迭代器类可能会对您有所帮助。它使用curiously recurring template pattern。它不是100%经过测试,但可以在我的代码中使用。

// common_safe_iterator is instantiated to produce both const_iterator and
// iterator types. It called "safe" because it is not necessarily invalidated
// by changes to the collection size, and it calls at() on the target
// collection, which is supposed to throw an exception if the index is
// out-of-range, instead of calling [] which does not.
template<class base>
class common_safe_iterator : public base {
protected:
    // base must contain the following 5 typedefs
    typedef typename base::reference reference;
    typedef typename base::pointer pointer;
    typedef typename base::vector_t vector_t;
    typedef typename base::const_iterator_t const_iterator_t;
    typedef typename base::iterator_t iterator_t;
    vector_t* _vec;
    size_type _pos;
public:
    typedef common_safe_iterator<base> self;
    friend const_iterator_t;

    common_safe_iterator(vector_t* vec, size_type pos) : _vec(vec), _pos(pos) { }
    common_safe_iterator(const iterator_t& copy) : _vec(copy._vec), _pos(copy._pos) { }

    reference operator*() const { return _vec->at(_pos); }
    pointer operator->() const { return &_vec->at(_pos); }

    self& operator++() // prefix ++
        { ++_pos; return *this; }
    self& operator--() // prefix --
        { --_pos; return *this; }
    self& operator+=(int amt) 
        { _pos += amt; return *this; }
    bool operator==(const self& x) const
        { return (x._vec == _vec) && (x._pos == _pos); }
    int operator-(const self& base) const
        { assert(base._vec == _vec); return _pos - base._pos; }
    // Returns true if the iterator can be dereferenced
    bool is_valid() const
        { return _vec != NULL && _pos < _vec->size(); }

    /////////////////////////////////////////////////////////
    // Operators that are defined in terms of other operators

    self operator++(int) // postfix ++
    {
        self tmp = *this; // copy ourselves
        ++*this;
        return tmp;
    }
    self operator--(int) // postfix --
    {
        self tmp = *this; // copy ourselves
        --*this;
        return tmp;
    }
    self& operator-=(int amt)
    {
        return *this += -amt;
    }
    bool operator!=(const self& x) const
    {
        return !(*this == x);
    }
    bool operator>(const self& x) const
    {
        return *this - x > 0;
    }
    bool operator>=(const self& x) const
    {
        return *this - x >= 0;
    }
    bool operator<(const self& x) const
    {
        return *this - x < 0;
    }
    bool operator<=(const self& x) const
    {
        return *this - x <= 0;
    }
    self operator+(int amt) const
    {
        self tmp = *this;
        return tmp += amt;
    }
    self operator-(int amt) const
    {
        self tmp = *this;
        return tmp -= amt;
    }
    reference operator[](int index) const
    {
        self tmp = *this;
        tmp += index;
        return *tmp;
    }
};

STL希望您提供“const_iterator”和非const“迭代器”类。为此,请编写两个基类,每个基类具有5个typedef。我的集合类名为mini_vector_t,因此我使用以下基类:

/// iterator and const_iterator differ only in these typedefs.
/// const_iterator_base is the base class of const_iterator, while
/// iterator_base is the base class of iterator; both iterator and
/// const_iterator are typedefs of common_safe_iterator.
struct iterator_base;
struct const_iterator_base
{
    typedef const typename mini_vector_t::value_type& reference;
    typedef const typename mini_vector_t::value_type* pointer;
    typedef const mini_vector_t vector_t;
    typedef common_safe_iterator<const_iterator_base> const_iterator_t;
    typedef common_safe_iterator<iterator_base> iterator_t;
};
struct iterator_base
{
    typedef typename mini_vector_t::value_type& reference;
    typedef typename mini_vector_t::value_type* pointer;
    typedef mini_vector_t vector_t;
    typedef common_safe_iterator<const_iterator_base> const_iterator_t;
    typedef common_safe_iterator<iterator_base> iterator_t;
};

最后,您的集合必须包含const_iterator和iterator的typedef:

typedef common_safe_iterator<const_iterator_base> const_iterator;
typedef common_safe_iterator<iterator_base> iterator;

如果你的集合包装了一个数组,那么更简单的替代方法是使用T *作为迭代器类型,使用const T *作为const_iterator类型:

typedef T* iterator;
typedef const T* const_iterator;

请记住,STL的设计使得指针本身就是迭代器。

我认为你应该做一些额外的事情来声明你的迭代器是“随机访问”,但我不知道是什么。