2001-02-12 21:35:20 +00:00
< html >
< head >
< meta http-equiv = "Content-Type" content = "text/html; charset=windows-1252" >
< meta name = "GENERATOR" content = "Microsoft FrontPage 4.0" >
< meta name = "ProgId" content = "FrontPage.Editor.Document" >
< title > Counting Iterator Adaptor Documentation< / title >
< / head >
< body bgcolor = "#FFFFFF" text = "#000000" >
< img src = "../../c++boost.gif" alt = "c++boost.gif (8819 bytes)"
align="center" width="277" height="86">
< h1 > Counting Iterator Adaptor< / h1 >
Defined in header
2001-02-15 05:53:10 +00:00
< a href = "../../boost/counting_iterator.hpp" > boost/counting_iterator.hpp< / a >
2001-02-12 21:35:20 +00:00
< p >
2001-02-15 16:39:55 +00:00
How would you fill up a vector with the numbers zero
2001-02-12 21:35:20 +00:00
through one hundred using < a
2001-02-15 16:39:55 +00:00
href="http://www.sgi.com/tech/stl/copy.html">< tt > std::copy()< / tt > < / a > ? The
2001-02-12 21:35:20 +00:00
only iterator operation missing from builtin integer types is an
2001-02-15 16:39:55 +00:00
< tt > operator*()< / tt > 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
2001-02-12 21:35:20 +00:00
counting iterator adaptor not only with integer types, but with any
2001-02-15 16:39:55 +00:00
type that is < tt > Incrementable< / tt > (see type requirements < a href = "#requirements" > below< / a > ). The
2001-02-15 05:53:10 +00:00
following < b > pseudo-code< / b > shows the general idea of how the
counting iterator is implemented.
2001-02-12 21:35:20 +00:00
< / p >
< pre >
// inside a hypothetical counting_iterator class...
typedef Incrementable value_type;
value_type counting_iterator::operator*() const {
return this->base; // no dereference!
}
< / pre >
All of the other operators of the counting iterator behave in the same
2001-02-15 16:39:55 +00:00
fashion as the < tt > Incrementable< / tt > base type.
2001-02-12 21:35:20 +00:00
< h2 > Synopsis< / h2 >
< pre >
namespace boost {
2001-02-15 05:53:10 +00:00
template < class Incrementable>
2001-02-15 16:39:55 +00:00
struct < a href = "#counting_iterator_traits" > counting_iterator_traits< / a > ;
2001-02-15 05:53:10 +00:00
2001-02-12 21:35:20 +00:00
template < class Incrementable>
2001-02-15 16:39:55 +00:00
struct < a href = "#counting_iterator_generator" > counting_iterator_generator< / a > ;
2001-02-12 21:35:20 +00:00
template < class Incrementable>
typename counting_iterator_generator< Incrementable> ::type
2001-02-15 16:39:55 +00:00
< a href = "#make_counting_iterator" > make_counting_iterator< / a > (Incrementable x);
2001-02-12 21:35:20 +00:00
}
< / pre >
< hr >
< h2 > < a name = "counting_iterator_generator" > The Counting Iterator Type
Generator< / a > < / h2 >
2001-02-15 16:39:55 +00:00
The class template < tt > counting_iterator_generator< Incrementable> < / tt > is a < a href = "../../more/generic_programming.html#type_generator" > type generator< / a > for counting iterators.
2001-02-12 21:35:20 +00:00
< pre >
template < class Incrementable>
class counting_iterator_generator
{
public:
typedef < a href = "./iterator_adaptors.htm#iterator_adaptor" > iterator_adaptor< / a > < ...> type;
};
< / pre >
< h3 > Example< / h3 >
In this example we use the counting iterator generator to create a
counting iterator, and count from zero to four.
< pre >
#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...
< / pre >
2001-02-12 21:57:19 +00:00
The output from this part is:
< pre >
counting from 0 to 4:
0 1 2 3
< / pre >
2001-02-12 21:35:20 +00:00
< h3 > Template Parameters< / h3 >
< Table border >
< TR >
< TH > Parameter< / TH > < TH > Description< / TH >
< / TR >
< TR >
< TD > < tt > Incrementable< / tt > < / TD >
< TD > The type being wrapped by the adaptor.< / TD >
< / TR >
< / Table >
< h3 > Model of< / h3 >
If the < tt > Incrementable< / tt > type has all of the functionality of a
< a href = "http://www.sgi.com/tech/stl/RandomAccessIterator.html" > Random
Access Iterator< / a > except the < tt > operator*()< / tt > , then the counting
iterator will be a model of < a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
2001-02-12 21:57:19 +00:00
Access Iterator< / a > . If the < tt > Incrementable< / tt > type has less
2001-02-12 21:35:20 +00:00
functionality, then the counting iterator will have correspondingly
less functionality.
2001-02-15 16:39:55 +00:00
< h3 > < a name = "requirements" > Type Requirements< / a > < / h3 >
2001-02-15 05:53:10 +00:00
The < tt > Incrementable< / tt > type must be < a
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default
Constructible< / a > , < a href = "./CopyConstructible.html" > Copy
Constructible< / a > , and < a href = "./Assignable.html" > Assignable< / a > .
2001-02-15 16:49:16 +00:00
Also, the < tt > Incrementable< / tt > type must provide access to an
associated < tt > difference_type< / tt > and < tt > iterator_category< / tt >
through the < a
href="#counting_iterator_traits">< tt > counting_iterator_traits< / tt > < / a >
class.
< p >
2001-02-15 05:53:10 +00:00
Furthermore, if you wish to create a counting iterator that is a < a
href="http://www.sgi.com/tech/stl/ForwardIterator.html"> Forward
Iterator< / a > , then the following expressions must be valid:
< pre >
Incrementable i, j;
++i // pre-increment
i == j // operator equal
< / pre >
If you wish to create a counting iterator that is a < a
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">
Bidirectional Iterator< / a > , then pre-decrement is also required:
< pre >
--i
< / pre >
If you wish to create a counting iterator that is a < a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> Random
Access Iterator< / a > , then these additional expressions are also required:
< pre >
2001-02-15 16:39:55 +00:00
< a href = "#counting_iterator_traits" > counting_iterator_traits< / a > < Incrementable> ::difference_type n;
2001-02-15 05:53:10 +00:00
i += n
n = i - j
i < j
< / pre >
2001-02-15 16:49:16 +00:00
2001-02-12 21:35:20 +00:00
< h3 > Members< / h3 >
The counting iterator type implements the member functions and
operators required of the < a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access Iterator< / a > concept. In addition it has the following
constructor:
< pre >
counting_iterator_generator::type(const Incrementable& i)
< / pre >
< p >
< hr >
< p >
< h2 > < a name = "make_counting_iterator" > The Counting Iterator Object Generator< / a > < / h2 >
< pre >
template < class Incrementable>
typename counting_iterator_generator< Incrementable> ::type
make_counting_iterator(Incrementable base);
< / pre >
2001-02-15 16:39:55 +00:00
An < a href = "../../more/generic_programming.html#object_generator" > object
generator< / a > function that provides a convenient way to create counting
iterators.< p >
2001-02-12 21:35:20 +00:00
< h3 > Example< / h3 >
In this example we count from negative five to positive five, this
time using the < tt > make_counting_iterator()< / tt > function to save some
typing.
< pre >
// continuing from previous example...
2001-02-12 21:57:19 +00:00
std::cout < < "counting from -5 to 4:" < < std::endl;
2001-02-12 21:35:20 +00:00
std::copy(boost::make_counting_iterator(-5),
boost::make_counting_iterator(5),
std::ostream_iterator< int> (std::cout, " "));
std::cout < < std::endl;
2001-02-12 21:57:19 +00:00
// to be continued...
< / pre >
The output from this part is:
< pre >
counting from -5 to 4:
-5 -4 -3 -2 -1 0 1 2 3 4
< / pre >
2001-02-12 21:35:20 +00:00
2001-02-12 21:57:19 +00:00
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 < a
href="./indirect_iterator.htm">indirect iterator adaptor< / a > to print
out the number in the array by accessing the numbers through the array
of pointers.
< pre >
// 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));
2001-02-12 21:59:25 +00:00
std::vector< std::vector< int> ::iterator> pointers;
2001-02-12 21:57:19 +00:00
// 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;
< / pre >
The output is:
< pre >
indirectly printing out the numbers from 0 to 7
0 1 2 3 4 5 6
2001-02-12 21:35:20 +00:00
< / pre >
2001-02-15 16:39:55 +00:00
< hr >
< h2 > < a name = "counting_iterator_traits" > Counting Iterator Traits< / a > < / h2 >
The counting iterator adaptor needs to determine the appropriate
< tt > difference_type< / tt > and < tt > iterator_category< / tt > to use based on the
< tt > Incrementable< / tt > type supplied by the user. The
< tt > counting_iterator_traits< / tt > class provides these types. If the
< tt > Incrementable< / tt > type is an integral type or an iterator, these types
will be correctly deduced by the < tt > counting_iterator_traits< / tt > provided by
the library. Otherwise, the user must specialize
< tt > counting_iterator_traits< / tt > for her type or add nested typedefs to
her type to fulfill the needs of
< a href = "http://www.sgi.com/tech/stl/iterator_traits.html" >
< tt > std::iterator_traits< / tt > < / a > .
< p > The following pseudocode describes how the < tt > counting_iterator_traits< / tt > are determined:
< pre >
template < class Incrementable>
struct counting_iterator_traits
{
if (numeric_limits< Incrementable& gt::is_specialized) {
2001-02-20 23:15:29 +00:00
if (!numeric_limits< Incrementable& gt::is_integer)
2001-02-15 16:39:55 +00:00
COMPILE_TIME_ERROR;
if (!numeric_limits< Incrementable& gt::is_bounded
& & numeric_limits< Incrementable> ::is_signed) {
typedef Incrementable difference_type;
}
else if (numeric_limits< Incrementable& gt::is_integral) {
typedef < i > next-larger-signed-type-or-intmax_t< / i > 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;
}
};
< / pre >
< p > The italicized sections above are implementation details, but it is important
to know that the < tt > difference_type< / tt > 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 < tt > std::numeric_limits< / tt >
implementation, the < tt > difference_type< / tt > for any variable-length signed
integer type < tt > T< / tt > is < tt > T< / tt > itself.
2001-02-12 21:35:20 +00:00
< hr >
2001-10-01 15:54:23 +00:00
< p > Revised <!-- webbot bot="Timestamp" s - type="EDITED" s - format="%d %b %Y" startspan --> 19 Aug 2001<!-- webbot bot="Timestamp" endspan i - checksum="14767" --> < / p >
2001-02-12 21:35:20 +00:00
< p > <EFBFBD> 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.< / p >
< / body >
< / html >
<!-- LocalWords: html charset alt gif hpp incrementable const namespace htm
-->
2001-02-15 05:53:10 +00:00
<!-- LocalWords: struct typename iostream int Siek CopyConstructible pre
2001-02-12 21:35:20 +00:00
-->
2001-02-15 16:39:55 +00:00