*** empty log message ***

[SVN r24430]
This commit is contained in:
Thorsten Jørgen Ottosen
2004-08-12 10:58:13 +00:00
parent 7d81f9a845
commit 8378643b44
13 changed files with 507 additions and 351 deletions

View File

@ -27,6 +27,8 @@
<li > <li >
<a href="#Semantics" >Semantics</a> <a href="#Semantics" >Semantics</a>
</li> </li>
<li>
<a href="#minimal_interface">Extending the library</a>
</ul> </ul>
<hr size="1" > <hr size="1" >
@ -35,7 +37,7 @@
Four types of objects are currently supported by the library: Four types of objects are currently supported by the library:
<ul > <ul >
<li > <li >
standard containers standard-like containers
</li> </li>
<li > <li >
<code >std::pair&lt;iterator,iterator&gt;</code> <code >std::pair&lt;iterator,iterator&gt;</code>
@ -48,126 +50,139 @@
built-in arrays built-in arrays
</li> </li>
</ul> </ul>
Even though the behavior of the primary templates are exactly such Even though the behavior of the primary templates are exactly such that standard
that standard containers will be supported by default, the requirements containers will be supported by default, the requirements are much lower than
are much lower than the standard container requirements. For example, the standard container requirements. For example, the utility class <a
the utility class <a href="utility_class#iterator_range"><code>iterator_range</code></a> implements the minimal interface required to make the class href="utility_class.html#iter_range"><code>iterator_range</code></a> implements
a <a href="range.htm#forward_range">Forward Range</a>. the <a href="#minimal_interface">minimal interface</a> required to make the
class a <a href="range.htm#forward_range">Forward Range</a>.
</p> </p>
<p> <p>
Please also see <a href="range.htm">Range concepts</a> for more details. Please also see <a href="range.htm">Range concepts</a> for more details.
</p> </p>
<a name="Synopsis" ></a> <a name="Synopsis" ></a> <h3 >Synopsis</h3>
<h3 >Synopsis</h3>
<p > <p >
<pre> <pre>
namespace boost <span class=keyword>namespace </span><span class=identifier>boost</span>
{ <span class=special>{
// </span><span class=comment>//
// Single Pass Range metafunctions // Single Pass Range metafunctions
// //
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
struct <a href="#value_type_of" >value_type_of</a>; </span><span class=keyword>struct </span><a href="#value_type_of"><span
class=identifier>value_type_of</span></a><span class=special>;
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
struct <a href="#iterator_of" >iterator_of</a>; </span><span class=keyword>struct </span><a href="#iterator_of"><span
class=identifier>iterator_of</span></a><span class=special>;
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
struct <a href="#const_iterator_of" >const_iterator_of</a>; </span><span class=keyword>struct </span><a href="#const_iterator_of"><span
class=identifier>const_iterator_of</span></a><span class=special>;
// </span><span class=comment>//
// Forward Range metafunctions // Forward Range metafunctions
// //
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
struct <a href="#difference_type_of" >difference_type_of</a>; </span><span class=keyword>struct </span><a href="#difference_type_of"><span
class=identifier>difference_type_of</span></a><span class=special>;
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
struct <a href="#size_type_of" >size_type_of</a>; </span><span class=keyword>struct </span><a href="#size_type_of"><span
class=identifier>size_type_of</span></a><span class=special>;
// </span><span class=comment>//
// Bidirectional Range metafunctions // Bidirectional Range metafunctions
// //
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
struct <a href="#reverse_iterator_of" >reverse_iterator_of</a>; </span><span class=keyword>struct </span><a
href="#reverse_iterator_of"><span
class=identifier>reverse_iterator_of</span></a><span class=special>;
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
struct <a href="#const_reverse_iterator_of" >const_reverse_iterator_of</a>; </span><span class=keyword>struct </span><a
href="#const_reverse_iterator_of"><span
class=identifier>const_reverse_iterator_of</span></a><span class=special>;
// </span><span class=comment>//
// Special metafunctions // Special metafunctions
// //
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
struct <a href="#result_iterator_of" >result_iterator_of</a>; </span><span class=keyword>struct </span><a href="#result_iterator_of"><span
class=identifier>result_iterator_of</span></a><span class=special>;
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
struct <a href="#reverse_result_iterator_of" >reverse_result_iterator_of</a>; </span><span class=keyword>struct </span><a
href="#reverse_result_iterator_of"><span
class=identifier>reverse_result_iterator_of</span></a><span class=special>;
// </span><span class=comment>//
// Single Pass Range functions // Single Pass Range functions
// //
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline typename iterator_of&lt;T>::type </span><span class=keyword></span><span class=keyword>typename </span><span class=identifier>iterator_of</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;::</span><span class=identifier>type
<a href="#begin" >begin</a>( T& c ); </span><a href="#begin"><span class=identifier>begin</span></a><span class=special>( </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>c </span><span class=special>);
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline typename const_iterator_of&lt;T>::type </span><span class=keyword></span><span class=keyword>typename </span><span class=identifier>const_iterator_of</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;::</span><span class=identifier>type
<a href="#begin" >begin</a>( const T& c ); </span><a href="#begin"><span class=identifier>begin</span></a><span class=special>( </span><span class=keyword>const </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>c </span><span class=special>);
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline typename iterator_of&lt;T>::type </span><span class=keyword></span><span class=keyword>typename </span><span class=identifier>iterator_of</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;::</span><span class=identifier>type
<a href="#end" >end</a>( T& c ); </span><a href="#end"><span class=identifier>end</span></a><span class=special>( </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>c </span><span class=special>);
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline typename const_iterator_of&lt;T>::type </span><span class=keyword></span><span class=keyword>typename </span><span class=identifier>const_iterator_of</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;::</span><span class=identifier>type
<a href="#end" >end</a>( const T& c ); </span><a href="#end"><span class=identifier>end</span></a><span class=special>( </span><span class=keyword>const </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>c </span><span class=special>);
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline bool </span><span class=keyword></span><span class=keyword>bool
<a href="#empty" >empty</a>( const T& c ); </span><a href="#empty"><span class=identifier>empty</span></a><span class=special>( </span><span class=keyword>const </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>c </span><span class=special>);
// </span><span class=comment>//
// Forward Range functions // Forward Range functions
// //
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline typename size_type_of&lt;T>::type </span><span class=keyword></span><span class=keyword>typename </span><span class=identifier>size_type_of</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;::</span><span class=identifier>type
<a href="#size" >size</a>( const T& c ); </span><a href="#size"><span class=identifier>size</span></a><span class=special>( </span><span class=keyword>const </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>c </span><span class=special>);
// </span><span class=comment>//
// Bidirectional Range functions // Bidirectional Range functions
// //
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline typename reverse_iterator_of&lt;T>::type </span><span class=keyword></span><span class=keyword>typename </span><span class=identifier>reverse_iterator_of</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;::</span><span class=identifier>type
<a href="#rbegin" >rbegin</a>( T& c ); </span><a href="#rbegin"><span class=identifier>rbegin</span></a><span class=special>( </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>c </span><span class=special>);
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline typename const_reverse_iterator_of&lt;T>::type </span><span class=keyword></span><span class=keyword>typename </span><span class=identifier>const_reverse_iterator_of</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;::</span><span class=identifier>type
<a href="#rbegin" >rbegin</a>( const T& c ); </span><a href="#rbegin"><span class=identifier>rbegin</span></a><span class=special>( </span><span class=keyword>const </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>c </span><span class=special>);
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline typename reverse_iterator_of&lt;T>::type </span><span class=keyword></span><span class=keyword>typename </span><span class=identifier>reverse_iterator_of</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;::</span><span class=identifier>type
<a href="#rend" >rend</a>( T& c ); </span><a href="#rend"><span class=identifier>rend</span></a><span class=special>( </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>c </span><span class=special>);
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline typename const_reverse_iterator_of&lt;T>::type </span><span class=keyword></span><span class=keyword>typename </span><span class=identifier>const_reverse_iterator_of</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;::</span><span class=identifier>type
<a href="#rend" >rend</a>( const T& c ); </span><a href="#rend"><span class=identifier>rend</span></a><span class=special>( </span><span class=keyword>const </span><span
class=identifier>T</span><span class=special>&amp; </span><span class=identifier>c </span><span class=special>);
} // namespace 'boost' </pre> </span>
<span class=special>} </span><span class=comment>// namespace 'boost'
</span></pre>
</p> </p>
<a name="Semantics" ></a> <a name="Semantics" ></a> <h3 >Semantics</h3>
<h3 >Semantics</h3>
<h4>notation</h4> <h4>notation</h4>
<p> <p>
@ -179,7 +194,7 @@ namespace boost
</tr> </tr>
<tr> <tr>
<td><code>X</code> <td><code>X</code>
<td> <code>x</code> <td><code>x</code>
<td>any type <td>any type
</tr> </tr>
<tr> <tr>
@ -206,10 +221,9 @@ namespace boost
</p> </p>
<p> <p>
Please notice in tables below that when four lines appear in a Please notice in tables below that when four lines appear in a cell, the first
cell, the first line will describe the primary template, the second line will describe the primary template, the second line pairs of iterators, the
line pairs of iterators, the third line arrays and the last line third line arrays and the last line null-terminated strings.
null-terminated strings.
</p> </p>
<h4>Metafunctions</h4> <h4>Metafunctions</h4>
<p> <p>
@ -232,16 +246,16 @@ namespace boost
<a name="iterator_of" ></a> <a name="iterator_of" ></a>
<td ><code >iterator_of&lt;X&gt;::type</code></td> <td ><code >iterator_of&lt;X&gt;::type</code></td>
<td ><code >T::iterator</code><br> <td ><code >T::iterator</code><br>
<code >P::first_type</code><br> <code >P::first_type</code><br>
<code >A*</code><br> <code >A*</code><br>
<code>Char*</code> <code>Char*</code>
<td >compile time</td> <td >compile time</td>
</tr> </tr>
<tr > <tr >
<a name="const_iterator_of" ></a> <a name="const_iterator_of" ></a>
<td ><code >const_iterator_of&lt;X&gt;::type</code></td> <td ><code >const_iterator_of&lt;X&gt;::type</code></td>
<td ><code >T::const_iterator</code><br> <td ><code >T::const_iterator</code><br>
<code >P::first_type</code><br> <code >P::first_type</code><br>
<code >const A*</code><br> <code >const A*</code><br>
<code>const Char*</code> <code>const Char*</code>
<td >compile time</td> <td >compile time</td>
@ -250,10 +264,10 @@ namespace boost
<a name="difference_type_of" ></a> <a name="difference_type_of" ></a>
<td ><code >difference_type_of&lt;X&gt;::type</code></td> <td ><code >difference_type_of&lt;X&gt;::type</code></td>
<td ><code >T::difference_type</code><br> <td ><code >T::difference_type</code><br>
<code <code
>boost_iterator_difference&lt;P::first_type&gt;::type</code><br> >boost_iterator_difference&lt;P::first_type&gt;::type</code><br>
<code >std::ptrdiff_t</code><br> <code >std::ptrdiff_t</code><br>
<code >std::ptrdiff_t</code><br> <code >std::ptrdiff_t</code><br>
<td >compile time</td> <td >compile time</td>
</tr> </tr>
<tr > <tr >
@ -268,8 +282,8 @@ namespace boost
<tr > <tr >
<a name="result_iterator_of" ></a> <a name="result_iterator_of" ></a>
<td ><code >result_iterator_of&lt;X&gt;::type</code></td> <td ><code >result_iterator_of&lt;X&gt;::type</code></td>
<td ><code >const_iterator_of&lt;X&gt;::type</code> if <code <td ><code >const_iterator_of&lt;X&gt;::type</code> if <code
>X</code> is <code >const</code> <br> >X</code> is <code >const</code> <br>
<code >iterator_of&lt;X&gt;::type</code> otherwise </td> <code >iterator_of&lt;X&gt;::type</code> otherwise </td>
<td >compile time</td> <td >compile time</td>
</tr> </tr>
@ -289,7 +303,8 @@ namespace boost
<tr > <tr >
<a name="reverse_result_iterator_of" ></a> <a name="reverse_result_iterator_of" ></a>
<td ><code >reverse_result_iterator_of&lt;X&gt;::type</code></td> <td ><code >reverse_result_iterator_of&lt;X&gt;::type</code></td>
<td ><code >boost::reverse_iterator< typename result_iterator_of&lt;T&gt;::type ></code> <td ><code >boost::reverse_iterator< typename result_iterator_of&lt;T&gt;::type
></code>
<td >compile time</td> <td >compile time</td>
</tr> </tr>
@ -297,12 +312,11 @@ namespace boost
</table> </table>
</p> </p>
<p> <p>
The special metafunctions <code>result_iterator_of</code> and The special metafunctions <code>result_iterator_of</code> and <code>reverse_result_iterator_of</code>
<code>reverse_result_iterator_of</code> are not part are not part of any Range concept, but they are very useful when implementing
of any Range concept, but they are very useful when implementing certain certain Range classes like <a
Range classes like <a href="utility_class.html#sub_range"><code>sub_range</code></a> because of their
href="utility_class.html#sub_range"><code>sub_range</code></a> because of ability to select iterators based on constness.
their ability to select iterators based on constness.
</p> </p>
<h4>Functions</h4> <h4>Functions</h4>
@ -319,7 +333,7 @@ their ability to select iterators based on constness.
<td ><code >begin(x)</code></td> <td ><code >begin(x)</code></td>
<td ><code >result_iterator_of&lt;X&gt;::type</code></td> <td ><code >result_iterator_of&lt;X&gt;::type</code></td>
<td ><code >t.begin()</code><br> <td ><code >t.begin()</code><br>
<code >p.first</code><br> <code >p.first</code><br>
<code >a</code><br> <code >a</code><br>
<code>s</code> <code>s</code>
<td >constant time</td> <td >constant time</td>
@ -329,13 +343,13 @@ their ability to select iterators based on constness.
<td ><code >end(x)</code></td> <td ><code >end(x)</code></td>
<td ><code >result_iterator_of&lt;X&gt;::type</code></td> <td ><code >result_iterator_of&lt;X&gt;::type</code></td>
<td ><code >t.end()</code><br> <td ><code >t.end()</code><br>
<code >p.second</code><br> <code >p.second</code><br>
<code >a + sz</code> <br> <code >a + sz</code> <br>
<code >s + std::char_traits&lt;X&gt;::length( s )</code> if <code >s + std::char_traits&lt;X&gt;::length( s )</code> if <code >X</code> is <code >Char*</code>
<code >X</code> is <code >Char*</code><br> <br>
<code >s + sz - 1</code> if <code >X</code> is <code >Char[sz]</code> <br> <code >s + sz - 1</code> if <code >X</code> is <code >Char[sz]</code> <br>
<td >linear if <code >X</code> is <code >Char*</code> <br> <td >linear if <code >X</code> is <code >Char*</code> <br>
constant time otherwise</td> constant time otherwise</td>
</tr> </tr>
@ -353,9 +367,9 @@ their ability to select iterators based on constness.
<td ><code >size(x)</code></td> <td ><code >size(x)</code></td>
<td ><code >size_type_of&lt;X&gt;::type</code></td> <td ><code >size_type_of&lt;X&gt;::type</code></td>
<td ><code >t.size()</code><br> <td ><code >t.size()</code><br>
<code>std::distance(p.first,p.second)</code><br> <code>std::distance(p.first,p.second)</code><br>
<code >sz</code><br> <code >sz</code><br>
<code>end(s) - s</code> <code>end(s) - s</code>
<td >linear if <code >X</code> is <code >Char*</code> <br> <td >linear if <code >X</code> is <code >Char*</code> <br>
or if <code >std::distance()</code> is linear <br> or if <code >std::distance()</code> is linear <br>
@ -365,22 +379,91 @@ their ability to select iterators based on constness.
<a name="rbegin" ></a> <a name="rbegin" ></a>
<td ><code >rbegin(x)</code></td> <td ><code >rbegin(x)</code></td>
<td ><code >reverse_result_iterator_of&lt;X&gt;::type</code></td> <td ><code >reverse_result_iterator_of&lt;X&gt;::type</code></td>
<td ><code >reverse_result_iterator_of&lt;X&gt;::type( end(x) <td ><code >reverse_result_iterator_of&lt;X&gt;::type( end(x) )</code> <br>
)</code> <br> <td >same as <code>end(x)</code> </td> <td >same as <code>end(x)</code> </td>
</tr> </tr>
<tr > <tr >
<a name="rend" ></a> <a name="rend" ></a>
<td ><code >rend(x)</code></td> <td ><code >rend(x)</code></td>
<td ><code >reverse_result_iterator_of&lt;X&gt;::type</code></td> <td ><code >reverse_result_iterator_of&lt;X&gt;::type</code></td>
<td ><code >reverse_result_iterator_of&lt;X&gt;::type( begin(x) <td ><code >reverse_result_iterator_of&lt;X&gt;::type( begin(x) )</code>
)</code> <td >same as <code>begin(x)</code></td> <td >same as <code>begin(x)</code></td>
</tr> </tr>
</table> </table>
</p> </p>
<hr> <hr>
<a name=minimal_interface></a> <h3>Extending the library</h3>
<p>
The primary templates in this library are implemented such that standard
containers will work automatically and so will <code>boost::<a
href=../../array/index.html>array</a></code>. Below is given an overview of
which member functions and member types a class must specify to
be useable as a certain Range concept.
</p>
<p>
<table cellpadding="5" border="1">
<tr>
<th>Member function</th>
<th>Related concept</th>
<tr>
<td><code>begin()</code></td>
<td><a href="range.htm#single_pass_range">Single Pass Range</a></td>
</tr>
<tr>
<td><code>end()</code> </td>
<td><a href="range.htm#single_pass_range">Single Pass Range</a></td>
</tr>
<tr>
<td><code>size()</code></td>
<td><a href="range.htm#forward_range">Forward Range</a></td>
</tr>
</table>
</p>
<p>
Notice that <code>rbegin()</code> and <code>rend()</code> member functions
are not needed even though the container can support bidirectional iteration.
</p>
<p>
The required member types are:
</p>
<p>
<table cellpadding="5" border="1">
<tr>
<th>Member type</th>
<th>Related concept</th>
<tr>
<tr>
<td><code>value_type</code></td>
<td><a href="range.htm#single_pass_range">Single Pass Range</a></td>
</tr>
<tr>
<td><code>iterator</code></td>
<td><a href="range.htm#single_pass_range">Single Pass Range</a></td>
</tr>
<tr>
<td><code>const_iterator</code></td>
<td><a href="range.htm#single_pass_range">Single Pass Range</a></td>
</tr>
<tr>
<td><code>difference_type</code></td>
<td><a href="range.htm#forward_range">Forward Range</a></td>
</tr>
<tr>
<td><code>size_type</code></td>
<td><a href="range.htm#forward_range">Forward Range</a></td>
</tr>
</table>
</p>
<p>
Again one should notice that member types <code>reverse_iterator</code> and
<code>const_reverse_iterator</code> are not needed.
</p>
<hr>
<p> <p>
(C) Copyright Thorsten Ottosen 2003-2004 (C) Copyright Thorsten Ottosen 2003-2004
</p> </p>

View File

@ -29,6 +29,9 @@
When it is possible to come up with one, the client might choose to construct a <code >std::pair&lt;const_iterator,const_iterator&gt;</code> When it is possible to come up with one, the client might choose to construct a <code >std::pair&lt;const_iterator,const_iterator&gt;</code>
object. object.
</p> </p>
<p>
Note that an <a href="utility_class.html#iter_range">iterator_range</a>
is somewhat more convenient than a <code>pair</code>. </p>
<li > <li >
<i>Why is there not supplied more types or more functions?</i> <i>Why is there not supplied more types or more functions?</i>
<p > <p >
@ -58,11 +61,13 @@
</li> </li>
<li> <li>
<i>Should I use qualified syntax, for example <i>Should I use qualified syntax, for example
<blockquote><pre>boost::begin( r ); </pre></blockquote> <blockquote><pre>
<span class=identifier>boost</span><span class=special>::</span><span class=identifier>begin</span><span class=special>( </span><span class=identifier>r </span><span class=special>); </span>
</pre></blockquote>
instead of instead of
<blockquote> <blockquote>
<pre>using namespace boost; <pre><span class=keyword>using </span><span class=keyword>namespace </span><span class=identifier>boost</span><span class=special>;</span>
begin( r )</pre></blockquote> <span class=identifier>begin</span><span class=special>( </span><span class=identifier>r </span><span class=special>)</span></pre></blockquote>
when calling functions in this library? If so, can I still rely on argument when calling functions in this library? If so, can I still rely on argument
dependent lookup (ADL) to kick in?</i> dependent lookup (ADL) to kick in?</i>
<p> <p>
@ -73,27 +78,30 @@ begin( r )</pre></blockquote>
Daniel Frey on comp.lang.std.c++ in the thread "Whence Swap" and Daniel Frey on comp.lang.std.c++ in the thread "Whence Swap" and
it is best explained by some code: <blockquote> it is best explained by some code: <blockquote>
<pre> <pre>
namespace boost <span class=keyword>namespace </span><span class=identifier>boost</span>
{ <span class=special>{
namespace range_detail </span><span class=keyword>namespace </span><span class=identifier>range_detail
{ </span><span class=special>{
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
typename iterator_of&lt;T>:type begin( T& r ) </span><span class=keyword>typename </span><span class=identifier>iterator_of</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;:</span><span class=identifier>type </span><span class=identifier>begin</span><span class=special>( </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>)
{ /* normal implementation */ } </span><span class=special>{ </span><span class=comment>/* normal implementation */ </span><span class=special>}
} </span><span class=special>}
template< class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
typename iterator_of&lt;T>::type begin( T& r ) </span><span class=keyword>typename </span><span class=identifier>iterator_of</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>&gt;::</span><span class=identifier>type </span><span class=identifier>begin</span><span class=special>( </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>)
{ </span><span class=special>{
// </span><span class=comment>//
// Create ADL hook // Create ADL hook
// //
using range_detail::begin; </span><span class=keyword>using </span><span class=identifier>range_detail</span><span class=special>::</span><span class=identifier>begin</span><span class=special>;
return begin( r ); </span><span class=keyword>return </span><span class=identifier>begin</span><span class=special>( </span><span class=identifier>r </span><span class=special>);
} </span><span class=special>}</span>
} </pre> <span class=special>} </span>
</pre>
</blockquote> </blockquote>
Cool indeed!
</p> </p>
</ol> </ol>

View File

@ -19,7 +19,7 @@
<h2 >History and Acknowledgement</h2><a name="History" ></a> <h2 >History and Acknowledgement</h2><a name="History" ></a>
<p > <p >
The library have been under way for a long time. Dietmar K<>hl originally The library have been under way for a long time. Dietmar K<>hl originally
intended to submit an <code >array_traits&lt;&gt;</code> class template which intended to submit an <code >array_traits</code> class template which
had most of the functionality present now, but only for arrays and standard had most of the functionality present now, but only for arrays and standard
containers. containers.
</p> </p>
@ -48,9 +48,10 @@ C++ standard: <blockquote>
<p> <p>
Special thanks goes to Special thanks goes to
<ul> <ul>
<li> Pavol Droba <li> Pavol Droba for help with documentation and implementation
<li> Pavel Vozenilek <li> Pavel Vozenilek for help with porting the library
<li> Jonathan Turkanis <li> Jonathan Turkanis for help with documentation
<li> Hartmut Kaiser for being review manager
</ul> </ul>
</p> </p>
<hr> <hr>

View File

@ -18,16 +18,24 @@
<h2>Introduction</h2> <h2>Introduction</h2>
<p> <p>
When writing generic code that works with Standard Library containers, one often When writing generic code that works with standard library containers, one
finds it desirable to extend that code to work with other types that offer often finds it desirable to extend that code to work with other types that offer
enough functionality to satisfy the needs of the generic code, but in an altered enough functionality to satisfy the needs of the generic code, but in an altered
form. For example, raw arrays are often suitable for use with generic code that form. For example, raw arrays are often suitable for use with generic code that
works with containers, provided a suitable adapter is used. Likewise, null works with containers, provided a suitable adapter is used. Likewise, null
terminated strings can be treated as containers of characters, if suitably terminated strings can be treated as containers of characters, if suitably
adapted. This library provides the means to adapt Standard Library containers, adapted.
</p>
<p>
This library provides the means to adapt standard library
containers,
null terminated strings, <code>std::pairs</code> of iterators, and raw null terminated strings, <code>std::pairs</code> of iterators, and raw
arrays, such that the same generic code can work with them all. arrays (and more), such that the same generic code can work with them all.
</p> The basic idea is to add another layer of indirection using <a
href="../../mpl/doc/index.html#metafunctions">metafunctions</a> and
free-standing functions so syntactic and/or semantic differences can be removed.
</p>
<!-- <p> <!-- <p>
This library makes it possible to treat different types as if they have This library makes it possible to treat different types as if they have
@ -62,59 +70,67 @@ arrays?) </li>
): ):
<blockquote> <blockquote>
<pre > <pre >
<span class=comment>
// //
// example: extracting bounds in a generic algorithm // example: extracting bounds in a generic algorithm
// //
template< typename ForwardRange, typename T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardReadableRange</span><span class=special>, </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline typename boost::iterator_of< ForwardRange >::type </span><span class=keyword>inline </span><span class=keyword>typename </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>iterator_of</span><span class=special>&lt; </span><span class=identifier>ForwardReadableRange </span><span class=special>&gt;::</span><span class=identifier>type
find( ForwardRange& c, const T& value ) </span><span class=identifier>find</span><span class=special>( </span><span class=identifier>ForwardReadableRange</span><span class=special>&amp; </span><span class=identifier>c</span><span class=special>, </span><span class=keyword>const </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>value </span><span class=special>)
{ </span><span class=special>{
return std::find( boost::begin( c ), boost::end( c ), value ); </span><span class=keyword>return </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>find</span><span class=special>( </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>begin</span><span class=special>( </span><span class=identifier>c </span><span class=special>), </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>end</span><span class=special>( </span><span class=identifier>c </span><span class=special>), </span><span class=identifier>value </span><span class=special>);
} </span><span class=special>}
template< typename ForwardRange, typename T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardReadableRange</span><span class=special>, </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline typename boost::const_iterator_of< ForwardRange >::type </span><span class=keyword>inline </span><span class=keyword>typename </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>const_iterator_of</span><span class=special>&lt; </span><span class=identifier>ForwardReadableRange </span><span class=special>&gt;::</span><span class=identifier>type
find( const ForwardRange& c, const T& value ) </span><span class=identifier>find</span><span class=special>( </span><span class=keyword>const </span><span class=identifier>ForwardReadableRange</span><span class=special>&amp; </span><span class=identifier>c</span><span class=special>, </span><span class=keyword>const </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>value </span><span class=special>)
{ </span><span class=special>{
return std::find( boost::begin( c ), boost::end( c ), value ); </span><span class=keyword>return </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>find</span><span class=special>( </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>begin</span><span class=special>( </span><span class=identifier>c </span><span class=special>), </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>end</span><span class=special>( </span><span class=identifier>c </span><span class=special>), </span><span class=identifier>value </span><span class=special>);
} </span><span class=special>}
// </span><span class=comment>//
// replace first value and return its index // replace first value and return its index
// //
template< class ForwardRange, class T > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardReadableWriteableRange</span><span class=special>, </span><span class=keyword>class </span><span class=identifier>T </span><span class=special>&gt;
inline typename boost::size_type_of< ForwardRange >::type </span><span class=keyword>inline </span><span class=keyword>typename </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>size_type_of</span><span class=special>&lt; </span><span class=identifier>ForwardReadableWriteableRange </span><span class=special>&gt;::</span><span class=identifier>type
my_generic_replace( ForwardRange& c, const T& value, const T& replacement ) </span><span class=identifier>my_generic_replace</span><span class=special>( </span><span class=identifier>ForwardReadableWriteableRange</span><span class=special>&amp; </span><span class=identifier>c</span><span class=special>, </span><span class=keyword>const </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>value</span><span class=special>, </span><span class=keyword>const </span><span class=identifier>T</span><span class=special>&amp; </span><span class=identifier>replacement </span><span class=special>)
{ </span><span class=special>{
typename boost::iterator_of< ForwardRange >::type found = find( c, value ); </span><span class=keyword>typename </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>iterator_of</span><span class=special>&lt; </span><span class=identifier>ForwardReadableWriteableRange </span><span class=special>&gt;::</span><span class=identifier>type </span><span class=identifier>found </span><span class=special>= </span><span class=identifier>find</span><span class=special>( </span><span class=identifier>c</span><span class=special>, </span><span class=identifier>value </span><span class=special>);
if( found != boost::end( c ) ) </span><span class=keyword>if</span><span class=special>( </span><span class=identifier>found </span><span class=special>!= </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>end</span><span class=special>( </span><span class=identifier>c </span><span class=special>) </span><span class=special>)
*found = replacement; </span><span class=special>*</span><span class=identifier>found </span><span class=special>= </span><span class=identifier>replacement</span><span class=special>;
return std::distance( boost::begin( c ), found ); </span><span class=keyword>return </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>distance</span><span class=special>( </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>begin</span><span class=special>( </span><span class=identifier>c </span><span class=special>), </span><span class=identifier>found </span><span class=special>);
} </span><span class=special>}
// </span><span class=comment>//
// usage // usage
// //
const int N = 5; </span><span class=keyword>const </span><span class=keyword>int </span><span class=identifier>N </span><span class=special>= </span><span class=number>5</span><span class=special>;
std::vector<int> my_vector; </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt; </span><span class=identifier>my_vector</span><span class=special>;
int values[] = { 1,2,3,4,5,6,7,8,9 }; </span><span class=keyword>int </span><span class=identifier>values</span><span class=special>[] </span><span class=special>= </span><span class=special>{ </span><span class=number>1</span><span class=special>,</span><span class=number>2</span><span class=special>,</span><span class=number>3</span><span class=special>,</span><span class=number>4</span><span class=special>,</span><span class=number>5</span><span class=special>,</span><span class=number>6</span><span class=special>,</span><span class=number>7</span><span class=special>,</span><span class=number>8</span><span class=special>,</span><span class=number>9 </span><span class=special>};
my_vector.assign( values, values + 9 ); </span>
typedef std::vector<int>::iterator iterator; <span class=identifier>my_vector</span><span class=special>.</span><span
std::pair<iterator,iterator> my_view( boost::begin( my_vector ), class=identifier>assign</span><span class=special>( </span><span class=identifier>values</span><span class=special>, </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>end</span><span class=special>( </span><span class=identifier>values </span><span class=special>) </span><span class=special>);</span>
boost::begin( my_vector ) + N ); </span><span class=keyword>typedef </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>vector</span><span class=special>&lt;</span><span class=keyword>int</span><span class=special>&gt;::</span><span class=identifier>iterator </span><span class=identifier>iterator</span><span class=special>;
char str_val[] = "a string"; </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>pair</span><span class=special>&lt;</span><span class=identifier>iterator</span><span class=special>,</span><span class=identifier>iterator</span><span class=special>&gt; </span><span class=identifier>my_view</span><span class=special>( </span><span class=identifier>boost</span><span class=special>::</span><span class=identifier>begin</span><span class=special>( </span><span class=identifier>my_vector </span><span class=special>),
char* str = str_val; </span><span
class=identifier>boost</span><span
class=special>::</span><span class=identifier>begin</span><span class=special>( </span><span class=identifier>my_vector </span><span class=special>) </span><span class=special>+ </span><span class=identifier>N </span><span class=special>);
</span><span class=keyword>char </span><span class=identifier>str_val</span><span class=special>[] </span><span class=special>= </span><span class=string>&quot;a string&quot;</span><span class=special>;
</span><span class=keyword>char</span><span class=special>* </span><span class=identifier>str </span><span class=special>= </span><span class=identifier>str_val</span><span class=special>;
std::cout << my_generic_replace( my_vector, 4, 2 ) </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>cout </span><span class=special>&lt;&lt; </span><span class=identifier>my_generic_replace</span><span class=special>( </span><span class=identifier>my_vector</span><span class=special>, </span><span class=number>4</span><span class=special>, </span><span class=number>2 </span><span class=special>)
<< my_generic_replace( my_view, 4, 2 ) </span><span class=special>&lt;&lt; </span><span class=identifier>my_generic_replace</span><span class=special>( </span><span class=identifier>my_view</span><span class=special>, </span><span class=number>4</span><span class=special>, </span><span class=number>2 </span><span class=special>)
<< my_generic_replace( str, 'a', 'b' ); </span><span class=special>&lt;&lt; </span><span class=identifier>my_generic_replace</span><span class=special>( </span><span class=identifier>str</span><span class=special>, </span><span class=literal>'a'</span><span class=special>, </span><span class=literal>'b' </span><span class=special>);
</span>
<span class=comment>// prints '3', '5' and '0' </span>
</pre> </pre>
</blockquote> </blockquote>
By using the free-standing functions and metafunctions, the code automatically By using the free-standing functions and <a
works for all the types supported by this library. Notice that we have to href="../../mpl/doc/index.html#metafunctions">metafunctions</a>, the code automatically
works for all the types supported by this library; now and in the future.
Notice that we have to
provide two version of <code >find()</code> since we cannot forward a non-const provide two version of <code >find()</code> since we cannot forward a non-const
rvalue with reference arguments (see this article about <a href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm" target="_self" >The rvalue with reference arguments (see this article about <a href="http://std.dkuug.dk/jtc1/sc22/wg21/docs/papers/2002/n1385.htm" target="_self" >The
Forwarding Problem</a> ). Forwarding Problem</a> ).

View File

@ -24,7 +24,7 @@
library. </p> library. </p>
<p > <p >
Notice that some compilers cannot do function template ordering properly. In Notice that some compilers cannot do function template ordering properly. In
that case one must rely of <code >result_iterator_of&lt;&gt;</code> and a that case one must rely of <code >result_iterator_of</code> and a
single function definition instead of single function definition instead of
overloaded versions for const and non-const arguments. overloaded versions for const and non-const arguments.

View File

@ -80,9 +80,9 @@ category</a> of the underlying iterator type. Therefore
iterators support. See also <a href="style.html">terminology and style guidelines.</a> iterators support. See also <a href="style.html">terminology and style guidelines.</a>
for more information about naming of ranges.</p> for more information about naming of ranges.</p>
<p> <p> The concepts described below specifies associated types as
<a href="../../mpl/doc/index.html#metafunctions">metafunctions</a> and all
</p> functions as free-standing functions to allow for a layer of indirection. </p>
<hr> <hr>
<a name="single_pass_range"> <a name="single_pass_range">

View File

@ -56,7 +56,7 @@
</ul> </ul>
</ul> </ul>
Notice how we have used the categories from the <a href=../../iterator/doc/new-iter-concepts.html>new Notice how we have used the categories from the <a href=../../iterator/doc/new-iter-concepts.html>new
style iterators</a>. style iterators</a>.
<p> <p>
Notice that an iterator (and therefore an range) has one <i>traversal</i> Notice that an iterator (and therefore an range) has one <i>traversal</i>
@ -74,25 +74,36 @@
</p> </p>
<p> <p>
As an example, consider how we specify the interface of <code>std::sort()</code>. It might, however, be reasonable to specify only one category if the other
The iterator-based version looks like this: category does not matter. For example, the <a
href="utility_class.html#iter_range">iterator_range</a> can be constructed from
a Forward Range. This means that we do not care about what <i>value access</i>
properties the Range has. Similarly, a Readable Range will be one that has the
lowest possible <i>traversal</i> property (Single Pass).
</p>
<p>
As another example, consider how we specify the interface of <code>std::sort()</code>.
Algorithms are usually more cumbersome to specify the interface of since both <i>traversal</i>
and <i>value access</i> properties must be exactly defined. The iterator-based
version looks like this:
<pre> <pre>
template< class RandomAccessTraversalReadableWritableIterator > <span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>RandomAccessTraversalReadableWritableIterator </span><span class=special>&gt;
void sort( RandomAccessTraversalReadableWritableIterator first, </span><span class=keyword>void </span><span class=identifier>sort</span><span class=special>( </span><span class=identifier>RandomAccessTraversalReadableWritableIterator </span><span class=identifier>first</span><span class=special>,
RandomAccessTraversalReadableWritableIterator last ); </span><span class=identifier>RandomAccessTraversalReadableWritableIterator </span><span class=identifier>last </span><span class=special>);</span>
</pre> </pre>
For ranges the interface becomes For ranges the interface becomes
<pre> <pre>
template< class RandomAccessReadableWritableRange > <span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>RandomAccessReadableWritableRange </span><span class=special>&gt;
void sort( RandomAccessReadableWritableRange& r ); </span><span class=keyword>void </span><span class=identifier>sort</span><span class=special>( </span><span class=identifier>RandomAccessReadableWritableRange</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>);</span>
</pre> </pre>
</p>
<p>
</p> </p>
<hr> <hr>
<p> <p>
(C) Copyright Thorsten Ottosen 2003-2004 (C) Copyright Thorsten Ottosen 2003-2004

View File

@ -29,7 +29,7 @@
<li> <li>
Class <a href=#iter_range><code>iterator_range</code></a> Class <a href=#iter_range><code>iterator_range</code></a>
<li> <li>
Class <a href=#sub_range><code>sub_range</code></a> Class <a href=#sub_range><code>sub_range</code></a>
</ul> </ul>
</ul> </ul>
@ -37,133 +37,157 @@
Traversal Iterator</a> and should be used whenever fairly general code is needed. Traversal Iterator</a> and should be used whenever fairly general code is needed.
The <code>sub_range</code> class is templated on an <a href="range.htm#forward_range">Forward The <code>sub_range</code> class is templated on an <a href="range.htm#forward_range">Forward
Range</a> and it is less general, but a bit easier to use since its template Range</a> and it is less general, but a bit easier to use since its template
argument is easier to specify. argument is easier to specify. The biggest difference is, however, that a
<code>sub_range</code> can propagate constness because it knows what a
corresponding <code>const_iterator</code> is. </p>
<p>
Both classes can be used as ranges since they implement the <a
href="boost_range.html#minimal_interface">minimal interface</a>
required for this to work automatically.
</p> </p>
<hr> <hr>
<a name=iter_range></a> <h1>Class <code>iterator_range</code></h1> <a name=iter_range></a> <h1>Class <code>iterator_range</code></h1>
<p> <p>
The intention of the <code>iterator_range</code> class is to encapsulate two The intention of the <code>iterator_range</code> class is to encapsulate two
iterators so they fulfill the <a iterators so they fulfill the <a
href="range.htm#forward_range">Forward Range</a> concept. A few other functions href="range.htm#forward_range">Forward Range</a> concept. A few other functions
are also provided for convenience. are also provided for convenience.
</p> </p>
<p> <p>
If the template argument is not a model of Forward Traversal Iterator, one If the template argument is not a model of Forward Traversal Iterator, one can
can still use a subset of the interface. In particular, <code>size()</code> still use a subset of the interface. In particular, <code>size()</code> requires
requires Forward Traversal Iterators whereas <code>empty()</code> only Forward Traversal Iterators whereas <code>empty()</code> only requires Single
requires Single Pass Iterators. Pass Iterators.
</p> </p>
<h3>Synopsis</h3> <h3>Synopsis</h3>
<pre> <pre>
namespace boost <span class=keyword>namespace </span><span class=identifier>boost</span>
{ <span class=special>{
template< class ForwardTraversalIterator > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardTraversalIterator </span><span class=special>&gt;
class iterator_range </span><span class=keyword>class </span><span class=identifier>iterator_range
{ </span><span class=special>{
iterator_range(); // not implemented </span><span class=keyword>public</span><span class=special>: </span><span class=comment>// Forward Range types
</span><span class=keyword>typedef </span><span class=special>... </span><span class=identifier>value_type</span><span class=special>;
public: // Forward Range types </span><span class=keyword>typedef </span><span class=special>... </span><span class=identifier>difference_type</span><span class=special>;
typedef ... value_type; </span><span class=keyword>typedef </span><span class=special>... </span><span class=identifier>size_type</span><span class=special>;
typedef ... difference_type; </span><span class=keyword>typedef </span><span class=identifier>ForwardTraversalIterator </span><span class=identifier>iterator</span><span class=special>;
typedef ... size_type; </span><span class=keyword>typedef </span><span class=identifier>ForwardTraversalIterator </span><span class=identifier>const_iterator</span><span class=special>;
typedef ForwardTraversalIterator iterator;
typedef ForwardTraversalIterator const_iterator;
public: // construction, assignment </span><span class=keyword>public</span><span class=special>: </span><span class=comment>// construction, assignment
template< class ForwardTraversalIterator2 > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardTraversalIterator2 </span><span class=special>&gt;
iterator_range( ForwardTraversalIterator2 Begin, ForwardTraversalIterator2 End ); </span><span class=identifier>iterator_range</span><span class=special>( </span><span class=identifier>ForwardTraversalIterator2 </span><span class=identifier>Begin</span><span class=special>, </span><span class=identifier>ForwardTraversalIterator2 </span><span class=identifier>End </span><span class=special>);
template< class ForwardRange > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardRange </span><span class=special>&gt;
iterator_range( ForwardRange& r ); </span><span class=identifier>iterator_range</span><span class=special>( </span><span class=identifier>ForwardRange</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>);
template< class ForwardRange > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardRange </span><span class=special>&gt;
iterator_range( const ForwardRange& r ); </span><span class=identifier>iterator_range</span><span class=special>( </span><span class=keyword>const </span><span class=identifier>ForwardRange</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>);
template< class ForwardRange > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardRange </span><span class=special>&gt;
iterator_range& operator=( ForwardRange& r ); </span><span class=identifier>iterator_range</span><span class=special>&amp; </span><span class=keyword>operator</span><span class=special>=( </span><span class=identifier>ForwardRange</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>);
template< class ForwardRange > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardRange </span><span class=special>&gt;
iterator_range& operator=( const ForwardRange& r ); </span><span class=identifier>iterator_range</span><span class=special>&amp; </span><span class=keyword>operator</span><span class=special>=( </span><span class=keyword>const </span><span class=identifier>ForwardRange</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>);
public: // Forward Range functions </span><span class=keyword>public</span><span class=special>: </span><span class=comment>// Forward Range functions
iterator begin() const; </span><span class=identifier>iterator </span><span class=identifier>begin</span><span class=special>() </span><span class=keyword>const</span><span class=special>;
iterator end() const; </span><span class=identifier>iterator </span><span class=identifier>end</span><span class=special>() </span><span class=keyword>const</span><span class=special>;
size_type size() const; </span><span class=identifier>size_type </span><span class=identifier>size</span><span class=special>() </span><span class=keyword>const</span><span class=special>;
bool empty() const; </span><span class=keyword>bool </span><span class=identifier>empty</span><span class=special>() </span><span class=keyword>const</span><span class=special>;
public: // convenience </span><span class=keyword>public</span><span class=special>: </span><span class=comment>// convenience
operator unspecified_bool_type() const; </span><span class=keyword>operator </span><a
}; href="#unspecified_bool"><span class=identifier>unspecified_bool_type</span></a><span class=special>() </span><span class=keyword>const</span><span class=special>;
</span><span class=special>};
// stream output </span><span class=comment>// stream output
template< class ForwardTraversalIterator, class T, class Traits > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardTraversalIterator</span><span class=special>, </span><span class=keyword>class </span><span class=identifier>T</span><span class=special>, </span><span class=keyword>class </span><span class=identifier>Traits </span><span class=special>&gt;
std::basic_ostream&lt;T,Traits>& operator<<( std::basic_ostream&lt;T,Traits>& Os, </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>basic_ostream</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Traits</span><span class=special>&gt;&amp;
const iterator_range&lt;ForwardTraversalIterator>& r ); </span><span class=keyword>operator</span><span class=special>&lt;&lt;( </span><span class=identifier>std</span><span class=special>::</span><span class=identifier>basic_ostream</span><span class=special>&lt;</span><span class=identifier>T</span><span class=special>,</span><span class=identifier>Traits</span><span class=special>&gt;&amp; </span><span class=identifier>Os</span><span class=special>,
</span><span class=keyword>const </span><span class=identifier>iterator_range</span><span class=special>&lt;</span><span class=identifier>ForwardTraversalIterator</span><span class=special>&gt;&amp; </span><span class=identifier>r </span><span class=special>);
// comparison </span><span class=comment>// comparison
template< class ForwardTraversalIterator > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardTraversalIterator</span><span class=special>, </span><span class=keyword>class </span><span class=identifier>ForwardTraversalIterator2 </span><span class=special>&gt;
bool operator==( const iterator_range&lt;ForwardTraversalIterator>& l, const iterator_range&lt;ForwardTraversalIterator>& r ); </span><span class=keyword>bool </span><span class=keyword>operator</span><span class=special>==( </span><span class=keyword>const </span><span class=identifier>iterator_range</span><span class=special>&lt;</span><span class=identifier>ForwardTraversalIterator</span><span class=special>&gt;&amp; </span><span class=identifier>l</span><span class=special>,
</span><span class=keyword>const </span><span class=identifier>iterator_range</span><span class=special>&lt;</span><span class=identifier>ForwardTraversalIterator2</span><span class=special>&gt;&amp; </span><span class=identifier>r </span><span class=special>);
template< class ForwardTraversalIterator > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardTraversalIterator</span><span class=special>, </span><span class=keyword>class </span><span class=identifier>ForwardTraversalIterator2 </span><span class=special>&gt;
bool operator!=( const iterator_range&lt;ForwardTraversalIterator>& l, const iterator_range&lt;ForwardTraversalIterator>& r ); </span><span class=keyword>bool </span><span class=keyword>operator</span><span class=special>!=( </span><span class=keyword>const </span><span class=identifier>iterator_range</span><span class=special>&lt;</span><span class=identifier>ForwardTraversalIterator</span><span class=special>&gt;&amp; </span><span class=identifier>l</span><span class=special>,
</span><span class=keyword>const </span><span class=identifier>iterator_range</span><span class=special>&lt;</span><span class=identifier>ForwardTraversalIterator2</span><span class=special>&gt;&amp; </span><span class=identifier>r </span><span class=special>);
// external construction </span><span class=comment>// external construction
template< class ForwardTraversalIterator > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardTraversalIterator </span><span class=special>&gt;
iterator_range< ForwardTraversalIterator > </span><span class=identifier>iterator_range</span><span class=special>&lt; </span><span class=identifier>ForwardTraversalIterator </span><span class=special>&gt;
make_iterator_range( ForwardTraversalIterator Begin, ForwardTraversalIterator End ); </span><span class=identifier>make_iterator_range</span><span class=special>( </span><span class=identifier>ForwardTraversalIterator </span><span class=identifier>Begin</span><span class=special>,
</span><span class=identifier>ForwardTraversalIterator </span><span class=identifier>End </span><span class=special>);
template< class ForwardRange > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardRange </span><span class=special>&gt;
iterator_range< typename iterator_of&lt;ForwardRange>::type > </span><span class=identifier>iterator_range</span><span class=special>&lt; </span><span class=keyword>typename </span><span class=identifier>iterator_of</span><span class=special>&lt;</span><span class=identifier>ForwardRange</span><span class=special>&gt;::</span><span class=identifier>type </span><span class=special>&gt;
make_iterator_range( ForwardRange& r ); </span><span class=identifier>make_iterator_range</span><span class=special>( </span><span class=identifier>ForwardRange</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>);
template< class ForwardRange > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardRange </span><span class=special>&gt;
iterator_range< typename const_iterator_of&lt;ForwardRange>::type > </span><span class=identifier>iterator_range</span><span class=special>&lt; </span><span class=keyword>typename </span><span class=identifier>const_iterator_of</span><span class=special>&lt;</span><span class=identifier>ForwardRange</span><span class=special>&gt;::</span><span class=identifier>type </span><span class=special>&gt;
make_iterator_range( const ForwardRange& r ); </span><span class=identifier>make_iterator_range</span><span class=special>( </span><span class=keyword>const </span><span class=identifier>ForwardRange</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>);
// convenience </span><span class=comment>// convenience
template< class Sequence, class ForwardRange > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>Sequence</span><span class=special>, </span><span class=keyword>class </span><span class=identifier>ForwardRange </span><span class=special>&gt;
Sequence copy_range( const ForwardRange& r ); </span><span class=identifier>Sequence </span><a href="#copy_range"><span
class=identifier>copy_range</span></a><span class=special>( </span><span
class=keyword>const </span><span class=identifier>ForwardRange</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>);
template< class Sequence, class ForwardRange, class Func > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>Sequence</span><span class=special>, </span><span class=keyword>class </span><span class=identifier>ForwardRange</span><span class=special>, </span><span class=keyword>class </span><span class=identifier>Func </span><span class=special>&gt;
Sequence transform_range( const ForwardRange& r, Func func ); </span><span class=identifier>Sequence </span><a
href="#transform_range"><span
} // namespace 'boost' class=identifier>transform_range</span></a><span class=special>( </span><span
class=keyword>const </span><span class=identifier>ForwardRange</span><span class=special>&amp; </span><span class=identifier>r</span><span class=special>, </span><span class=identifier>Func </span><span class=identifier>func </span><span class=special>);
</span>
<span class=special>} </span><span class=comment>// namespace 'boost'</span>
</pre> </pre>
<p> <p>
It is worth noticing that the templated constructors and assignment operators If an instance of
allow conversion from <code>iterator_range&lt;iterator></code> to
<code>iterator_range&lt;const_iterator></code>. If an instance of
<code>iterator_range</code> is constructed by a client with two iterators, the <code>iterator_range</code> is constructed by a client with two iterators, the
client must ensure that the two iterators delimit a valid closed-open range client must ensure that the two iterators delimit a valid closed-open range
<code>[begin,end)</code>. <code>[begin,end)</code>.
</p> </p>
<p>
It is worth noticing that the templated constructors and assignment operators
allow conversion from <code>iterator_range&lt;iterator></code> to
<code>iterator_range&lt;const_iterator></code>. Similarly, since the comparison
operators have two template arguments, we can compare ranges whenever the
iterators are comparable; for example when we are dealing with const and
non-const iterators from the same container. </p>
<h3>Details member functions</h3> <h3>Details member functions</h3>
<code>operator unspecified_bool_type() const; </code> <a name="unspecified_bool"></a>
<code>operator unspecified_bool_type() const; </code>
<blockquote> <blockquote>
Returns <code>!empty().</code> Returns <code>!empty().</code>
<!--
<b>Example</b> <code> iterator_range<const char*> r( "a string" ); if( r ) <!--
do_something();</code>--> <b>Example</b> <code> iterator_range<const char*> r( "a string" ); if( r )
do_something();</code>-->
</blockquote> </blockquote>
<h3>Details functions</h3> <h3>Details functions</h3>
<a name="copy_range"></a>
<code>Sequence copy_range( const ForwardRange& r );</code> <code>Sequence copy_range( const ForwardRange& r );</code>
<blockquote> <blockquote>
Constructs a new sequence of the specified type from the elements Constructs a new sequence of the specified type from the elements
in the given range. in the given range.
</blockquote> </blockquote>
<a name="transform_range"></a>
<code>Sequence transform_range( const ForwardRange& r, Func func );</code> <code>Sequence transform_range( const ForwardRange& r, Func func );</code>
<blockquote> <blockquote>
Constructs a new sequence from the elements in the range, Constructs a new sequence from the elements in the range,
transformed by a function. transformed by a function.
</blockquote> </blockquote>
@ -175,48 +199,67 @@ The <code>sub_range</code> class inherits all its functionality
from the <a href="#iter_range"><code>iterator_range</code></a> class. from the <a href="#iter_range"><code>iterator_range</code></a> class.
The <code>sub_range</code> class is often easier to use because The <code>sub_range</code> class is often easier to use because
one must specify the <a href="range.html#forward_range">Forward Range</a> one must specify the <a href="range.html#forward_range">Forward Range</a>
template argument instead of an iterator. template argument instead of an iterator. Moreover, the <code>sub_range</code>
class can propagate constness since it knows what a corresponding
<code>const_iterator</code> is.
<h3>Synopsis</h3> <h3>Synopsis</h3>
<pre> <pre>
namespace boost <span class=keyword>namespace </span><span class=identifier>boost</span>
{ <span class=special>{
</span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardRange </span><span class=special>&gt;
</span><span class=keyword>class </span><span class=identifier>sub_range </span><span class=special>: </span><span class=keyword>public </span><span class=identifier>iterator_range</span><span class=special>&lt; </span><span class=keyword>typename </span><span class=identifier>result_iterator_of</span><span class=special>&lt;</span><span class=identifier>ForwardRange</span><span class=special>&gt;::</span><span class=identifier>type </span><span class=special>&gt;
</span><span class=special>{
</span><span class=keyword>public</span><span class=special>: </span>
<span class=keyword>typedef </span><span class=keyword>typename </span><span class=identifier>iterator_of</span><span class=special>&lt;</span><span class=identifier>ForwardRange</span><span
class=special>&gt;::</span><span class=identifier>type </span><span class=identifier>iterator</span><span class=special>;</span>
<span class=keyword>typedef </span><span class=keyword>typename </span><span class=identifier>const_iterator_of</span><span class=special>&lt;</span><span class=identifier>ForwardRange</span><span class=special>&gt;::</span><span class=identifier>type </span><span class=identifier>const_iterator</span><span class=special>;</span>
template< class ForwardRange > <span class=keyword>public</span><span class=special>: </span><span class=comment>// construction, assignment
class sub_range : public iterator_range< typename result_iterator_of&lt;ForwardRange>::type > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardTraversalIterator </span><span class=special>&gt;
{ </span><span class=identifier>sub_range</span><span class=special>( </span><span class=identifier>ForwardTraversalIterator </span><span class=identifier>Begin</span><span class=special>, </span><span class=identifier>ForwardTraversalIterator </span><span class=identifier>End </span><span class=special>);
public: // construction, assignment
template< class ForwardTraversalIterator >
sub_range( ForwardTraversalIterator Begin, ForwardTraversalIterator End );
template< class ForwardRange2 > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardRange2 </span><span class=special>&gt;
sub_range( ForwardRange2& r ); </span><span class=identifier>sub_range</span><span class=special>( </span><span class=identifier>ForwardRange2</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>);
template< class ForwardRange2 > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardRange2 </span><span class=special>&gt;
sub_range( const Range2& r ); </span><span class=identifier>sub_range</span><span class=special>( </span><span class=keyword>const </span><span class=identifier>Range2</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>);
template< class ForwardRange2 > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardRange2 </span><span class=special>&gt;
sub_range& operator=( ForwardRange2& r ); </span><span class=identifier>sub_range</span><span class=special>&amp; </span><span class=keyword>operator</span><span class=special>=( </span><span class=identifier>ForwardRange2</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>);
template< class ForwardRange2 > </span><span class=keyword>template</span><span class=special>&lt; </span><span class=keyword>class </span><span class=identifier>ForwardRange2 </span><span class=special>&gt;
sub_range& operator=( const ForwardRange2& r ); </span><span class=identifier>sub_range</span><span class=special>&amp; </span><span class=keyword>operator</span><span class=special>=( </span><span class=keyword>const </span><span class=identifier>ForwardRange2</span><span class=special>&amp; </span><span class=identifier>r </span><span class=special>);
</span>
<span class=keyword>public</span><span class=special>:
</span><span class=identifier>iterator </span><span
class=identifier>begin</span><span class=special>();
</span><span class=identifier>const_iterator </span><span class=identifier>begin</span><span class=special>() </span><span class=keyword>const</span><span class=special>;
</span><span class=identifier>iterator </span><span class=identifier>end</span><span class=special>();
</span><span class=identifier>const_iterator </span><span class=identifier>end</span><span class=special>() </span><span class=keyword>const</span><span class=special>;</span>
public: <span class=keyword>public</span><span class=special>:
// rest of interface inherited from iterator_range </span><span class=comment>// rest of interface inherited from iterator_range
}; </span><span class=special>};
</span>
} // namespace 'boost' <span class=special>} </span><span class=comment>// namespace 'boost'</span>
</pre> </pre>
<p> <p>
The class should be trivial to use, an example with strings is shown below. The class should be trivial to use as seen below.
Imagine that we have an algorithm that searches for a sub-string in a string.
The
result is an <code>iterator_range</code>, that delimits the match. We need to
store the result
from this algorithm. Here is an example of how we can do it with and without
<code>sub_range</code>
<pre> <pre>
typedef sub_range<std::string> sub_string; <span class=identifier>std</span><span class=special>::</span><span class=identifier>string </span><span class=identifier>str</span><span class=special>(</span><span class=string>&quot;hello&quot;</span><span class=special>);
std::string s = "something"; </span><span class=identifier>iterator_range</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>::</span><span class=identifier>iterator</span><span class=special>&gt; </span><span class=identifier>ir </span><span class=special>= </span><span class=identifier>find_first</span><span class=special>( </span><span class=identifier>str</span><span class=special>, </span><span class=string>&quot;ll&quot; </span><span class=special>);
sub_string ss( s ); </span><span class=identifier>sub_range</span><span class=special>&lt;</span><span class=identifier>std</span><span class=special>::</span><span class=identifier>string</span><span class=special>&gt; </span><span class=identifier>sub </span><span class=special>= </span><span class=identifier>find_first</span><span class=special>( </span><span class=identifier>str</span><span class=special>, </span><span class=string>&quot;ll&quot; </span><span class=special>);</span>
sub_string ss2( begin( s ), begin( s ) + 2 );</pre> </pre>
</p>
<hr> <hr>
<p> <p>
@ -236,6 +279,7 @@ namespace boost
<br> <br>
<br> <br>
</body> </body>
</html> </html>

View File

@ -51,8 +51,6 @@ namespace boost {
template<typename IteratorT> template<typename IteratorT>
class iterator_range class iterator_range
{ {
iterator_range(); // not implemented
public: public:
//! this type //! this type
typedef iterator_range<IteratorT> type; typedef iterator_range<IteratorT> type;
@ -185,9 +183,9 @@ namespace boost {
/*! /*!
Compare operands for equality Compare operands for equality
*/ */
template< class IteratorT > template< class IteratorT, class IteratorT2 >
inline bool operator==( const iterator_range<IteratorT>& l, inline bool operator==( const iterator_range<IteratorT>& l,
const iterator_range<IteratorT>& r ) const iterator_range<IteratorT2>& r )
{ {
return ! (l != r); return ! (l != r);
} }
@ -196,9 +194,9 @@ namespace boost {
/*! /*!
Compare operands for non-equality Compare operands for non-equality
*/ */
template< class IteratorT > template< class IteratorT, class IteratorT2 >
inline bool operator!=( const iterator_range<IteratorT>& l, inline bool operator!=( const iterator_range<IteratorT>& l,
const iterator_range<IteratorT>& r ) const iterator_range<IteratorT2>& r )
{ {
return l.begin() != r.begin() || l.end() != r.end(); return l.begin() != r.begin() || l.end() != r.end();
} }

View File

@ -23,17 +23,15 @@ namespace boost
template< class ForwardRange > template< class ForwardRange >
class sub_range : public iterator_range< BOOST_DEDUCED_TYPENAME result_iterator_of<ForwardRange>::type > class sub_range : public iterator_range< BOOST_DEDUCED_TYPENAME result_iterator_of<ForwardRange>::type >
{ {
sub_range(); // not implemented
typedef BOOST_DEDUCED_TYPENAME result_iterator_of<ForwardRange>::type iterator_t; typedef BOOST_DEDUCED_TYPENAME result_iterator_of<ForwardRange>::type iterator_t;
typedef iterator_range< iterator_t > base; typedef iterator_range< iterator_t > base;
public: public:
using base::iterator; using BOOST_DEDUCED_TYPENAME base::value_type;
using base::const_iterator; using BOOST_DEDUCED_TYPENAME base::iterator;
using base::value_type; typedef BOOST_DEDUCED_TYPENAME const_iterator_of<ForwardRange>::type const_iterator;
typedef BOOST_DEDUCED_TYPENAME difference_type_of<ForwardRange>::type difference_type; typedef BOOST_DEDUCED_TYPENAME difference_type_of<ForwardRange>::type difference_type;
typedef BOOST_DEDUCED_TYPENAME size_type_of<ForwardRange>::type size_type; typedef BOOST_DEDUCED_TYPENAME size_type_of<ForwardRange>::type size_type;
public: public:
template< class ForwardRange2 > template< class ForwardRange2 >
@ -63,10 +61,13 @@ namespace boost
return *this; return *this;
} }
size_type size() const public:
{
return base::size(); iterator begin() { return base::begin(); }
} const_iterator begin() const { return base::begin(); }
iterator end() { return base::end(); }
const_iterator end() const { return base::end(); }
size_type size() const { return std::distance( begin(), end() ); }
}; };

View File

@ -1,28 +0,0 @@
// Boost.Range library
//
// Copyright Thorsten Ottosen 2003-2004. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// For more information, see http://www.boost.org/libs/range/
//
#ifndef BOOST_RANGE_TYPES_HPP
#define BOOST_RANGE_TYPES_HPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif
#include <boost/range/iterator.hpp>
#include <boost/range/const_iterator.hpp>
#include <boost/range/value_type.hpp>
#include <boost/range/size_type.hpp>
#include <boost/range/difference_type.hpp>
#include <boost/range/result_iterator.hpp>
#include <boost/range/reverse_iterator.hpp>
#include <boost/range/const_reverse_iterator.hpp>
#include <boost/range/reverse_result_iterator.hpp>
#endif

View File

@ -17,6 +17,8 @@
#include <boost/range/functions.hpp > #include <boost/range/functions.hpp >
#include <boost/range/metafunctions.hpp> #include <boost/range/metafunctions.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/test_tools.hpp>
#include <iostream> #include <iostream>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
@ -24,7 +26,6 @@
namespace namespace
{ {
// //
// example: extrating bounds in a generic algorithm // example: extrating bounds in a generic algorithm
// //
@ -58,12 +59,12 @@ namespace
} }
int main() void check_algorithm()
{ {
// //
// usage // usage
// //
const int N = 5; const unsigned N = 5;
std::vector<int> my_vector; std::vector<int> my_vector;
int values[] = { 1,2,3,4,5,6,7,8,9 }; int values[] = { 1,2,3,4,5,6,7,8,9 };
my_vector.assign( values, values + 9 ); my_vector.assign( values, values + 9 );
@ -73,8 +74,24 @@ int main()
char str_val[] = "a string"; char str_val[] = "a string";
char* str = str_val; char* str = str_val;
std::cout << my_generic_replace( my_vector, 4, 2 ) BOOST_CHECK_EQUAL( my_generic_replace( my_vector, 4, 2 ), 3u );
<< my_generic_replace( my_view, 4, 2 ) BOOST_CHECK_EQUAL( my_generic_replace( my_view, 4, 2 ), N );
<< my_generic_replace( str, 'a', 'b' ); BOOST_CHECK_EQUAL( my_generic_replace( str, 'a', 'b' ), 0u );
return 0;
} }
#include <boost/test/included/unit_test_framework.hpp>
using boost::unit_test_framework::test_suite;
test_suite* init_unit_test_suite( int argc, char* argv[] )
{
test_suite* test = BOOST_TEST_SUITE( "Range Test Suite" );
test->add( BOOST_TEST_CASE( &check_algorithm ) );
return test;
}

View File

@ -60,11 +60,13 @@ void check_iterator_range()
typedef sub_range<const string> csrange; typedef sub_range<const string> csrange;
srange s = r; srange s = r;
BOOST_CHECK( r == r ); BOOST_CHECK( r == r );
BOOST_CHECK( s == r );
s = make_iterator_range( str ); s = make_iterator_range( str );
csrange s2 = r; csrange s2 = r;
s2 = r2; s2 = r2;
s2 = make_iterator_range( cstr ); s2 = make_iterator_range( cstr );
BOOST_CHECK( r2 == r2 ); BOOST_CHECK( r2 == r2 );
BOOST_CHECK( s2 != r2 );
s2 = make_iterator_range( str ); s2 = make_iterator_range( str );
BOOST_CHECK( !(s != s) ); BOOST_CHECK( !(s != s) );
@ -88,7 +90,10 @@ void check_iterator_range()
string res = copy_range<string>( r ); string res = copy_range<string>( r );
BOOST_CHECK( equal( res.begin(), res.end(), r.begin() ) ); BOOST_CHECK( equal( res.begin(), res.end(), r.begin() ) );
res = transform_range<string>( r, add_one() );
BOOST_CHECK( res[0] == 'i' );
BOOST_CHECK( *res.rbegin() == 'e' );
r.empty(); r.empty();
s.empty(); s.empty();
r.size(); r.size();