General edits for clarity; some reorganization.

[SVN r9213]
This commit is contained in:
Dave Abrahams 2001-02-15 16:39:55 +00:00
parent 272025bb07
commit fda44ca17d

View File

@ -18,16 +18,15 @@ Defined in header
<a href="../../boost/counting_iterator.hpp">boost/counting_iterator.hpp</a> <a href="../../boost/counting_iterator.hpp">boost/counting_iterator.hpp</a>
<p> <p>
Sometimes it would be nice if one could treat an integer like an How would you fill up a vector with the numbers zero
iterator, for example, to fill up a vector with the numbers zero
through one hundred using <a through one hundred using <a
href="http://www.sgi.com/tech/stl/copy.html"><tt>std::copy()</tt></a>. The href="http://www.sgi.com/tech/stl/copy.html"><tt>std::copy()</tt></a>? The
only iterator operation missing from builtin integer types is an only iterator operation missing from builtin integer types is an
<tt>operator*()</tt>, which we would want to just return the current <tt>operator*()</tt> that returns the current
value of the integer. The counting iterator adaptor provides this value of the integer. The counting iterator adaptor adds this crucial piece of
functionality, though it is a bit more generalized. One can use the functionality to whatever type it wraps. One can use the
counting iterator adaptor not only with integer types, but with any counting iterator adaptor not only with integer types, but with any
type that is incrementable (see type requirements below). The type that is <tt>Incrementable</tt> (see type requirements <a href="#requirements">below</a>). The
following <b>pseudo-code</b> shows the general idea of how the following <b>pseudo-code</b> shows the general idea of how the
counting iterator is implemented. counting iterator is implemented.
</p> </p>
@ -41,63 +40,30 @@ counting iterator is implemented.
</pre> </pre>
All of the other operators of the counting iterator behave in the same All of the other operators of the counting iterator behave in the same
fashion as the incrementable base type. fashion as the <tt>Incrementable</tt> base type.
<h2>Synopsis</h2> <h2>Synopsis</h2>
<pre> <pre>
namespace boost { namespace boost {
template &lt;class Incrementable&gt; template &lt;class Incrementable&gt;
struct counting_iterator_traits; struct <a href="#counting_iterator_traits">counting_iterator_traits</a>;
template &lt;class Incrementable&gt; template &lt;class Incrementable&gt;
struct counting_iterator_generator; struct <a href="#counting_iterator_generator">counting_iterator_generator</a>;
template &lt;class Incrementable&gt; template &lt;class Incrementable&gt;
typename counting_iterator_generator&lt;Incrementable&gt;::type typename counting_iterator_generator&lt;Incrementable&gt;::type
make_counting_iterator(Incrementable x); <a href="#make_counting_iterator">make_counting_iterator</a>(Incrementable x);
} }
</pre> </pre>
<hr> <hr>
<h2><a name="counting_iterator_traits">Counting Iterator Traits</a></h2>
The counting iterator adaptor needs to know the appropriate
<tt>difference_type</tt> and <tt>iterator_category</tt> to use
depending 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 a numeric type or is an iterator
then these types will be correctly deduced by the below counting
iterator traits. Otherwise, the user must specialize
<tt>counting_iterator_traits</tt> for their type, or add nested
typedefs to their type to fulfill the needs of
<a href="http://www.sgi.com/tech/stl/iterator_traits.html">
<tt>std::iterator_traits</tt></a>.
<pre>
template &lt;class Incrementable&gt;
struct counting_iterator_traits
{
<i>if (numeric_limits&lt;Incrementable&gt::is_specialized == true) {</i>
typedef <i>detail::numeric_traits</i>&lt;Incrementable&gt;::difference_type difference_type;
typedef std::random_access_iterator_tag iterator_category;
<i>} else {</i>
typedef std::iterator_traits&lt;Incrementable&gt;::difference_type difference_type;
typedef std::iterator_traits&lt;Incrementable&gt;::iterator_category iterator_category;
<i>}</i>
};
</pre>
<hr>
<h2><a name="counting_iterator_generator">The Counting Iterator Type <h2><a name="counting_iterator_generator">The Counting Iterator Type
Generator</a></h2> Generator</a></h2>
The class <tt>counting_iterator_generator</tt> is a helper class whose The class template <tt>counting_iterator_generator&lt;Incrementable&gt;</tt> is a <a href="../../more/generic_programming.html#type_generator">type generator</a> for counting iterators.
purpose is to construct a counting iterator type. The template
parameters for this class is the <tt>Incrementable</tt> type that is
being wrapped.
<pre> <pre>
template &lt;class Incrementable&gt; template &lt;class Incrementable&gt;
@ -159,7 +125,7 @@ Access Iterator</a>. If the <tt>Incrementable</tt> type has less
functionality, then the counting iterator will have correspondingly functionality, then the counting iterator will have correspondingly
less functionality. less functionality.
<h3>Type Requirements</h3> <h3><a name="requirements">Type Requirements</a></h3>
The <tt>Incrementable</tt> type must be <a The <tt>Incrementable</tt> type must be <a
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default
@ -183,7 +149,7 @@ If you wish to create a counting iterator that is a <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> Random href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> Random
Access Iterator</a>, then these additional expressions are also required: Access Iterator</a>, then these additional expressions are also required:
<pre> <pre>
counting_iterator_traits&lt;Incrementable&gt;::difference_type n; <a href="#counting_iterator_traits">counting_iterator_traits</a>&lt;Incrementable&gt;::difference_type n;
i += n i += n
n = i - j n = i - j
i < j i < j
@ -214,7 +180,11 @@ typename counting_iterator_generator&lt;Incrementable&gt;::type
make_counting_iterator(Incrementable base); make_counting_iterator(Incrementable base);
</pre> </pre>
This function provides a convenient way to create counting iterators. An <a href="../../more/generic_programming.html#object_generator">object
generator</a> function that provides a convenient way to create counting
iterators.<p>
<h3>Example</h3> <h3>Example</h3>
@ -280,9 +250,56 @@ indirectly printing out the numbers from 0 to 7
0 1 2 3 4 5 6 0 1 2 3 4 5 6
</pre> </pre>
<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 &lt;class Incrementable&gt;
struct counting_iterator_traits
{
if (numeric_limits&lt;Incrementable&gt::is_specialized) {
if (!numeric_limits&lt;Incrementable&gt::is_integral)
COMPILE_TIME_ERROR;
if (!numeric_limits&lt;Incrementable&gt::is_bounded
&amp;&amp; numeric_limits&lt;Incrementable&gt;::is_signed) {
typedef Incrementable difference_type;
}
else if (numeric_limits&lt;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&lt;Incrementable&gt;::difference_type difference_type;
typedef std::iterator_traits&lt;Incrementable&gt;::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.
<hr> <hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->10 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" --></p> <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->15 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" --></p>
<p>© Copyright Jeremy Siek 2000. Permission to copy, use, <p>© Copyright Jeremy Siek 2000. Permission to copy, use,
modify, sell and distribute this document is granted provided this copyright modify, sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as is&quot; notice appears in all copies. This document is provided &quot;as is&quot;
@ -296,3 +313,4 @@ any purpose.</p>
--> -->
<!-- LocalWords: struct typename iostream int Siek CopyConstructible pre <!-- LocalWords: struct typename iostream int Siek CopyConstructible pre
--> -->