Author: | David Abrahams, Jeremy Siek, Thomas Witt |
---|---|
Contact: | dave@boost-consulting.com, jsiek@osl.iu.edu, witt@ive.uni-hannover.de |
Organization: | Boost Consulting, Indiana University Open Systems Lab, University of Hanover Institute for Transport Railway Operation and Construction |
Date: | 2004-01-12 |
Copyright: | Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003. All rights reserved |
abstract: | How would you fill up a vector with the numbers zero through one hundred using std::copy()? The only iterator operation missing from builtin integer types is an operator*() that returns the current value of the integer. The counting iterator adaptor adds this crucial piece of functionality to whatever type it wraps. One can use the counting iterator adaptor not only with integer types, but with any type that is Incrementable (see type requirements below). |
---|
counting_iterator adapts an incrementable type such as int or std::list<std::string>::iterator, by adding an operator* that returns the current value of the object.
template < class Incrementable , class CategoryOrTraversal = use_default , class Difference = use_default > class counting_iterator { public: typedef Incrementable value_type; typedef const Incrementable& reference; typedef const Incrementable* pointer; typedef /* see below */ difference_type; typedef /* see below */ iterator_category; counting_iterator(); counting_iterator(counting_iterator const& rhs); explicit counting_iterator(Incrementable x); Incrementable base() const; reference operator*() const; counting_iterator& operator++(); counting_iterator& operator--(); private: Incrementable m_inc; // exposition };
If the Diference argument is use_default then the difference_type member is an implementation defined signed integral type.
The member iterator_category is a type that satisfies the requirements of the concepts modeled by the counting_iterator as specified in the models section.
The Incrementable type must be Default Constructible, Copy Constructible, and Assignable.
counting_iterator models Readable Lvalue Iterator.
Furthermore, if you wish to create a counting iterator that is a Forward Traversal Iterator and also Forward Iterator, then the following expressions must be valid:
Incrementable i, j; ++i // pre-increment i == j // operator equal
If you wish to create a counting iterator that is a Bidirectional Traversal Iterator and also Bidirectional Iterator, then pre-decrement is also required:
--i
If you wish to create a counting iterator that is a Random Access Traversal Iterator and also Random Access Iterator, then these additional expressions are also required:
counting_iterator::difference_type n; i += n n = i - j i < j
In addition to the operations required by the concepts modeled by counting_iterator, counting_iterator provides the following operations.
counting_iterator();
Returns: | A default constructed instance of counting_iterator. |
---|
counting_iterator(counting_iterator const& rhs);
Returns: | An instance of counting_iterator that is a copy of rhs. |
---|
explicit counting_iterator(Incrementable x);
Returns: | An instance of counting_iterator with m_inc constructed from x. |
---|
reference operator*() const;
Returns: | m_inc |
---|
counting_iterator& operator++();
Effects: | ++m_inc |
---|---|
Returns: | *this |
counting_iterator& operator--();
Effects: | --m_inc |
---|---|
Returns: | *this |
Incrementable base() const;
Returns: | m_inc |
---|
template <class Incrementable> counting_iterator<Incrementable> make_counting_iterator(Incrementable x);
Returns: | An instance of counting_iterator<Incrementable> with current constructed from x. |
---|
This example fills an array with numbers and a second array with pointers into the first array, using counting_iterator for both tasks. Finally indirect_iterator is used to print out the numbers into the first array via indirection through the second array.
int N = 7; std::vector<int> numbers; typedef std::vector<int>::iterator n_iter; std::copy(boost::counting_iterator<int>(0), boost::counting_iterator<int>(N), std::back_inserter(numbers)); std::vector<std::vector<int>::iterator> pointers; std::copy(boost::make_counting_iterator(numbers.begin()), boost::make_counting_iterator(numbers.end()), std::back_inserter(pointers)); std::cout << "indirectly printing out the numbers from 0 to " << N << std::endl; std::copy(boost::make_indirect_iterator(pointers.begin()), boost::make_indirect_iterator(pointers.end()), std::ostream_iterator<int>(std::cout, " ")); std::cout << std::endl;
The output is:
indirectly printing out the numbers from 0 to 7 0 1 2 3 4 5 6
The source code for this example can be found here.