Project: ArangoDB (App Definition and Development / Database)
File: counting_iterator.pdf

Counting Iterator
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-11-01
Copyright : Copyright David Abrahams, Jeremy Siek, and Thomas Witt 2003.
abstract: How would you ﬁll up a vector with the numbers zero through one hundred
using std::copy() ? The only iterator operation missing from builtin integer types is
anoperator*() 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 incrementable
type.
counting_iterator adapts an object by adding an operator* that returns the current
value of the object. All other iterator operations are forwarded to the adapted object.
Table of Contents
counting_iterator synopsis
counting_iterator requirements
counting_iterator models
counting_iterator operations
Example
counting_iterator synopsis
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;
1counting_iterator();
counting_iterator(counting_iterator const& rhs);
explicit counting_iterator(Incrementable x);
Incrementable const& base() const;
reference operator*() const;
counting_iterator& operator++();
counting_iterator& operator--();
private:
Incrementable m_inc; // exposition
};
If the Difference argument is use_default then difference_type is an unspeciﬁed signed integral
type. Otherwise difference_type isDifference .
iterator_category is determined according to the following algorithm:
if (CategoryOrTraversal is not use_default)
return CategoryOrTraversal
else if (numeric_limits<Incrementable>::is_specialized)
return iterator-category (
random_access_traversal_tag, Incrementable, const Incrementable&)
else
return iterator-category (
iterator_traversal<Incrementable>::type,
Incrementable, const Incrementable&)
[Note: implementers are encouraged to provide an implementation of operator- and a dif-
ference_type that avoids overﬂows in the cases where std::numeric_limits<Incrementable>::is_specialized
is true.]
counting_iterator requirements
The Incrementable argument shall be Copy Constructible and Assignable.
Ifiterator_category is convertible to forward_iterator_tag orforward_traversal_tag , the
following must be well-formed:
Incrementable i, j;
++i; // pre-increment
i == j; // operator equal
Ifiterator_category is convertible to bidirectional_iterator_tag orbidirectional_traversal_tag ,
the following expression must also be well-formed:
--i
Ifiterator_category is convertible to random_access_iterator_tag orrandom_access_traversal_tag ,
the following must must also be valid:
counting_iterator::difference_type n;
i += n;
n = i - j;
i < j;
2counting_iterator models
Specializations of counting_iterator model Readable Lvalue Iterator. In addition, they model the con-
cepts corresponding to the iterator tags to which their iterator_category is convertible. Also, if Cat-
egoryOrTraversal is not use_default then counting_iterator models the concept corresponding to
the iterator tag CategoryOrTraversal . Otherwise, if numeric_limits<Incrementable>::is_specialized ,
then counting_iterator models Random Access Traversal Iterator. Otherwise, counting_iterator
models the same iterator traversal concepts modeled by Incrementable .
counting_iterator<X,C1,D1> is interoperable with counting_iterator<Y,C2,D2> if and only if
Xis interoperable with Y.
counting_iterator operations
In addition to the operations required by the concepts modeled by counting_iterator ,counting_iterator
provides the following operations.
counting_iterator();
Requires: Incrementable is Default Constructible.
Eﬀects: Default construct the member m_inc .
counting_iterator(counting_iterator const& rhs);
Eﬀects: Construct member m_inc from rhs.m_inc .
explicit counting_iterator(Incrementable x);
Eﬀects: Construct member m_inc from x.
reference operator*() const;
Returns: m_inc
counting_iterator& operator++();
Eﬀects: ++m_inc
Returns: *this
counting_iterator& operator--();
Eﬀects: --m_inc
Returns: *this
Incrementable const& 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.
3Example
This example ﬁlls an array with numbers and a second array with pointers into the ﬁrst array, using
counting_iterator for both tasks. Finally indirect_iterator is used to print out the numbers into
the ﬁrst 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.
4