c++boost.gif (8819 bytes)

Counting Iterator Adaptor

Defined in header boost/counting_iterator.hpp

Sometimes it would be nice if one could treat an integer like an iterator, for example, to 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*(), which we would want to just return the current value of the integer. The counting iterator adaptor provides this functionality, though it is a bit more generalized. One can use the counting iterator adaptor not only with integer types, but with any type that is incrementable (has operator++()). The following pseudo-code shows the general idea of how the counting iterator is implemented.

  // inside a hypothetical counting_iterator class...
  typedef Incrementable value_type;
  value_type counting_iterator::operator*() const {
    return this->base; // no dereference!
  }
All of the other operators of the counting iterator behave in the same fashion as the incrementable base type.

Synopsis

namespace boost {
  template <class Incrementable>
  struct counting_iterator_generator;

  template <class Incrementable>
  typename counting_iterator_generator<Incrementable>::type
  make_counting_iterator(Incrementable x);
}

The Counting Iterator Type Generator

The class counting_iterator_generator is a helper class whose purpose is to construct a counting iterator type. The template parameters for this class is the Incrementable type that is being wrapped.
template <class Incrementable>
class counting_iterator_generator
{
public:
    typedef iterator_adaptor<...> type;
};

Example

In this example we use the counting iterator generator to create a counting iterator, and count from zero to four.
#include <boost/config.hpp>
#include <iostream>
#include <boost/counting_iterator.hpp>

int main(int, char*[])
{
  // Example of using counting_iterator_generator
  std::cout << "counting from 0 to 4:" << std::endl;
  boost::counting_iterator_generator<int>::type first(0), last(4);
  std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;

  // to be continued...
The output from this part is:
counting from 0 to 4:
0 1 2 3 

Template Parameters

ParameterDescription
Incrementable The type being wrapped by the adaptor.

Model of

If the Incrementable type has all of the functionality of a Random Access Iterator except the operator*(), then the counting iterator will be a model of Random Access Iterator. If the Incrementable type has less functionality, then the counting iterator will have correspondingly less functionality.

Members

The counting iterator type implements the member functions and operators required of the Random Access Iterator concept. In addition it has the following constructor:
counting_iterator_generator::type(const Incrementable& i)


The Counting Iterator Object Generator

template <class Incrementable>
typename counting_iterator_generator<Incrementable>::type
make_counting_iterator(Incrementable base);
This function provides a convenient way to create counting iterators.

Example

In this example we count from negative five to positive five, this time using the make_counting_iterator() function to save some typing.
  // continuing from previous example...

  std::cout << "counting from -5 to 4:" << std::endl;
  std::copy(boost::make_counting_iterator(-5),
	    boost::make_counting_iterator(5),
	    std::ostream_iterator<int>(std::cout, " "));
  std::cout << std::endl;

  // to be continued...
The output from this part is:
counting from -5 to 4:
-5 -4 -3 -2 -1 0 1 2 3 4 
In the next example we create an array of numbers, and then create a second array of pointers, where each pointer is the address of a number in the first array. The counting iterator makes it easy to do this since dereferencing a counting iterator that is wrapping an iterator over the array of numbers just returns a pointer to the current location in the array. We then use the indirect iterator adaptor to print out the number in the array by accessing the numbers through the array of pointers.
  // continuing from previous example...

  const int N = 7;
  std::vector<int> numbers;
  // Fill "numbers" array with [0,N)
  std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N),
	    std::back_inserter(numbers));

  std::vector<std::vector<int>::iterator> pointers;

  // Use counting iterator to fill in the array of pointers.
  std::copy(boost::make_counting_iterator(numbers.begin()),
	    boost::make_counting_iterator(numbers.end()),
	    std::back_inserter(pointers));

  // Use indirect iterator to print out numbers by accessing
  // them through the array of 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 

Revised 10 Feb 2001

© Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.