Bigtime edits

[SVN r9219]
This commit is contained in:
Dave Abrahams 2001-02-16 00:38:28 +00:00
parent 648c6240a2
commit 083b1b02df

View File

@ -32,9 +32,25 @@
<ul> <ul>
<li>Template class <tt><a href= <li>Generalized Iterator Adaptor
<ul>
<li>Class template <tt><a href=
"#iterator_adaptor">iterator_adaptor</a></tt> "#iterator_adaptor">iterator_adaptor</a></tt>
<li><a href="#template_parameters">Template Parameters</a>
<li><a href="#policies">The Policies Class</a>
<li><a href="#additional_members">Additional Class Members</a>
<li><a href="#example">Example</a>
<li>(<tt>const</tt>/non-<tt>const</tt>) <a
href="#iterator_interactions">Iterator Interactions</a>
<li><a href="#challenge">Challenge</a>
<li><a href="#model_of">Model of</a>
<li><a href="#declaration_synopsis">Declaration Synopsis</a>
<li><a href="#notes">Notes</a>
</ul>
<li>Specialized Iterator Adaptors
<ul>
<li><a href="indirect_iterator.htm">Indirect Iterator Adaptor</a> <li><a href="indirect_iterator.htm">Indirect Iterator Adaptor</a>
<li><a href="reverse_iterator.htm">Reverse Iterator Adaptor</a> <li><a href="reverse_iterator.htm">Reverse Iterator Adaptor</a>
@ -44,6 +60,7 @@
<li><a href="projection_iterator.htm">Projection Iterator Adaptor</a> <li><a href="projection_iterator.htm">Projection Iterator Adaptor</a>
<li><a href="filter_iterator.htm">Filter Iterator Adaptor</a> <li><a href="filter_iterator.htm">Filter Iterator Adaptor</a>
</ul>
</ul> </ul>
<li>Header <tt><a href= <li>Header <tt><a href=
@ -54,12 +71,13 @@
<p><b><a href="http://www.boost.org/people/dave_abrahams.htm">Dave <p><b><a href="http://www.boost.org/people/dave_abrahams.htm">Dave
Abrahams</a></b> started the library, applying <a href= Abrahams</a></b> started the library, applying <a href=
"../../more/generic_programming.html#policies">policies class</a> technique "../../more/generic_programming.html#policy">policy class</a> technique
and handling const/non-const iterator interactions. He also contributed the and handling const/non-const iterator interactions. He also contributed the
<tt><a href="indirect_iterator.htm">indirect_</a></tt> and <tt><a href= <tt><a href="indirect_iterator.htm">indirect_</a></tt> and <tt><a href=
"reverse_iterator.htm">reverse_</a></tt> iterator generators, and expanded "reverse_iterator.htm">reverse_</a></tt> iterator generators, and expanded
<tt><a href="counting_iterator.htm">counting_iterator_generator</a></tt> to <tt><a href="counting_iterator.htm">counting_iterator_generator</a></tt> to
cover all incrementable types.<br> cover all incrementable types. He edited most of the documentation,
sometimes heavily.<br>
<b><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy <b><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy
Siek</a></b> contributed the <a href="transform_iterator.htm">transform Siek</a></b> contributed the <a href="transform_iterator.htm">transform
iterator</a> adaptor, the integer-only version of <tt><a href= iterator</a> adaptor, the integer-only version of <tt><a href=
@ -84,190 +102,251 @@
types. Moreover, it is easy to make a pair of interoperable <tt>const</tt> types. Moreover, it is easy to make a pair of interoperable <tt>const</tt>
and <tt>non-const</tt> iterators. and <tt>non-const</tt> iterators.
<h3>Synopsis</h3> <p><tt>iterator_adaptor</tt> is declared like this:
<pre> <pre>
template &lt;class Base, class Policies, template &lt;class Base, class Policies,
class Value = typename std::iterator_traits&lt;Base&gt;::value_type, class Value = typename std::iterator_traits&lt;Base&gt;::value_type,
class Reference = <i>...(see below)</i>, class Reference = <i>...(see below)</i>,
class Pointer = <i>...(see below)</i>, class Pointer = <i>...(see below)</i>,
class Category = typename std::iterator_traits&lt;Base&gt;::iterator_category, class Category = typename std::iterator_traits&lt;Base&gt;::iterator_category,
class Distance = typename std::iterator_traits&lt;Base&gt;::difference_type class Distance = typename std::iterator_traits&lt;Base&gt;::difference_type&gt;
&gt;
struct iterator_adaptor; struct iterator_adaptor;
{
typedef Distance difference_type;
typedef typename boost::remove_const&lt;Value&gt;::type value_type;
typedef Pointer pointer;
typedef Reference reference;
typedef Category iterator_category;
typedef Base base_type;
typedef Policies policies_type;
iterator_adaptor();
iterator_adaptor(const Base&amp;, const Policies&amp; = Policies());
base_type base() const;
template &lt;class B, class V, class R, class P&gt;
iterator_adaptor (
const iterator_adaptor&lt;B,Policies,V,R,P,Category,Distance&gt;&amp;);
reference operator*() const;
<i>operator_arrow_result_type</i> operator-&gt;() const; <a href="#2">[2]</a>
value_type operator[](difference_type n) const;
iterator_adaptor&amp; operator++();
iterator_adaptor&amp; operator++(int);
iterator_adaptor&amp; operator--();
iterator_adaptor&amp; operator--(int);
iterator_adaptor&amp; operator+=(difference_type n);
iterator_adaptor&amp; operator-=(difference_type n);
iterator_adaptor&amp; operator-(Distance x) const;
};
template &lt;class B, class P, class V, class R, class Ptr,
class C, class D1, class D2&gt;
iterator_adaptor&lt;B,P,V,R,Ptr,C,D1&gt;
operator+(iterator_adaptor&lt;B,P,V,R,Ptr,C,D1&gt;, D2);
template &lt;class B, class P, class V, class R, class Ptr,
class C, class D1, class D2&gt;
iterator_adaptor&lt;B,P,V,R,P,C,D1&gt;
operator+(D2, iterator_adaptor&lt;B,P,V,R,Ptr,C,D1&gt; p);
template &lt;class B1, class B2, class P, class V1, class V2,
class R1, class R2, class P1, class P2, class C, class D&gt;
Distance operator-(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
const iterator_adaptor&lt;B2,P,V2,R2,P2,C,D&gt;&amp;);
template &lt;class B1, class B2, class P, class V1, class V2,
class R1, class R2, class P1, class P2, class C, class D&gt;
bool operator==(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
const iterator_adaptor&lt;B2,P,V2,R2,P2,C,D&gt;&amp;);
// and similarly for operators !=, <, <=, >=, >
</pre> </pre>
<h3>Example</h3> <h3><a name="template_parameters">Template Parameters</a></h3>
<p>It is often useful to automatically apply some function to the <p>Although <tt>iterator_adaptor</tt> takes seven template parameters,
value returned by dereferencing (<tt>operator*()</tt>) an defaults have been carefully chosen to minimize the number of parameters you
iterator. The <a href="./transform_iterator.htm">transform must supply in most cases, especially if <tt>BaseType</tt> is an iterator.
iterator</a> makes it easy to create an iterator adaptor that does
just that. Here we will show how easy it is to implement the <table border>
transform iterator using the <tt>iterator_adaptor</tt> class.</p> <tr>
<th>Parameter
<th>Description
<tr>
<td><tt>BaseType</tt>
<td>The type being wrapped.
<tr>
<td><tt>Policies</tt>
<td>A <a href= "../../more/generic_programming.html#policy">policy class</a>
that supplies core functionality to the resulting iterator. A
detailed description can be found <a href="#policies">below</a>.
<tr>
<td><tt>Value</tt>
<td>The <tt>value_type</tt> of the resulting iterator, unless const. If Value is
<tt>const X</tt>, a conforming compiler makes the
<tt>value_type</tt> <tt><i>non-</i>const X</tt><a href="#1">[1]</a>.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseType&gt;::value_type</tt>
<tr>
<td><tt>Pointer</tt>
<td>The <tt>pointer</tt> type of the resulting iterator, and in
particular, the result type of operator-&gt;().<br>
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
otherwise <tt>std::iterator_traits&lt;BaseType&gt;::pointer</tt>.
<tr>
<td><tt>Reference</tt>
<td>The <tt>reference</tt> type of the resulting iterator, and in
particular, the result type of operator*().<br>
<b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&amp;</tt> is
used. Otherwise
<tt>std::iterator_traits&lt;BaseType&gt;::reference</tt> is used.
<tr>
<td><tt>Category</tt>
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseType&gt;::iterator_category</tt>
<tr>
<td><tt>Distance</tt>
<td>The <tt>difference_type</tt> for the resulting iterator.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseType&gt;::difference_type</tt>
</table>
<h3><a name="policies">The Policies Class</a></h3>
<p>The main task in using <tt>iterator_adaptor</tt> is creating an <p>The main task in using <tt>iterator_adaptor</tt> is creating an
appropriate <tt>Policies</tt> class (a general description of the appropriate <tt>Policies</tt> class.
policy class technique can be found <a href=
"../../more/generic_programming.html#policies">here</a>).
The <tt>Policies</tt> class that you pass in will become the heart of The <tt>Policies</tt> class will become the functional heart of the iterator
the iterator adaptor, supplying the core iterator operations that will adaptor, supplying the core iterator operations that will determine how your
determine how your new adaptor class will behave. The core iterator new adaptor class will behave. The <tt>iterator_adaptor</tt> template
operations are: defines all of the operators required of a
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
Random Access Iterator</a>.
Your <tt>Policies</tt> class must implement three, four, or seven of the core
iterator operations below depending on the iterator categories you want it to support.
<ul>
<li><code>dereference</code> - returns an element of the iterator's
<code>reference</code> type
<li><code>equal</code> - tests the iterator for equality
<li><code>increment</code> - increments the iterator <table border>
<caption><b>Core Iterator Operations</b></caption>
<tr><th>Operation <th>Effects <th>Required for Iterator Categories
<tr>
<td><tt>dereference</tt> <td>returns an element of the iterator's
<tt>reference</tt> type <td rowspan="3"><a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input</a>/ <a
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output</a>/ <a
href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward</a>/ <a
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/ <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access</a>
<li><code>decrement</code> - decrements bidirectional and random-access <tr><td><tt>equal</tt> <td>tests the iterator for equality
iterators
<li><code>less</code> - imposes a strict weak ordering relation on <tr><td><tt>increment</tt> <td>increments the iterator
random-access iterators
<li><code>distance</code> - measures the distance between random-access <tr><td><tt>decrement</tt> <td>decrements the iterator <td><a
iterators href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/ <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access</a>
<li><code>advance</code> - adds an integer offset to random-access <tr><td><tt>less</tt> <td>imposes a <a
iterators href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">Strict Weak
</ul> Ordering</a> relation on the iterator's <tt>reference</tt> type
The <tt>Policies</tt> class must implement three, four, or seven of the <td
core iterator operations depending on whether you wish the new iterator rowspan="3"><a
adaptor class to be a <a href= href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
"http://www.sgi.com/Technology/STL/ForwardIterator.html">ForwardIterator</a>, Access</a>
<a href=
"http://www.sgi.com/Technology/STL/BidirectionalIterator.html">BidirectionalIterator</a>, <tr><td><tt>distance</tt> <td>measures the distance between iterators
or <a href=
"http://www.sgi.com/Technology/STL/RandomAccessIterator.html">RandomAccessIterator</a>. <tr><td><tt>advance</tt> <td>adds an integer offset to iterators
The <tt>iterator_category</tt> type of the traits class you pass in must
match the category of iterator that you want to create. The default policy </table>
class, <tt>default_iterator_policies</tt>, implements all 7 of the core
<p>
The library also supplies a &quot;trivial&quot; policy class,
<tt>default_iterator_policies</tt>, which implements all seven of the core
operations in the usual way. If you wish to create an iterator adaptor that operations in the usual way. If you wish to create an iterator adaptor that
only changes a few of the iterator's behaviors, then you can have your new only changes a few of the base type's behaviors, then you can derive your new
policy class inherit from <tt>default_iterator_policies</tt> to avoid policy class from <tt>default_iterator_policies</tt> to avoid
retyping the usual behaviors. You should also look at retyping the usual behaviors. You should also look at
<tt>default_iterator_policies</tt> as the ``boiler-plate'' for your own <tt>default_iterator_policies</tt> as the ``boilerplate'' for your own
policy classes. The following is the definition of the policy classes, defining functions with the same interface. This is the definition of
<tt>default_iterator_policies</tt> class: <tt>default_iterator_policies</tt>:
<p> <p>
<blockquote> <blockquote>
<pre> <pre>
struct default_iterator_policies struct default_iterator_policies
{ {
// required for a ForwardIterator template &lt;class Reference, class BaseType&gt;
template &lt;class Reference, class Iterator&gt; Reference dereference(type&lt;Reference&gt;, const BaseType&amp; x) const
Reference dereference(type&lt;Reference&gt;, const Iterator&amp; x) const
{ return *x; } { return *x; }
template &lt;class Iterator&gt; template &lt;class BaseType&gt;
static void increment(Iterator&amp; x) static void increment(BaseType&amp; x)
{ ++x; } { ++x; }
template &lt;class Iterator1, class Iterator2&gt; template &lt;class BaseType1, class BaseType2&gt;
bool equal(Iterator1&amp; x, Iterator2&amp; y) const bool equal(BaseType1&amp; x, BaseType2&amp; y) const
{ return x == y; } { return x == y; }
// required for a BidirectionalIterator template &lt;class BaseType&gt;
template &lt;class Iterator&gt; static void decrement(BaseType&amp; x)
static void decrement(Iterator&amp; x)
{ --x; } { --x; }
// required for a RandomAccessIterator template &lt;class BaseType, class DifferenceType&gt;
template &lt;class Iterator, class DifferenceType&gt; static void advance(BaseType&amp; x, DifferenceType n)
static void advance(Iterator&amp; x, DifferenceType n)
{ x += n; } { x += n; }
template &lt;class Difference, class Iterator1, class Iterator2&gt; template &lt;class Difference, class BaseType1, class BaseType2&gt;
Difference distance(type&lt;Difference&gt;, Iterator1&amp; x, Iterator2&amp; y) const Difference distance(type&lt;Difference&gt;, BaseType1&amp; x, BaseType2&amp; y) const
{ return y - x; } { return y - x; }
template &lt;class Iterator1, class Iterator2&gt; template &lt;class BaseType1, class BaseType2&gt;
bool less(Iterator1&amp; x, Iterator2&amp; y) const bool less(BaseType1&amp; x, BaseType2&amp; y) const
{ return x &lt; y; } { return x &lt; y; }
}; };
</pre> </pre>
</blockquote> </blockquote>
<p>Template member functions are used throughout
<tt>default_iterator_policies</tt> so that it can be employed with a wide range
of iterators. If we had used concrete types above, we'd have tied the usefulness
of <tt>default_iterator_policies</tt> to a particular range of adapted
iterators. If you follow the same pattern with your <tt>Policies</tt> classes,
you may achieve the same sort of reusability.
<h3><a name="additional_members">Additional Members</a></h3>
In addition to all of the member functions required of a <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
Random Access Iterator</a>, the <tt>iterator_adaptor</tt> class
template defines the following members.
<p>
<table border>
<tr><td><tt>
iterator_adaptor(const Base&amp;, const Policies&amp; = Policies())
</tt><br>
Construct an adapted iterator from a base object and a policies object.
</td></tr>
<tr><td><tt>
template &lt;class B, class V, class R, class P&gt;<br>
iterator_adaptor(const iterator_adaptor&lt;B,Policies,V,R,P,Category,Distance&gt;&amp;)
</tt><br><br>
This constructor allows for conversion from non-<tt>const</tt> to constant
adapted iterators. See <a href="#iterator_interactions">below</a> for more details.<br>
Requires: <tt>B</tt> is convertible to <tt>Base</tt>.
</td></tr>
<tr><td><tt>
base_type base() const;
</tt><br><br>
Return a copy of the base object.
</td></tr>
</table>
<h3><a name="example">Example</a></h3>
<p>It is often useful to automatically apply some function to the
value returned by dereferencing an
iterator. The <a href="./transform_iterator.htm">transform
iterator</a> makes it easy to create an iterator adaptor which does
just that. Here we will show how easy it is to implement the
transform iterator using the <tt>iterator_adaptor</tt> template.</p>
<p>We want to be able to adapt a range of iterators and functions, so the
policies class will have a template parameter for the function type and it
will have a data member of that type. We know that the function takes
one argument and that we'll need to be able to deduce the
<tt>result_type</tt> of the function so we can use it for the adapted
iterator's <tt>value_type</tt>.
<a href="http://www.sgi.com/Technology/STL/AdaptableUnaryFunction.html">
AdaptableUnaryFunction</a> is the
<a href="../../more/generic_programming.html#concept">
Concept</a> that fulfills those requirements.
<p>
To implement a transform iterator we will only change one of the To implement a transform iterator we will only change one of the
base iterator's behaviors, so the base iterator's behaviors, so the
<tt>transform_iterator_policies</tt> class will inherit the rest <tt>transform_iterator_policies</tt> class can inherit the rest
from <tt>default_iterator_policies</tt>. In addition, we will need from <tt>default_iterator_policies</tt>. We will define the
a function object to apply, so the policies class will have a <tt>dereference()</tt> member function, which is used implement
template parameter for the function object and it will have a data <tt>operator*()</tt> of the adapted iterator. The implementation will
member of that type. The function will take one argument (the dereference the base iterator and apply the function object. The
value type of the base iterator) and we will need to know the <tt>type&lt;Reference&gt;</tt> parameter is used to convey the appropriate return
<tt>result_type</tt> of the function, so type. The complete code for <tt>transform_iterator_policies</tt> is:
<a href="http://www.sgi.com/Technology/STL/AdaptableUnaryFunction.html">
AdaptableUnaryFunction</a> is the correct
<a href="../../more/generic_programming.html#concept">
concept</a> to choose for the function object type. Inside of
<tt>transform_iterator_policies</tt> we will implement the
<tt>dereference()</tt> member function. This member function will
dereference the base iterator (the second parameter of
<tt>dereference()</tt>) and apply the function object. The
<tt>type&lt;Reference&gt;</tt> class used below is there to convey
the reference type of the iterator, which is handy when writing
generic iterator adaptors such as this one. The following is the
complete code for the <tt>transform_iterator_policies</tt> class.
<p> <p>
<blockquote> <blockquote>
@ -276,7 +355,9 @@ struct default_iterator_policies
struct transform_iterator_policies : public default_iterator_policies struct transform_iterator_policies : public default_iterator_policies
{ {
transform_iterator_policies() { } transform_iterator_policies() { }
transform_iterator_policies(const AdaptableUnaryFunction&amp; f) : m_f(f) { }
transform_iterator_policies(const AdaptableUnaryFunction&amp; f)
: m_f(f) { }
template &lt;class Reference, class BaseIterator&gt; template &lt;class Reference, class BaseIterator&gt;
Reference dereference(type&lt;Reference&gt;, const BaseIterator&amp; i) const Reference dereference(type&lt;Reference&gt;, const BaseIterator&amp; i) const
@ -288,15 +369,20 @@ struct default_iterator_policies
</blockquote> </blockquote>
<p> <p>
The next step is to use the <tt>iterator_adaptor</tt> class to The next step is to use the <tt>iterator_adaptor</tt> template to construct
construct the transform iterator type. The nicest way to package the transform iterator type. The nicest way to package the construction of
up the construction of the transform iterator is to create a <a the transform iterator is to create a <a
href="../../more/generic_programming.html#type_generator">type href="../../more/generic_programming.html#type_generator">type
generator</a>. The first template parameter of the generator will generator</a>. The first template parameter to the generator will be the
be the type of the function object and the second will be the base type of the function object and the second will be the base iterator
iterator type. Inside the <tt>transform_iterator_generator</tt> type. We use
class we use the <tt>iterator_adaptor</tt> class to create the <tt>iterator_adaptor</tt> to define the transform iterator type as a nested
transform iterator type. <tt>typedef</tt> inside the <tt>transform_iterator_generator</tt> class. Because the function may return by-value, we must limit the
<tt>iterator_category</tt> to <a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>,
and the iterator's <tt>reference</tt> type cannot be a true reference (the
standard allows this for input iterators), so in this case we can use few of
<tt>iterator_adaptor</tt>'s default template arguments.
<p> <p>
<blockquote> <blockquote>
@ -333,9 +419,9 @@ make_transform_iterator(Iterator base,
</pre> </pre>
</blockquote> </blockquote>
<p>The following is an example of how to use a transform iterator <p>Here is an example that shows how to use a transform iterator
to iterate through a range of numbers, multiplying each of them by to iterate through a range of numbers, multiplying each of them by
2 when they are dereferenced and printing the result to standard 2 and printing the result to standard
output. output.
<p> <p>
@ -364,68 +450,54 @@ This output is:
</pre> </pre>
</blockquote> </blockquote>
<h3><a name="iterator_interactions">Iterator Interactions</a></h3>
<h3>Template Parameters</h3> <p>C++ allows <tt>const</tt> and
non-<tt>const</tt> pointers to interact in the following intuitive ways:
<ul>
<li>a non-<tt>const</tt> pointer to <tt>T</tt> can be implicitly converted
to a <tt>const</tt> pointer to <tt>T</tt>.
<li><tt>const</tt> and non-<tt>const</tt> pointers to <tt>T</tt> can be
freely mixed in comparison expressions.
<li><tt>const</tt> and non-<tt>const</tt> pointers to <tt>T</tt> can be
freely subtracted, in any order.
</ul>
<table border> Getting user-defined iterators to work together that way is nontrivial, but
<tr> <tt>iterator_adaptor</tt> can make it easy. The rules are as follows:
<th>Parameter
<ul>
<li>Adapted iterators that share the same <tt>Policies</tt>, <tt>Category</tt>, and <tt>Distance</tt>
parameters are called <i>interoperable</i>.
<th>Description <li>An adapted iterator can be implicitly converted to any other adapted
iterator with which it is interoperable, so long as the <tt>Base</tt> type
of the source iterator can be converted to the <tt>Base</tt> type of the
target iterator.
<tr> <li>Interoperable iterators can be freely mixed in comparison expressions so long
<td><tt>Base</tt> as the <tt>Policies</tt> class has <tt>equal</tt> (and, for
random access iterators,
<tt>less</tt>) members that can accept both <tt>Base</tt> types in either
order.
<td>The type being wrapped. <li>Interoperable iterators can be freely mixed in subtraction expressions so long
as the <tt>Policies</tt> class has a <tt>distance</tt> member that can
accept both <tt>Base</tt> types in either order.
<tr> </ul>
<td><tt>Value</tt>
<td>The <tt>value_type</tt> of the resulting iterator, unless const. If <h3><a name="challenge">Challenge</a></h3>
const, a conforming compiler strips constness for the
<tt>value_type</tt>. Typically the default for this parameter is the
appropriate type<a href="#1">[1]</a>.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseIterator&gt;::value_type</tt>
<tr> <p>There is an unlimited number of ways the the
<td><tt>Pointer</tt> <tt>iterator_adaptors</tt> class can be used to create
iterators. One interesting exercise would be to re-implement the
<td>The <tt>pointer</tt> type of the resulting iterator, and in iterators of <tt>std::list</tt> and <tt>std::slist</tt> using
particular, the result type of operator-&gt;(). Typically the default <tt>iterator_adaptors</tt>, where the adapted <tt>Iterator</tt>
for this parameter is the appropriate type.<br> types would be node pointers.
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
otherwise <tt>std::iterator_traits&lt;BaseIterator&gt;::pointer</tt>.
<tr>
<td><tt>Reference</tt>
<td>The <tt>reference</tt> type of the resulting iterator, and in
particular, the result type of operator*(). Typically the default for
this parameter is the appropriate type.<br>
<b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&amp;</tt> is
used. Otherwise
<tt>std::iterator_traits&lt;BaseIterator&gt;::reference</tt> is used.
<tr>
<td><tt>Category</tt>
<td>The <tt>iterator_category</tt> type for the resulting iterator.
Typically the default for this parameter is the appropriate type.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseIterator&gt;::iterator_category</tt>
<tr>
<td><tt>Distance</tt>
<td>The <tt>difference_type</tt> for the resulting iterator. Typically
the default for this parameter is the appropriate type.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseIterator&gt;::difference_type</tt>
</table>
<h3>Model of</h3> <h3><a name="model_of">Model of</a></h3>
Depending on the <tt>Base</tt> and <tt>Policies</tt> template Depending on the <tt>Base</tt> and <tt>Policies</tt> template
parameters, an <tt>iterator_adaptor</tt> can be a <a parameters, an <tt>iterator_adaptor</tt> can be a <a
@ -438,92 +510,117 @@ This output is:
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
Random Access Iterator</a>. Random Access Iterator</a>.
<h3>Members</h3>
In addition to all of the member functions required of a <a <h3><a name="declaration_synopsis">Declaration Synopsis</a></h3>
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> <pre>
Random Access Iterator</a>, the <tt>iterator_adaptor</tt> class template &lt;class Base, class Policies,
template defines the following members. class Value = typename std::iterator_traits&lt;Base&gt;::value_type,
class Reference = <i>...(see below)</i>,
class Pointer = <i>...(see below)</i>,
class Category = typename std::iterator_traits&lt;Base&gt;::iterator_category,
class Distance = typename std::iterator_traits&lt;Base&gt;::difference_type
&gt;
struct iterator_adaptor
{
typedef Distance difference_type;
typedef typename boost::remove_const&lt;Value&gt;::type value_type;
typedef Pointer pointer;
typedef Reference reference;
typedef Category iterator_category;
typedef Base base_type;
typedef Policies policies_type;
<p> iterator_adaptor();
<table border> iterator_adaptor(const Base&amp;, const Policies&amp; = Policies());
<tr><td><tt>
iterator_adaptor(const Base&amp;, const Policies&amp; = Policies())
</tt><br>
Construct an iterator adaptor from a base object and a policies object.
</td></tr>
<tr><td><tt> base_type base() const;
template &lt;class B, class V, class R, class P&gt;<br>
iterator_adaptor(const iterator_adaptor&lt;B,Policies,V,R,P,Category,Distance&gt;&amp;)
</tt><br><br>
This constructor allows for conversion from mutable to constant iterator
adaptors. This assumes that the type <tt>B</tt> is convertible to the
type <tt>Base</tt>.
</td></tr>
<tr><td><tt> template &lt;class B, class V, class R, class P&gt;
base_type base() const; iterator_adaptor (
</tt><br><br> const iterator_adaptor&lt;B,Policies,V,R,P,Category,Distance&gt;&amp;);
Return a copy of the base object.
</td></tr>
</table> reference operator*() const;
<i>operator_arrow_result_type</i> operator-&gt;() const; <a href="#3">[3]</a>
<h3>Operators</h3> <i>value_type</i> operator[](difference_type n) const; <a href="#3">[4]</a>
The <tt>iterator_adaptor</tt> class defines all of the operators
required of a
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
Random Access Iterator</a>. Also, the operators of the
<tt>iterator_adaptor</tt> class that take two iterator adaptor
arguments (difference and comparisons) are defined in such a way
that the operators work on pairs of <tt>iterator_adaptor</tt>
types that have different template parameters, provided that the
base types of the iterator adaptors are interoperable. The reason
for this is so that mutable and constant versions of an iterator
adaptor can be created that will be interoperable with eachother.
<h3>Challenge</h3> iterator_adaptor&amp; operator++();
iterator_adaptor&amp; operator++(int);
iterator_adaptor&amp; operator--();
iterator_adaptor&amp; operator--(int);
<p>There is an unlimited number of ways the the iterator_adaptor&amp; operator+=(difference_type n);
<tt>iterator_adaptors</tt> class can be used to create iterator_adaptor&amp; operator-=(difference_type n);
iterators. One interesting exercise would be to re-implement the
iterators of <tt>std::list</tt> and <tt>std::slist</tt> using
<tt>iterator_adaptors</tt>, where the adapted <tt>Iterator</tt>
types would be node pointers.
<h3>Notes</h3> iterator_adaptor&amp; operator-(Distance x) const;
};
template &lt;class B, class P, class V, class R, class Ptr,
class C, class D1, class D2&gt;
iterator_adaptor&lt;B,P,V,R,Ptr,C,D1&gt;
operator+(iterator_adaptor&lt;B,P,V,R,Ptr,C,D1&gt;, D2);
template &lt;class B, class P, class V, class R, class Ptr,
class C, class D1, class D2&gt;
iterator_adaptor&lt;B,P,V,R,P,C,D1&gt;
operator+(D2, iterator_adaptor&lt;B,P,V,R,Ptr,C,D1&gt; p);
template &lt;class B1, class B2, class P, class V1, class V2,
class R1, class R2, class P1, class P2, class C, class D&gt;
Distance operator-(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
const iterator_adaptor&lt;B2,P,V2,R2,P2,C,D&gt;&amp;);
template &lt;class B1, class B2, class P, class V1, class V2,
class R1, class R2, class P1, class P2, class C, class D&gt;
bool operator==(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
const iterator_adaptor&lt;B2,P,V2,R2,P2,C,D&gt;&amp;);
// and similarly for operators !=, <, <=, >=, >
</pre>
<h3><a name="notes">Notes</a></h3>
<p><a name="1">[1]</a> If your compiler does not support partial <p><a name="1">[1]</a> If your compiler does not support partial
specialization and the base iterator is a builtin pointer type, specialization and the base iterator is a builtin pointer type,
then you will not be able to use the default for <tt>Value</tt> then you will not be able to use the default for <tt>Value</tt>
and will need to explicitly specify this type. and will need to explicitly specify this type.
<p><a name="2">[2]</a> The result type for the <tt>operator->()</tt> <p><a name="2">[2]</a> The standard specifies that the <tt>value_type</tt>
of <tt>const</tt> iterators to <tt>T</tt> (e.g. <tt>const T*</tt>) is
<tt><i>non-</i>const T</tt>, while the <tt>pointer</tt> and
<tt>reference</tt> types for all <a
href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
Iterators</a> are <tt>const T*</tt> and <tt>const T&amp;</tt>,
respectively. Stripping the <tt>const</tt>-ness of <tt>Value</tt> is
designed to allow you to easily make a <tt>const</tt> iterator adaptor by
supplying a <tt>const</tt> type for <tt>Value</tt>, and allowing the
defaults for the <tt>Pointer</tt> and <tt>Reference</tt> parameters to take
effect. Although compilers that don't support partial specialization won't
do this for you, having a <tt>const value_type</tt> is often harmless in
practice.
<p><a name="3">[3]</a> The result type for the <tt>operator->()</tt>
depends on the category and value type of the iterator and depends on the category and value type of the iterator and
is somewhat complicated to describe. But be assured, it works is somewhat complicated to describe. But be assured, it works
in a stardard conforming fashion, providing access to members in a stardard conforming fashion, providing access to members
of the objects pointed to by the iterator. of the objects pointed to by the iterator.
<h3>Implemenation Notes</h3> <p><a name="4">[4]</a> The result type of <tt>operator[]()</tt> is <tt>value_type</tt>
instead of <tt>reference</tt> as might be expected. There are two
reasons for this choice. First, the C++ standard only requires that the return
type of an arbitrary
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">
Random Access Iterator</a>'s <tt>operator[]</tt>be ``convertible to T''
(Table 76), so when adapting an arbitrary base iterator we may not have a
reference to return. Second, and more importantly, for certain kinds of
iterators, returning a reference could cause serious memory problems due to
the reference being bound to a temporary object whose lifetime ends inside
of the <tt>operator[]</tt>.
<ul>
<li>The <tt>iterator_adaptor::operator[]</tt> returns by-value
instead of by-reference as might be expected. There are two
reasons for this. First, the C++ standard only requires that
the return type by ``convertible to T'' (Table 76). Second,
and more importantly, for certain kinds of iterators,
returning a reference could cause serious memory problems due
to the reference being bound to a temporary object whose
lifetime ends inside of the <tt>operator[]</tt>.</li>
</ul>
<hr> <hr>
<p>Revised <p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->10 <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->15
Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" --> Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" -->
<p>&copy; Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy, use, modify, sell <p>&copy; Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy, use, modify, sell