可能重复:
How to correctly implement custom iterators and const_iterators ?
我真的想为我所拥有的实体集合类提供类似于迭代器的STL。作为奖励,如果迭代器可以很容易地重用于我得到的其他集合类,我会喜欢它。问题是我曾经试图通过STL跋涉,但那对我来说太复杂了。关于如何做到这一点的任何建议?它不需要像STL迭代器那么复杂,但如果我可以说MyCollection::iterator it = o_MyCollection.begin()
等我就会喜欢它。 :)
作为第二个问题,如果我将它传递给像for_each
这样的常用算法,这个迭代器的基本要求是什么?
答案 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的设计使得指针本身就是迭代器。
我认为你应该做一些额外的事情来声明你的迭代器是“随机访问”,但我不知道是什么。