I thought I would add my own little batch of advice.
The first thing I'd like to note is that iterator
and const_iterator
are very likely to have much of their implementation in common. However, even though their code is similar, it's not exactly identical. This begs for templates.
The second thing I'd like to note is that a const_iterator
should be constructible from an iterator
(implicitly), but not the other way around.
The third thing I'd like to note is that if you wish to have a map
-like interface, then you need to provide a reverse_iterator
and const_reverse_iterator
as well.
From a style point of view, I tend not to put the implementation of the iterator
itself right in the class. I find it unreadable when the class implementation is cluttered with so much code that you struggle to see the types and methods available. For this reason I would recommend putting the implementation outside the class.
Finally, I definitely recommend Boost.Iterator. You may not use it, but read the material, it'll notably give you insight on how to write the code once and use it for the 4 kinds!
Quick illustration:
namespace detail {
template <class Value> class base_iterator;
}
template <class Value>
class container
{
public:
typedef detail::base_iterator<Value> iterator;
typedef detail::base_iterator<Value const> const_iterator;
typedef boost::reverse_iterator<iterator> reverse_iterator;
typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
};
I don't know about you, but I feel good when I do only a quarter of the work and leverages a compiler/library to fill in the rest for me :)