Reputation: 14573
I am reading a book, and I started the Templates chapter. I have already read the chapter about iterators. For practicing, I am trying to implement a doubly-linked class using templates. Below is the header file of my class.
template<typename T>
class list
{
private:
T* first_node;
T* last_node;
struct node_structure
{
T* previous;
T* next;
T content;
};
public:
list();
void push_back( T& item );
void push_front( T& item );
void remove( size_t index );
size_t size() const;
T& get_node( size_t index );
void clear();
~list();
};
I could have set two members:
T* begin();
T* end();
...to act like very basic iterators, but they are not iterators actually. So, I have a question:
How do I implement the custom iterator class to be used with all the arithmetic operations and to have begin()
, cbegin()
, end()
, and cend()
?
(I am aware that creating a list class will not be as efficient as std::list
, but I am doing this just for sake of practicing.)
Upvotes: 3
Views: 10040
Reputation: 7637
If you have a look at an implementation of <iterator>
, you'll find something like __normal_iterator
, which looks like:
template<typename I>
class iter
{
protected:
I i;
using tr = iterator_traits<I>;
public:
using iterator_type = I;
using iterator_category = typename tr::iterator_category;
using value_type = typename tr::value_type;
using difference_type = typename tr::difference_type;
using reference = typename tr::reference;
using pointer = typename tr::pointer;
iter() : i(I()) { }
explicit iter(const I& i) : i(i) { }
// Forward iterator requirements
reference operator*() const { return *i; }
pointer operator->() const { return i; }
iter& operator++() { ++i; return *this; }
iter operator++(int) { return iter(i++); }
// Bidirectional iterator requirements
iter& operator--() { --i; return *this; }
iter operator--(int) { return iter(i--); }
// Random access iterator requirements
reference operator[](const difference_type& n) const { return i[n]; }
iter& operator+=(const difference_type& n) { i += n; return *this; }
iter operator+(const difference_type& n) const { return iter(i + n); }
iter& operator-=(const difference_type& n) { i -= n; return *this; }
iter operator-(const difference_type& n) const { return iter(i - n); }
const I& base() const { return i; }
};
This is supposed to work on an ordinary pointer or iterator. All you have to do is use this as a template and adjust to what is needed by your custom container. If T
is your value_type
, then member functions normally return
begin()
-> iter<T*>
cbegin()
-> iter<const T*>
rbegin()
-> std::reverse_iterator<iter<T*> >
crbegin()
-> std::reverse_iterator<iter<const T*> >
However, since you have your node_structure
, this is not entirely true and you need to elaborate a bit more.
Upvotes: 8