# Counting Iterator Adaptor

Defined in header boost/counting_iterator.hpp

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). 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_traits;

      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 template `counting_iterator_generator<Incrementable>` is a type generator for counting iterators.

    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

Parameter | Description
--- | ---
`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.

### Type Requirements

The `Incrementable` type must be Default Constructible, Copy Constructible, and Assignable. Also, the `Incrementable` type must provide access to an associated `difference_type` and `iterator_category` through the `counting_iterator_traits` class.

Furthermore, if you wish to create a counting iterator that is a 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 Iterator, then pre-decrement is also required:

    --i

If you wish to create a counting iterator that is a Random Access Iterator, then these additional expressions are also required:

    counting_iterator_traits<Incrementable>::difference_type n;
    i += n
    n = i - j
    i < j

### 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);

An object generator function that 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

## Counting Iterator Traits

The counting iterator adaptor needs to determine the appropriate `difference_type` and `iterator_category` to use based on the `Incrementable` type supplied by the user. The `counting_iterator_traits` class provides these types. If the `Incrementable` type is an integral type or an iterator, these types will be correctly deduced by the `counting_iterator_traits` provided by the library. Otherwise, the user must specialize `counting_iterator_traits` for her type or add nested typedefs to her type to fulfill the needs of `std::iterator_traits`.

The following pseudocode describes how the `counting_iterator_traits` are determined:

    template <class Incrementable>
    struct counting_iterator_traits
    {
      if (numeric_limits<Incrementable>::is_specialized) {
        if (!numeric_limits<Incrementable>::is_integer)
           COMPILE_TIME_ERROR;

        if (!numeric_limits<Incrementable>::is_bounded
            && numeric_limits<Incrementable>::is_signed) {
            typedef Incrementable difference_type;
        }
        else if (numeric_limits<Incrementable>::is_integral) {
            typedef next-larger-signed-type-or-intmax_t difference_type;
        }
        typedef std::random_access_iterator_tag iterator_category;
      } else {
        typedef std::iterator_traits<Incrementable>::difference_type difference_type;
        typedef std::iterator_traits<Incrementable>::iterator_category iterator_category;
      }
    };

The italicized sections above are implementation details, but it is important to know that the `difference_type` for integral types is selected so that it can always represent the difference between two values if such a built-in integer exists. On platforms with a working `std::numeric_limits` implementation, the `difference_type` for any variable-length signed integer type `T` is `T` itself.

Revised 28 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.