Iterators: What Must Be Done?

Whenever I need to implement a custom iterator type in C++ I immediately remember nothing about what the standard has to say about the requirements for each iterator category, so here is a collation of cppreference links and examples describing what must be done to implement a custom iterator type.

All iterator types must be CopyConstructible, CopyAssignable, Destructible, and Swappable; have the member types required by std::iterator_traits ; and support the following expressions.

Expression Return Type *r unspecified ++r iterator&

struct iterator { using difference_type = std :: ptrdiff_t ; using value_type = ?; using pointer = value_type*; using reference = value_type&; using iterator_category = ?; iterator( const iterator& rhs); iterator(iterator&& rhs); iterator& operator =( const iterator& rhs); iterator& operator =(iterator&& rhs); void swap (iterator& iter) ; reference operator *(); iterator& operator ++(); }; void swap (iterator& lhs, iterator& rhs) ;

In addition to the Iterator requirements, an InputIterator must also be EqualityComparable and support the following expressions.

Expression Return Type i != j contextually convertible to bool *i reference , convertible to value_type i->m ++i input_iterator& (void)i++ convertible to value_type *i++

struct input_iterator { using difference_type = std :: ptrdiff_t ; using value_type = ?; using pointer = value_type*; using reference = value_type&; using iterator_category = std ::input_iterator_tag; input_iterator( const input_iterator& rhs); input_iterator(input_iterator&& rhs); input_iterator& operator =( const input_iterator& rhs); input_iterator& operator =(input_iterator&& rhs); void swap (input_iterator& iter) ; bool operator ==( const input_iterator& rhs); bool operator !=( const input_iterator& rhs); reference operator *(); pointer operator ->(); input_iterator& operator ++(); input_iterator& operator ++( int ); }; void swap (input_iterator& lhs, input_iterator& rhs) ;

In addition to the Iterator requirements, an OutputIterator must also be a class type or a pointer type and support the following expressions.

Expression Return Type *r = o (not used) ++r output_iterator& r++ convertible to const output_iterator& *r++ = o (not used)

struct output_iterator { using difference_type = std :: ptrdiff_t ; using value_type = ?; using pointer = value_type*; using reference = value_type&; using iterator_category = std ::output_iterator_tag; output_iterator( const output_iterator& rhs); output_iterator(output_iterator&& rhs); output_iterator& operator =( const output_iterator& rhs); output_iterator& operator =(output_iterator&& rhs); void swap (output_iterator& iter) ; reference operator *(); output_iterator& operator ++(); output_iterator operator ++( int ); }; void swap (output_iterator& lhs, output_iterator& rhs) ;

In addition to the InputIterator requirements, a ForwardIterator must also be DefaultConstructible; support multiple iteration passes; std::iterator_traits<forward_iterator>::reference must be exactly T& satisfies OutputIterator or exactly const T& otherwise; and support the following expressions.

Expression Return Type i++ forward_iterator *i++ reference

struct forward_iterator { using difference_type = std :: ptrdiff_t ; using value_type = ?; using pointer = value_type*; using reference = value_type&; using iterator_category = std ::forward_iterator_tag; forward_iterator(); forward_iterator( const forward_iterator& rhs); forward_iterator(forward_iterator&& rhs); forward_iterator& operator =( const forward_iterator& rhs); forward_iterator& operator =(forward_iterator&& rhs); void swap (forward_iterator& iter) ; bool operator ==( const forward_iterator& rhs); bool operator !=( const forward_iterator& rhs); reference operator *(); pointer operator ->(); forward_iterator& operator ++(); forward_iterator operator ++( int ); }; void swap (forward_iterator& lhs, forward_iterator& rhs) ;

In addition to the ForwardIterator requirements, a BidirectionalIterator must also support the following expressions.

Expression Return Type --a bidirectional_iterator& a-- convertible to const bidirectional_iterator& *a-- reference

struct bidirectional_iterator { using difference_type = std :: ptrdiff_t ; using value_type = ?; using pointer = value_type*; using reference = value_type&; using iterator_category = std ::bidirectional_iterator_tag; bidirectional_iterator(); bidirectional_iterator( const bidirectional_iterator& rhs); bidirectional_iterator(bidirectional_iterator&& rhs); bidirectional_iterator& operator =( const bidirectional_iterator& rhs); bidirectional_iterator& operator =(bidirectional_iterator&& rhs); void swap (bidirectional_iterator& iter) ; bool operator ==( const bidirectional_iterator& rhs); bool operator !=( const bidirectional_iterator& rhs); reference operator *(); pointer operator ->(); bidirectional_iterator& operator ++(); bidirectional_iterator operator ++( int ); bidirectional_iterator& operator --(); bidirectional_iterator operator --( int ); }; void swap (bidirectional_iterator& lhs, bidirectional_iterator& rhs) ;

In addition to the BidirectionalIterator requirements, a RandomAccessIterator must support the following expressions.

Expression Return Type r += n random_access_iterator& a + n / n + a random_access_iterator r -= n random_access_iterator& i - n random_access_iterator b - a difference_type i[n] convertible to reference a < b contextually convertible to bool a >= b contextually convertible to bool a <= b contextually convertible to bool

struct random_access_iterator { using difference_type = std :: ptrdiff_t ; using value_type = ?; using pointer = value_type*; using reference = value_type&; using iterator_category = std ::random_access_iterator_tag; random_access_iterator(); random_access_iterator( const random_access_iterator& rhs); random_access_iterator(random_access_iterator&& rhs); random_access_iterator& operator =( const random_access_iterator& rhs); random_access_iterator& operator =(random_access_iterator&& rhs); void swap (random_access_iterator& iter) ; bool operator ==( const random_access_iterator& rhs); bool operator !=( const random_access_iterator& rhs); bool operator <( const random_access_iterator& rhs); bool operator <=( const random_access_iterator& rhs); bool operator >( const random_access_iterator& rhs); bool operator >=( const random_access_iterator& rhs); reference operator *(); pointer operator ->(); reference operator [](difference_type n); random_access_iterator& operator ++(); random_access_iterator operator ++( int ); random_access_iterator& operator +=(difference_type n); random_access_iterator operator +(difference_type n); random_access_iterator& operator --(); random_access_iterator operator --( int ); random_access_iterator& operator -=(difference_type n); random_access_iterator operator -(difference_type n); }; void swap (random_access_iterator& lhs, random_access_iterator& rhs) ;

Summary

There they are, code snippets to get started implementing custom iterator types in C++. I will find these useful in future, I hope you do too. If there are any mistakes or glaring omissions please let know.