*** empty log message ***

[SVN r24368]
This commit is contained in:
Thorsten Jørgen Ottosen
2004-08-10 09:56:55 +00:00
parent 7b37911918
commit 6157440017
11 changed files with 989 additions and 626 deletions

View File

@ -3,6 +3,7 @@
<head> <head>
<title>Boost.Range Range Implementation </title> <title>Boost.Range Range Implementation </title>
<meta http-equiv="Content-Type"content="text/html; charset=iso-8859-1"> <meta http-equiv="Content-Type"content="text/html; charset=iso-8859-1">
<link rel="stylesheet" href="style.css" type="text/css">
</head> </head>
<body> <body>
@ -42,17 +43,14 @@ Five types of objects are currently supported by the library:
standard containers standard containers
</li> </li>
<li > <li >
built-in arrays <code >std::pair&lt;iterator,iterator&gt;</code>
</li> </li>
<li > <li >
null terminated strings (this includes <code >char[]</code>,<code >wchar_t[]</code>, null terminated strings (this includes <code >char[]</code>,<code >wchar_t[]</code>,
<code >char*</code>, and <code >wchar_t*</code>) <code >char*</code>, and <code >wchar_t*</code>)
</li> </li>
<li > <li >
<code >std::pair&lt;iterator,iterator&gt;</code> built-in arrays
</li>
<li >
iterators which when default constructed denotes the end of the range
</li> </li>
</ul> </ul>
It is worth noticing that some functionality requires partial template It is worth noticing that some functionality requires partial template
@ -61,99 +59,102 @@ small problem since one would use <code>boost::array<></code> anyway). Also note
that arrays and pointers of <code >char</code> or <code >whar_t</code> are that arrays and pointers of <code >char</code> or <code >whar_t</code> are
treated special because of their use in string algorithms. treated special because of their use in string algorithms.
</p> </p>
<h3 >ExternalCollectionConcept</h3><a name="ExternalCollectionConcept" ></a>
<p > <p >
The concept is defined by the type-generators and the functions below. Even The concept is defined by the metafunction and the functions below. Even
though these functions are defined in namespace <code>boost</code>, there is no though these functions are defined in namespace <code>boost</code>, there is no
such general requirement, that is, if one wants to extend the list of supported such general requirement, that is, if one wants to extend the list of supported
types, it can be done in any namespace. types, it can be done in any namespace.
</p> </p>
<h3 >Synopsis</h3><a name="Synopsis" ></a> <h3 >Synopsis</h3><a name="Synopsis" ></a>
<p > <p >
<pre> <pre>
namespace boost namespace boost
{ {
// //
// type generators // Range metafunctions
// //
template< typename EC >
struct <a href="#value_type_of" >value_type_of</a>
{
typedef ... type; // type of stored objects
};
template< typename EC >
struct <a href="#iterator_of" >iterator_of</a>
{
typedef ... type; // iterator over stored objects
};
template< typename EC >
struct <a href="#const_iterator_of" >const_iterator_of</a>
{
typedef ... type; // iterator over immutable stored objects
};
template< typename EC >
struct <a href="#difference_type_of" >difference_type_of</a>
{
typedef ... type;
BOOST_STATIC_ASSERT( boost::is_signed< type >::value );
//
// remark: if std::iterator_traits<> works for the type, this assertion must
hold
//
BOOST_STATIC_ASSERT( boost::is_same< type, std::iterator_traits< typename
<a href="#iterator_of" >iterator_of</a>< EC >::type >::difference_type>::value );
};
template< typename EC >
struct <a href="#size_type_of" >size_type_of</a>
{
typedef ... type;
BOOST_STATIC_ASSERT( boost::is_unsigned< type >::value );
BOOST_STATIC_ASSERT( sizeof( type ) >= sizeof( <a href="#difference_type_of" >
difference_type_of</a>< EC >::type ) );
};
template< typename EC >
struct <a href="#result_iterator_of" >result_iterator_of</a>
{
typedef ... type;
// <a href="#iterator_of" >iterator_of</a>< EC >::type if EC is non-const, <a href="#const_iterator_of" >
const_iterator_of</a>< EC >::type otherwise
};
//
// funtions
//
template< typename EC >
inline typename iterator_of<EC>::type
<a href="#begin" >begin</a>( EC& c );
template< typename EC > template< class T >
inline typename const_iterator_of< EC >::type struct <a href="#value_type_of" >value_type_of</a>
<a href="#begin" >begin</a>( const EC& c ); {
typedef ... type; // type of stored objTts
template< typename EC > };
inline typename iterator_of< EC >::type
<a href="#end" >end</a>( EC& c ); template< class T >
struct <a href="#iterator_of" >iterator_of</a>
template< typename EC > {
inline typename const_iterator_of< EC >::type typedef ... type; // iterator over stored objects
<a href="#end" >end</a>( const EC& c ); };
template< class T >
struct <a href="#const_iterator_of" >const_iterator_of</a>
{
typedef ... type; // iterator over immutable stored objects
};
template< class T >
struct <a href="#difference_type_of" >difference_type_of</a>
{
typedef ... type;
BOOST_STATIC_ASSERT( boost::is_signed< type >::value );
//
// remark: if std::iterator_traits<> works for the type, this assertion must
hold
//
BOOST_STATIC_ASSERT( boost::is_same< type, std::iterator_traits< typename
<a href="#iterator_of" >iterator_of</a>< T >::type >::difference_type>::value );
};
template< class T >
struct <a href="#size_type_of" >size_type_of</a>
{
typedef ... type;
BOOST_STATIC_ASSERT( boost::is_unsigned< type >::value );
BOOST_STATIC_ASSERT( sizeof( type ) >= sizeof( <a href="#difference_type_of" >
difference_type_of</a>< T >::type ) );
};
template< class T >
struct <a href="#result_iterator_of" >result_iterator_of</a>
{
typedef ... type;
// <a href="#iterator_of" >iterator_of</a>< T >::type if T is non-const, <a href="#const_iterator_of" >
const_iterator_of</a>< T >::type otherwise
};
//
// funtions
//
template< class T >
inline typename iterator_of<T>::type
<a href="#begin" >begin</a>( T& c );
template< class T >
inline typename const_iterator_of< T >::type
<a href="#begin" >begin</a>( const T& c );
template< typename EC > template< class T >
inline bool inline typename iterator_of< T >::type
<a href="#empty" >empty</a>( const EC& c ); <a href="#end" >end</a>( T& c );
template< typename EC > template< class T >
inline typename size_type_of< EC >::type inline typename const_iterator_of< T >::type
<a href="#size" >size</a>( const EC& c ); <a href="#end" >end</a>( const T& c );
} // namespace 'boost' </pre> template< class T >
inline bool
<a href="#empty" >empty</a>( const T& c );
template< class T >
inline typename size_type_of< T >::type
<a href="#size" >size</a>( const T& c );
} // namespace 'boost' </pre>
</p> </p>

View File

@ -1,38 +1,123 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title> Concepts and External Concepts </title><meta http-equiv="Content-Type"content="text/html; charset=iso-8859-1"></head> <body><table ><tr ><td ><img src="cboost.gif" width="100%" border="0"></td><td ><h1 >Concepts and External Concepts</h1></td></tr></table><p >Generic programming in C++ is characterized by the use of function and class templates where <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
the template parameter(s) must satisfy certain requirements.Often these <html>
requirements are so important that we give them a name: we call <head>
such a set of type requirements a <b>concept</b>. We say that a type <i> <title>Concepts and External Concepts </title>
conforms to a concept</i> or that it <i>is a model of a concept</i> if it <meta http-equiv="Content-Type"content="text/html; charset=iso-8859-1">
satisfies all of those requirements. The concept can be specified as a set </head>
of member functions with well-defined semantics <body>
and a set of nested typedefs with well-defined properties.</p><p >Often it much more flexible to provide free-standing functions and typedefs <table >
which provides the exact same semantics (but a different syntax) as <tr >
specified <td ><img src="cboost.gif" width="100%" border="0"></td>
by the concept. This allows generic code to treat different types <i> as if <td ><h1 >Concepts and External Concepts</h1></td>
</i> they fulfilled the concept. In this case we say that the concept has </tr>
been <b> externalized </b> or that the new requirements constitutes an <b>external </table>
concept </b>. We say that a type <i> conforms to an external concept </i> <p >
or that it <i> is a model of an external concept </i>. A concept may exist Generic programming in C++ is characterized by the use of function and class
without a corresponding external concept and conversely.</p><p >Whenever a concept specifies a member function, the corresponding external templates where the template parameter(s) must satisfy certain requirements.Often
concept these requirements are so important that we give them a name: we call such a set
must specify a free-standing function of the same name, same return type and of type requirements a <b>concept</b>. We say that a type <i>conforms to a
the same argument list except there is an extra first argument which must concept</i> or that it <i>is a model of a concept</i> if it satisfies all of
be of the type (or a reference to that type) that is to fulfill the external those requirements. The concept can be specified as a set of member functions
concept. If the corresonding member function has any cv-qulifiers, the with well-defined semantics and a set of nested typedefs with well-defined
first argument must have the same cv-qualifiers. Whenever a concept properties.
specifies a nested typedef, the corresponding external concept </p>
specifies a <b>type-generator</b>, that is, a type with a nested typedef <p >
named <code>type</code>. The type-generator has the name as the nested typedef with Often it much more flexible to provide free-standing functions and typedefs
<code>_of</code> appended. which provides the exact same semantics (but a different syntax) as specified by
The converse relationship of an external concept and its corresponding concept the concept. This allows generic code to treat different types <i>as if</i> they
also holds.</p><p ><b ><i >Example:</i></b></p><p >A type <code>T</code> fulfills the FooConcept if it fulfilled the concept. In this case we say that the concept has been <b>externalized
has the follwing public members:</p><code> void T::foo( int ) const; <br> </b> or that the new requirements constitutes an <b>external concept </b>. We
int T::bar(); <br> say that a type <i>conforms to an external concept </i> or that it <i>is a model
typedef <i>implementation defined </i> foo_type;</code><p >The corresponding external concept is the ExternalFooConcept.</p><p >A type <code>T</code> fullfills the ExternalFooConcept if these of an external concept </i>. A concept may exist without a corresponding
free-standing functions and type-generators exists:</p><code>void foo( const T&, int ); <br> external concept and conversely.
int bar( T& ); <br> </p>
foo_type_of< T >::type;</code> <br> <br><hr size="1" ><h3 >Literature</h3><ul ><li > <a href="http://www.boost.org/more/generic_programming.html#type_generator" target="_self" >Type Generators</a> </li><li > <a href="http://www.boost.org/more/generic_programming.html#concept" target="_self" >Concepts</a> </li><li > <a href="http://www.sgi.com/tech/stl/stl_introduction.html" target="_self" >Concepts and SGI STL</a> </li></ul><hr size="1" ><p >&copy; Thorsten Ottosen 2003-2004 (nesotto_AT_cs.auc.dk). <p >
Permission to copy, use, modify, sell and distribute this software is granted provided this copyright notice appears Whenever a concept specifies a member function, the corresponding external
in all copies. This software is provided "as is" without express or implied warranty, and with no concept must specify a free-standing function of the same name, same return type
claim as to its suitability for any purpose.</p><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br></body></html> and the same argument list except there is an extra first argument which must be
<!-- Copyright Dezide Aps 2003-2004 --> of the type (or a reference to that type) that is to fulfill the external
concept. If the corresonding member function has any cv-qulifiers, the first
argument must have the same cv-qualifiers. Whenever a concept specifies a nested
typedef, the corresponding external concept specifies a <b>metafunction</b>,
that is, a type with a nested typedef named <code>type</code>. The metafunction
has the name as the nested typedef with <code>_of</code> appended. The converse
relationship of an external concept and its corresponding concept also holds.
</p>
<p >
<b ><i >Example:</i></b>
</p>
<p >
A type <code>T</code> fulfills the FooConcept if it has the follwing public
members:
</p>
<code>void T::foo( int ) const; <br>
int T::bar(); <br>
typedef <i>implementation defined </i> foo_type;</code>
<p >
The corresponding external concept is the ExternalFooConcept.
</p>
<p >
A type <code>T</code> fullfills the ExternalFooConcept if these free-standing
functions and metafunctions exists:
</p>
<code>void foo( const T&, int ); <br>
int bar( T& ); <br>
foo_type_of< T >::type;</code> <br>
<br>
<hr size="1" >
<h3 >Literature</h3>
<ul >
<li >
<a href="http://www.boost.org/more/generic_programming.html#type_generator" target="_self" >Type
Generators</a>
</li>
<li >
<a href="http://www.boost.org/more/generic_programming.html#concept" target="_self" >Concepts</a>
</li>
<li >
<a href="http://www.sgi.com/tech/stl/stl_introduction.html" target="_self" >Concepts
and SGI STL</a>
</li>
</ul>
<hr size="1" >
<p >
&copy; Thorsten Ottosen 2003-2004 (nesotto_AT_cs.auc.dk). Permission to copy,
use, modify, sell and distribute this software is granted provided this
copyright notice appears in all copies. This software is provided "as is"
without express or implied warranty, and with no claim as to its suitability for
any purpose.
</p>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</body>
</html>
<!-- Copyright Dezide Aps 2003-2004 -->

View File

@ -17,12 +17,12 @@
</table> </table>
<p> <p>
<h2 >FAQ</h2> <h2 >FAQ</h2> <a name="FAQ" ></a>
<a name="FAQ" ></a>
<ol > <ol >
<li > <li >
Why is there no difference between <code >iterator_of&lt;C&gt;::type</code> and <code >const_iterator_of&lt;C&gt;::type</code> <i>Why is there no difference between <code >iterator_of&lt;C&gt;::type</code>
for <code >std::pair&lt;iterator, iterator&gt;</code>. and <code >const_iterator_of&lt;C&gt;::type</code> for <code >std::pair&lt;iterator,
iterator&gt;</code></i>.
</li> </li>
<p > <p >
In general it is not possible nor desirable to find a corresponding <code >const_iterator</code>. In general it is not possible nor desirable to find a corresponding <code >const_iterator</code>.
@ -30,24 +30,71 @@
object. object.
</p> </p>
<li > <li >
Why is there not supplied more types or more functions? <i>Why is there not supplied more types or more functions?</i>
<p > <p >
The library have been kept small because its current interface will serve The library have been kept small because its current interface will serve most
most purposes. If and when a genuine need arises for more functionality, it can purposes. If and when a genuine need arises for more functionality, it can be
be implemented. implemented.
</p> </p>
</li> </li>
<li > <li >
How should I implement generic algorithms for ranges? <i>How should I implement generic algorithms for ranges?</i>
<p > <p >
One should always start with a generic algorithm that takes two One should always start with a generic algorithm that takes two iterators (or
iterators (or more) as more) as input. Then use Boost.Range to build handier versions on top of the
input. Then use Boost.Range to build handier versions on top of the iterator based algorithm. Please notice that once the range version of the
iterator based algorithm. Please notice that once the range version algorithm is done, it makes sense <i>not</i> to expose the iterator version in
of the algorithm is done, it makes sense <i>not</i> to expose the the public interface.
iterator version in the public interface.
</p> </p>
</li> </li>
<li>
<i>Why is there no Incrementable Range concept?</i>
<p>
Even though we speak of incrementable iterators, it would not make
much sense for ranges; for example, we cannot determine the size and
emptiness of a range since we cannot even compare
its iterators.
</p>
</li>
<li>
<i>Should I use qualified syntax, for example
<blockquote><pre>boost::begin( r ); </pre></blockquote>
instead of
<blockquote>
<pre>using namespace boost;
begin( r )</pre></blockquote>
when calling functions in this library? If so, can I still rely on argument
dependent lookup (ADL) to kick in?</i>
<p>
The answer to the first question is that "it's up to you". The
answer to the second question is Yes. Normally qualified syntax
disables ADL, but the functions are implemented in a special
manner that preserves ADL properties. The trick was explained by
Daniel Frey on comp.lang.std.c++ in the thread "Whence Swap" and
it is best explained by some code: <blockquote>
<pre>
namespace boost
{
namespace range_detail
{
template< class T >
typename iterator_of&lt;T>:type begin( T& r )
{ /* normal implementation */ }
}
template< class T >
typename iterator_of&lt;T>::type begin( T& r )
{
//
// Create ADL hook
//
using range_detail::begin;
return begin( r );
}
} </pre>
</blockquote>
</p>
</ol> </ol>

View File

@ -22,87 +22,108 @@
<tr > <tr >
<th >Header</th> <th >Header</th>
<th >Includes</th> <th >Includes</th>
<th>Related concept </th>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range.hpp&gt;</code></td> <td ><code >&lt;boost/range.hpp&gt;</code></td>
<td >everything</td> <td >everything</td>
<td>- </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/types.hpp&gt;</code></td> <td ><code >&lt;boost/range/metafunctions.hpp&gt;</code></td>
<td >every meta-function</td> <td >every metafunction</td>
<td>- </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/functions.hpp&gt;</code></td> <td ><code >&lt;boost/range/functions.hpp&gt;</code></td>
<td >every function</td> <td >every function</td>
<td>- </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/value_type.hpp&gt;</code></td> <td ><code >&lt;boost/range/value_type.hpp&gt;</code></td>
<td ><a href="boost_range.html#value_type_of" >value_type_of</a></td> <td ><a href="boost_range.html#value_type_of" >value_type_of</a></td>
<td><a href="range.htm#single_pass_range">Single Pass Range</a></td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/iterator.hpp&gt;</code></td> <td ><code >&lt;boost/range/iterator.hpp&gt;</code></td>
<td ><a href="boost_range.html#iterator_of" >iterator_of</a></td> <td ><a href="boost_range.html#iterator_of" >iterator_of</a></td>
<td><a href="range.htm#single_pass_range">Single Pass Range</a> </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/const_iterator.hpp&gt;</code></td> <td ><code >&lt;boost/range/const_iterator.hpp&gt;</code></td>
<td ><a href="boost_range.html#const_iterator_of" >const_iterator_of</a></td> <td ><a href="boost_range.html#const_iterator_of" >const_iterator_of</a></td>
<td><a href="range.htm#single_pass_range">Single Pass Range</a> </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/difference_type.hpp&gt;</code></td> <td ><code >&lt;boost/range/difference_type.hpp&gt;</code></td>
<td ><a href="boost_range.html#difference_type_of" >difference_type_of</a></td> <td ><a href="boost_range.html#difference_type_of" >difference_type_of</a></td>
<td><a href="range.htm#forward_range">Forward Range</a> </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/size_type.hpp&gt;</code></td> <td ><code >&lt;boost/range/size_type.hpp&gt;</code></td>
<td ><a href="boost_range.html#size_type_of" >size_type_of</a></td> <td ><a href="boost_range.html#size_type_of" >size_type_of</a></td>
<td><a href="range.htm#forward_range">Forward Range</a> </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/result_iterator.hpp&gt;</code></td> <td ><code >&lt;boost/range/result_iterator.hpp&gt;</code></td>
<td ><a href="boost_range.html#result_iterator_of" >result_iterator_of</a></td> <td ><a href="boost_range.html#result_iterator_of" >result_iterator_of</a></td>
<td>- </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/reverse_iterator.hpp&gt;</code></td> <td ><code >&lt;boost/range/reverse_iterator.hpp&gt;</code></td>
<td ><a href="boost_range.html#reverse_iterator_of" >reverse_iterator_of</a></td> <td ><a href="boost_range.html#reverse_iterator_of" >reverse_iterator_of</a></td>
<td><a href="range.htm#bidirectional_range">Bidirectional Range</a> </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/const_reverse_iterator.hpp&gt;</code></td> <td ><code >&lt;boost/range/const_reverse_iterator.hpp&gt;</code></td>
<td ><a href="boost_range.html#const_reverse_iterator_of" >const_reverse_iterator_of</a></td> <td ><a href="boost_range.html#const_reverse_iterator_of" >const_reverse_iterator_of</a></td>
<td><a href="range.htm#bidirectional_range">Bidirectional Range</a> </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/reverse_result_iterator.hpp&gt;</code></td> <td ><code >&lt;boost/range/reverse_result_iterator.hpp&gt;</code></td>
<td ><a href="boost_range.html#reverse_result_iterator_of">reverse_result_iterator_of</a></td> <td ><a href="boost_range.html#reverse_result_iterator_of">reverse_result_iterator_of</a></td>
<td>- </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/begin.hpp&gt;</code></td> <td ><code >&lt;boost/range/begin.hpp&gt;</code></td>
<td ><a href="boost_range.html#begin" >begin</a></td> <td ><a href="boost_range.html#begin" >begin</a></td>
<td><a href="range.htm#single_pass_range">Single Pass Range</a> </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/end.hpp&gt;</code></td> <td ><code >&lt;boost/range/end.hpp&gt;</code></td>
<td ><a href="boost_range.html#end" >end</a></td> <td ><a href="boost_range.html#end" >end</a></td>
<td><a href="range.htm#single_pass_range">Single Pass Range</a> </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/empty.hpp&gt;</code></td> <td ><code >&lt;boost/range/empty.hpp&gt;</code></td>
<td ><a href="boost_range.html#empty" >empty</a></td> <td ><a href="boost_range.html#empty" >empty</a></td>
<td><a href="range.htm#single_pass_range">Single Pass Range</a> </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/size.hpp&gt;</code></td> <td ><code >&lt;boost/range/size.hpp&gt;</code></td>
<td ><a href="boost_range.html#size" >size</a></td> <td ><a href="boost_range.html#size" >size</a></td>
<td><a href="range.htm#forward_range">Forward Range</a> </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/rbegin.hpp&gt;</code></td> <td ><code >&lt;boost/range/rbegin.hpp&gt;</code></td>
<td ><a href="boost_range.html#rbegin" >rbegin</a></td> <td ><a href="boost_range.html#rbegin" >rbegin</a></td>
<td><a href="range.htm#bidirectional_range">Bidirectional Range</a> </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/rend.hpp&gt;</code></td> <td ><code >&lt;boost/range/rend.hpp&gt;</code></td>
<td ><a href="boost_range.html#rend" >rend</a></td> <td ><a href="boost_range.html#rend" >rend</a></td>
<td><a href="range.htm#bidirectional_range">Bidirectional Range</a> </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/iterator_range.hpp&gt;</code></td> <td ><code >&lt;boost/range/iterator_range.hpp&gt;</code></td>
<td ><a href="utility_class.html#iter_range" <td ><a href="utility_class.html#iter_range"
>iterator_range</a></td> >iterator_range</a></td>
<td>- </td>
</tr> </tr>
<tr > <tr >
<td ><code >&lt;boost/range/sub_range.hpp&gt;</code></td> <td ><code >&lt;boost/range/sub_range.hpp&gt;</code></td>
<td ><a href="utility_class.html#sub_range" >sub_range</a></td> <td ><a href="utility_class.html#sub_range" >sub_range</a></td>
<td>- </td>
</tr> </tr>
</table> </table>

View File

@ -25,10 +25,25 @@
</p> </p>
<p> <p>
Meanwhile work on container algorithms in various context showed the Meanwhile work on algorithms for containers in various contexts showed the
need for handling pairs of iterators, and string libraries needed special need for handling pairs of iterators, and string libraries needed special
treatment of character arrays. treatment of character arrays. In the end it made sense to formalize the
</p> minimal requirements of these similar concepts. And the results are the
Range concepts found in this library. </p>
<p>
The term Range was adopted because of paragraph <code>24.1/7</code> from the
C++ standard: <blockquote>
Most of the library's algorithmic templates that operate on data
structures have interfaces that use ranges. A <i>range</i> is a pair of
iterators that designate the beginning and end of the computation. A
range [i, i) is an empty range; in general, a range [i, j) refers to
the elements in the data structure starting with the one pointed to
by i and up to but not including the one pointed to by j. Range [i,
j) is valid if and only if j is reachable from i. The result of the
application of functions in the library to invalid ranges is
undefined.
</blockquote>
<p> <p>
Special thanks goes to Special thanks goes to

View File

@ -18,22 +18,32 @@
<h2>Introduction</h2> <h2>Introduction</h2>
<p> <p>
When writing generic code that works with Standard Library containers, one 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
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
terminated strings can be treated as containers of characters, if suitably
adapted. This library provides the means to adapt Standard Library containers,
null terminated strings, <code>std::pairs</code> of iterators, and raw
arrays, such that the same generic code can work with them all.
</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
implemented a subset of the container requirements (see &sect;23.1of the C++ implemented a subset of the container requirements (see &sect;23.1of the C++
standard). Formally, that subset is defined by the <a href="Range.htm" standard). Formally, that subset is defined by the <a href="Range.htm"
target="_self" >Range</a> concept. The subset deals mostly with iterator target="_self" >Range</a> concept. The subset deals mostly with iterator
returning functions and nested <code >typedef</code>s. The main goal is to treat returning functions and nested <code >typedef</code>s. The main goal is to treat
built-in arrays, standard containers, pairs of iterators and some iterators built-in arrays, standard containers, pairs of iterators and some iterators
uniformly. uniformly.
</p> </p>
-->
<p > <p >
The main advantages are The main advantages are
<ul > <ul >
<li > <li >
safe use of built-in arrays simpler implementation of generic range algorithms
</li>
<li >
simpler implementation of generic container algorithms
</li> </li>
<li > <li >
more flexible client code more flexible client code
@ -41,58 +51,69 @@
<li > <li >
correct handling of null-terminated strings correct handling of null-terminated strings
</li> </li>
<li >
safe use of built-in arrays (for legacy code; why else would you use
arrays?) </li>
</ul> </ul>
</p> </p>
<p > <p >
Below are given a small example (the complete example can be found <a href="../test/algorithm_example.cpp" target="_self" >here</a> Below are given a small example (the complete example can be found <a href="../test/algorithm_example.cpp" target="_self" >here</a>
): ):
<pre > <blockquote>
<pre >
//
// example: extracting bounds in a generic algorithm
//
template< typename ForwardRange, typename T >
inline typename boost::iterator_of< ForwardRange >::type
find( ForwardRange& c, const T& value )
{
return std::find( boost::begin( c ), boost::end( c ), value );
}
template< typename ForwardRange, typename T >
inline typename boost::const_iterator_of< ForwardRange >::type
find( const ForwardRange& c, const T& value )
{
return std::find( boost::begin( c ), boost::end( c ), value );
}
//
// replace first value and return its index
//
template< class ForwardRange, class T >
inline typename boost::size_type_of< ForwardRange >::type
my_generic_replace( ForwardRange& c, const T& value, const T& replacement )
{
typename boost::iterator_of< ForwardRange >::type found = find( c, value );
// if( found != boost::end( c ) )
// Example: extracting bounds in generic algorithms
//
template&lt; typename XRange, typename T &gt;
inline typename boost::iterator_of&lt;XRange&gt;::type
find( XRange& c, const T& value )
{
return std::find( boost::begin( c ), boost::end( c ), value );
}
template&lt; typename XRange, typename T &gt;
inline typename boost::const_iterator_of&lt;XRange&gt;::type
find( const XRange& c, const T& value )
{
return std::find( boost::begin( c ), boost::end( c ), value );
}
//
// replace first value and return its index
//
template&lt; typename EC, typename T &gt;
inline typename boost::size_type_of&lt; EC &gt;::type
my_generic_replace( EC& c, const T& value, const T& replacement )
{
typename boost::const_iterator_of&lt;EC&gt;::type found = find( c, value );
*found = replacement; *found = replacement;
return std::distance( boost::begin( c ), found ); return std::distance( boost::begin( c ), found );
} }
//
// usage
//
std::vector&lt;int&gt; my_vector;
typedef vector&lt;int&gt;::iterator iterator;
std::pair&lt;iterator,iterator&gt; my_view( my_vector.begin(), my_vector.begin(
) + N );
char str[] = "a string";
// ...
std::cout &lt;&lt; my_generic_replace( my_vector, 4, 2 )
&lt;&lt; my_generic_replace( my_view, 4, 2 )
&lt;&lt; my_generic_replace( str, 'a', 'b' );
</pre>
By using the free-standing functions and type-generators, the code automatically //
// usage
//
const int N = 5;
std::vector<int> my_vector;
int values[] = { 1,2,3,4,5,6,7,8,9 };
my_vector.assign( values, values + 9 );
typedef std::vector<int>::iterator iterator;
std::pair<iterator,iterator> my_view( boost::begin( my_vector ),
boost::begin( my_vector ) + N );
char str_val[] = "a string";
char* str = str_val;
std::cout << my_generic_replace( my_vector, 4, 2 )
<< my_generic_replace( my_view, 4, 2 )
<< my_generic_replace( str, 'a', 'b' );
</pre>
</blockquote>
By using the free-standing functions and metafunctions, the code automatically
works for all the types supported by this library. Notice that we have to works for all the types supported by this library. 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

View File

@ -20,7 +20,7 @@
<p > <p >
Full support for built-in arrays require that the compiler supports class Full support for built-in arrays require that the compiler supports class
template partial specialization. For non-conforming compilers there might template partial specialization. For non-conforming compilers there might
be a change that it works anyway thanks to workarounds in the type traits be a chance that it works anyway thanks to workarounds in the type traits
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

View File

@ -16,318 +16,454 @@
<link rel="stylesheet" href="style.css" type="text/css"> <link rel="stylesheet" href="style.css" type="text/css">
</HEAD> </HEAD>
<table border="0" > <table border="0" >
<tr> <tr>
<td ><img src="cboost.gif" border="0" ></td> <td ><img src="cboost.gif" border="0" ></td>
<td ><h1 align="center">Boost.Range </h1></td> <td ><h1 align="center">Boost.Range </h1></td>
</tr> </tr>
</table> </table>
<h2>Range concepts </h2> <h2>Range concepts </h2>
<ul> <ul>
<li> <li>
<a href="#range">Range</a> <a href="#overview">Overview</a>
<li> <li>
<a href="#reversible_range">ReversibleRange</a> <a href="#single_pass_range">Single Pass Range</a>
</ul> <li>
<hr> <a href="#forward_range">Forward Range</a>
<li>
<a href="#bidirectional_range">Bidirectional Range</a>
<li>
<a href="#random_access_range">Random Access Range</a>
</ul>
<a name="range"><H1>Range</H1> <a name="overview"></a>
<hr>
<h3>Overview</h3>
<h3>Description</h3> <p>
A Range is a <i>concept</i> similar to the STL <a
href="http://www.sgi.com/Technology/STL/Container.html">Container</a> concept. A
Range provides iterators for accessing a closed-open range
<code>[first,one_past_last)</code> of elements and provides
information about the number of elements in the Range. However, a Range has
fewer requirements than a Container.
</p>
<p>
The motivation for the Range concept is
that there are many useful Container-like types that do not meet the full
requirements of Container, and many algorithms that can be written with this
reduced set of requirements. In particular, a Range does not necessarily
A Range is a <i>concept</i> similar to the STL <a <ul>
href="http://www.sgi.com/Technology/STL/Container.html">Container</a> concept. A <li>
Range provides iterators for accessing a range of elements and provides own the elements that can be accessed through it,
information about the number of elements in the Range. However, a Range has <li>
fewer requirements than a Container. The motivation for the Range concept is have copy semantics,
that there are many useful Container-like types that do not meet the full <!--
requirements of Container, and many algorithms that can be written with this <li>
reduced set of requirements. In particular, a Range does not necessarily require that the associated reference type is a real C++ reference.
-->
</ul>
<ul>
<li> Because of the second requirement, a Range object must be passed by reference in
own the elements that can be accessed through it, generic code.
<li>
have copy semantics,
<li>
require that the associated reference type is a real C++ reference.
</ul>
Because of the second requirement, a Range object must be passed by reference in </p>
generic code. <p>
The operations that can be performed on a Range is dependent on the
<a href="../../iterator/doc/new-iter-concepts.html#iterator-traversal-concepts-lib-iterator-traversal">traversal
category</a> of the underlying iterator type. Therefore
the range concepts are named to reflect which traversal category its
iterators support. See also <a href="style.html">terminology and style guidelines.</a>
for more information about naming of ranges.</p>
<p>
<p> </p>
<h3>Notation</h3> <hr>
<Table> <a name="single_pass_range">
<TR> <H2>Single Pass Range</H2>
<TD VAlign="top"><tt>X</tt></TD>
<TD VAlign="top">A type that is a model of Range.</TD>
</TR>
<TR>
<TD VAlign="top"><tt>a</tt>, <tt>b</tt></TD>
<TD VAlign="top">Object of type <tt>X</tt>.</TD>
</TR>
<TR>
<TD VAlign="top"><tt>T</tt></TD>
<TD VAlign="top">The value type of <tt>X</tt>.</TD>
</tr>
</table>
<h3>Associated types</h3> <h3>Notation</h3>
<Table>
<table border=1 cellpadding=5>
<TR>
<TD VAlign="top">Value type</TD>
<TD VAlign="top"><tt>value_type_of&lt;X>::type</tt></TD>
<TD VAlign="top">The type of the object stored in a Range.
</TR>
<TR>
<TD VAlign="top">Iterator type</TD>
<TD VAlign="top"><tt>iterator_of&lt;X>::type</tt></TD>
<TD VAlign="top">The type of iterator used to iterate through a Range's elements.
The iterator's value type is expected to be the Range's value type. A
conversion from the iterator type to the const iterator type must exist. The
iterator type must at least be an <A
href="http://www.sgi.com/Technology/STL/InputIterator.html">InputIterator</A>.</TD>
</TR>
<TR>
<TD VAlign="top">Const iterator type</TD>
<TD VAlign="top"><tt>const_iterator_of&lt;X>::type</tt></TD>
<TD VAlign="top">A type of iterator that may be used to examine, but not to
modify, a Range's elements.</TD>
</TR>
<TR>
<TD VAlign="top">Reference type</TD>
<TD VAlign="top"><tt>reference_of&lt;X>::type</tt></TD>
<TD VAlign="top">A type that behaves like a reference to the Range's value type. <a href="#1">[1]</a></TD>
</TR>
<TR>
<TD VAlign="top">Distance type</TD>
<TD VAlign="top"><tt>difference_type_of&lt;>::type</tt></TD>
<TD VAlign="top">A signed integral type used to represent the distance between
two of the Range's iterators. This type must be the same as the iterator's
distance type.</TD>
</TR>
<TR>
<TD VAlign="top">Size type</TD>
<TD VAlign="top"><tt>size_type_of&lt;X>::type</tt></TD>
<TD VAlign="top">An unsigned integral type that can represent any nonnegative
value of the Range's distance type.</TD>
</tr>
</table>
<h3>Valid expressions</h3>
The following expressions must be valid.
<p>
<Table border=1 cellpadding=5>
<TR>
<TH>Name</TH>
<TH>Expression</TH>
<TH>Return type</TH>
</TR>
<TR>
<TD VAlign="top">Beginning of range</TD>
<TD VAlign="top"><tt>begin(a)</tt></TD>
<TD VAlign="top"><tt>iterator</tt> if <tt>a</tt> is mutable, <tt>const_iterator</tt>
otherwise</TD>
</TR>
<TR>
<TD VAlign="top">End of range</TD>
<TD VAlign="top"><tt>end(a)</tt></TD>
<TD VAlign="top"><tt>iterator</tt> if <tt>a</tt> is mutable, <tt>const_iterator</tt>
otherwise</TD>
</TR>
<TR>
<TD VAlign="top">Size of range</TD>
<TD VAlign="top"><tt>size(a)</tt></TD>
<TD VAlign="top"><tt>size_type</tt></TD>
</TR>
<TD VAlign="top">Is range empty?</TD>
<TD VAlign="top"><tt>empty(a)</tt></TD>
<TD VAlign="top">Convertible to <tt>bool</tt></TD>
</TR>
<TR>
</tr>
</table>
<h3>Expression semantics</h3>
<Table border>
<TR>
<TH>Expression</TH>
<TH>Semantics</TH>
<TH>Postcondition</TH>
</TR>
<TD VAlign="top">
<TR> <TR>
<TD VAlign="top"><tt>begin(a)</tt></TD> <TD VAlign="top"><code>X</code></TD>
<TD VAlign="top">Returns an iterator pointing to the first element in the Range.</TD> <TD VAlign="top">A type that is a model of Single Pass Range.</TD>
<TD VAlign="top"><tt>begin(a)</tt> is either dereferenceable or
past-the-end. It is past-the-end if and only if <tt>size(a) == 0</tt>.</TD>
</TR> </TR>
<TR> <TR>
<TD VAlign="top"><tt>end(a)</tt></TD> <TD VAlign="top"><code>a</code></TD>
<TD VAlign="top">Object of type <code>X</code>.</TD>
</TR>
</table>
<h3>Description</h3>
<p>
A range X where <code>iterator_of&lt;X>::type</code> is a model of <a
href="../../iterator/doc/new-iter-concepts.html#single-pass-iterators-lib-single-pass-iterators">
Single Pass Iterator</a>
</p>
<h3>Associated types</h3>
<table border="1" cellpadding="5">
<TR>
<TD VAlign="top">Value type</TD>
<TD VAlign="top"><code>value_type_of&lt;X>::type</code></TD>
<TD VAlign="top">The type of the object stored in a Range.
</TR>
<TR>
<TD VAlign="top">Iterator type</TD>
<TD VAlign="top"><code>iterator_of&lt;X>::type</code></TD>
<TD VAlign="top">The type of iterator used to iterate through a Range's elements.
The iterator's value type is expected to be the Range's value type. A
conversion from the iterator type to the const iterator type must exist.
</TR>
<TR>
<TD VAlign="top">Const iterator type</TD>
<TD VAlign="top"><code>const_iterator_of&lt;X>::type</code></TD>
<TD VAlign="top">A type of iterator that may be used to examine, but not to
modify, a Range's elements.</TD>
</TR>
<!--
<TR>
<TD VAlign="top">Reference type</TD>
<TD VAlign="top"><code>reference_of&lt;X>::type</code></TD>
<TD VAlign="top">A type that behaves like a reference to the Range's value type. <a href="#1">[1]</a></TD>
</TR>
-->
</table>
<h3>Valid expressions</h3>
The following expressions must be valid.
<p>
<Table border="1" cellpadding="5">
<TR>
<TH>Name</TH>
<TH>Expression</TH>
<TH>Return type</TH>
</TR>
<TR>
<TD VAlign="top">Beginning of range</TD>
<TD VAlign="top"><code>begin(a)</code></TD>
<TD VAlign="top"><code>iterator_of&lt;X>::type</code> if
<code>a</code> is mutable, <code>const_iterator_of&lt;X>::type</code>
otherwise</TD> </TR>
<TR>
<TD VAlign="top">End of range</TD>
<TD VAlign="top"><code>end(a)</code></TD>
<TD VAlign="top"><code>iterator_of&lt;X>::type</code> if
<code>a</code> is mutable, <code>const_iterator_of&lt;X>::type</code>
otherwise</TD>
</TR>
<tr>
<TD VAlign="top">Is range empty?</TD>
<TD VAlign="top"><code>empty(a)</code></TD>
<TD VAlign="top">Convertible to <code>bool</code></TD>
</TR>
</table>
<h3>Expression semantics</h3>
<Table border>
<TR>
<TH>Expression</TH>
<TH>Semantics</TH>
<TH>Postcondition</TH>
</TR>
<TR>
<TD VAlign="top"><code>begin(a)</code></TD>
<TD VAlign="top">Returns an iterator pointing to the first element in the Range.</TD>
<TD VAlign="top"><code>begin(a)</code> is either dereferenceable or past-the-end.
It is past-the-end if and only if <code>size(a) == 0</code>.</TD>
</TR>
<TR>
<TD VAlign="top"><code>end(a)</code></TD>
<TD VAlign="top">Returns an iterator pointing one past the last element in the <TD VAlign="top">Returns an iterator pointing one past the last element in the
Range.</TD> Range.</TD>
<TD VAlign="top"><tt>end(a)</tt> is past-the-end.</TD> <TD VAlign="top"><code>end(a)</code> is past-the-end.</TD>
</TR> </TR>
<TR> <TR>
<TD VAlign="top"><tt>size(a)</tt></TD> <TD VAlign="top"><code>empty(a)</code></TD>
<TD VAlign="top">Returns the size of the Collection, that is, its number of <TD VAlign="top">Equivalent to <code>begin(a) == end(a)</code>. (But possibly
elements.</TD> faster.)</TD>
<TD VAlign="top"><tt>size(a) &gt;= 0</TD> <TD VAlign="top">&nbsp;-&nbsp;</TD>
</TR>
</table>
<h3>Complexity guarantees</h3>
All three functions are at most amortized linear time. For most practical
purposes, one can expect <code>begin(a)</code>, <code>end(a)</code> and <code>empty(a)</code>
to be amortized constant time.
<h3>Invariants</h3>
<Table border>
<TR>
<TD VAlign="top">Valid range</TD>
<TD VAlign="top">For any Range <code>a</code>, <code>[begin(a),end(a))</code> is
a valid range, that is, <code>end(a)</code> is reachable from <code>begin(a)</code>
in a finite number of increments.</TD>
</TR> </TR>
<TR> <TR>
<TD VAlign="top"><tt>empty(a)</tt></TD> <TD VAlign="top">Completeness</TD>
<TD VAlign="top">Equivalent to <tt>size(a) == 0</tt>. (But <TD VAlign="top">An algorithm that iterates through the range <code>[begin(a),end(a))</code>
possibly faster.)</TD> <TD VAlign="top">&nbsp;-&nbsp;</TD> will pass through every element of <code>a</code>.</TD>
</tr>
</table>
<h3>See also</h3>
<p>
<A href="http://www.sgi.com/Technology/STL/Container.html">Container</A>
</p>
<hr>
<a name=forward_range><h2>Forward Range</h2>
<h3>Notation</h3>
<Table>
<TR>
<TD VAlign="top"><code>X</code></TD>
<TD VAlign="top">A type that is a model of Forward Range.</TD>
</TR> </TR>
</table> <TR>
<TD VAlign="top"><code>a</code></TD>
<TD VAlign="top">Object of type <code>X</code>.</TD>
</TR>
</table>
<h3>Complexity guarantees</h3> <h3>Description</h3>
<p>
A range <code>X</code> where <code>iterator_of&lt;X>::type</code> is a model
of <a
href="../../iterator/doc/new-iter-concepts.html#forward-traversal-iterators-lib-forward-traversal-iterators">Forward Traversal Iterator</a>
</p>
All four functions are at most amortized linear time. For most practical <h3>Refinement of</h3> <a href="#single_pass_range">Single Pass
purposes, one can expect <tt>begin(a)</tt>, <tt>end(a)</tt> and Range</a>
<tt>empty(a)</tt> to be amortized constant time.
<h3>Associated types</h3>
<h3>Invariants</h3> <table cellpadding="5" border="1">
<Table border> <TR>
<TR> <TD VAlign="top">Distance type</TD>
<TD VAlign="top">Valid range</TD> <TD VAlign="top"><code>difference_type_of&lt;X>::type</code></TD>
<TD VAlign="top">For any Range <tt>a</tt>, <tt>[begin(a),end(a))</tt> is a <TD VAlign="top">A signed integral type used to represent the distance between
valid range, that is, <code>end(a)</code> is reachable from <code>begin(a)</code> two of the Range's iterators. This type must be the same as the iterator's
in a finite number of increments.</TD> distance type.</TD>
</TR> </TR>
<TR> <TR>
<TD VAlign="top">Range size</TD> <TD VAlign="top">Size type</TD>
<TD VAlign="top"><tt>size(a)</tt> is equal to the distance from <TD VAlign="top"><code>size_type_of&lt;X>::type</code></TD>
<tt>begin(a)</tt> to <tt>end(a)</tt>.</TD> <TD VAlign="top">An unsigned integral type that can represent any nonnegative
</TR> value of the Range's distance type.</TD>
<TR> </tr>
<TD VAlign="top">Completeness</TD> </table>
<TD VAlign="top">An algorithm that iterates through the range
<tt>[begin(a),end(a))</tt> will pass through every element of <tt>a</tt>.</TD> <h3>Valid expressions</h3>
</tr>
</table> <table border="1" cellpadding="5">
<tr>
<th>Name</th>
<th>Expression</th>
<th>Return type</th>
</tr>
<TR>
<TD VAlign="top">Size of range</TD>
<TD VAlign="top"><code>size(a)</code></TD>
<TD VAlign="top"><code>size_type</code></TD>
</TR>
</table>
<h3>Expression semantics </h3>
<table border="1" cellpadding="5">
<TR>
<TH>Expression</TH>
<TH>Semantics</TH>
<TH>Postcondition</TH>
</TR>
<tr>
<TD VAlign="top"><code>size(a)</code></TD>
<TD VAlign="top">Returns the size of the Range, that is, its number
of elements. Note <code>size(a) == 0u</code> is equivalent to
<code>empty(a).</code></TD>
<TD VAlign="top"><code>size(a) &gt;= 0</TD>
</TR>
</table>
<h3>Complexity guarantees</h3>
<p><code>size(a)</code> is at most amortized linear time.</p>
<h3>Invariants</h3>
<p>
<Table border="1" cellpadding="5">
<TR>
<TD VAlign="top">Range size</TD>
<TD VAlign="top"><code>size(a)</code> is equal to the distance from <code>begin(a)</code>
to <code>end(a)</code>.</TD> </table>
</p>
<hr>
<a name=bidirectional_range><h2>Bidirectional Range</h2>
<h3>Notation</h3>
<Table>
<TR>
<TD VAlign="top"><code>X</code></TD>
<TD VAlign="top">A type that is a model of Bidirectional Range.</TD>
</TR>
<TR>
<TD VAlign="top"><code>a</code></TD>
<TD VAlign="top">Object of type <code>X</code>.</TD>
</TR>
</table>
<h3>Description</h3> This concept provides access to iterators that traverse in
both directions (forward and reverse). The
<code>iterator_of&lt;X>::type</code> iterator must meet all of the requirements
of <a
href="../../iterator/doc/new-iter-concepts.html#bidirectional-traversal-iterator
s-lib-bidirectional-traversal-iterators">Bidirectional Traversal Iterator.</a>
<h3>Refinement of</h3> <a href="#forward_range">Forward Range</a>
<h3>Associated types</h3>
<Table border>
<TR>
<TD VAlign="top">Reverse Iterator type</TD>
<TD VAlign="top"><code>reverse_iterator_of&lt;X>::type</code></TD>
<TD VAlign="top">The type of iterator used to iterate through a Range's elements
in reverse order. The iterator's value type is expected to be the Range's value
type. A conversion from the reverse iterator type to the const reverse iterator
type must exist. </TD>
</TR>
<TR>
<TD VAlign="top">Const reverse iterator type</TD>
<TD
VAlign="top"><code>const_reverse_iterator_of&ltX>::type</code></TD>
<TD VAlign="top">A type of reverse iterator that may be used to examine, but not
to modify, a Range's elements.</TD>
</TR>
</table>
<h3>Models</h3> <h3>Valid expressions</h3>
<UL>
<li>
<code>All models of <A href="http://www.sgi.com/Technology/STL/Container.html">Container</A></code>
<LI>
<tt>boost::array&lt;T,sz></tt>
<LI>
<tt>std::vector&lt;bool&gt;</tt>
</UL>
<h3>See also</h3> <A href="http://www.sgi.com/Technology/STL/Container.html">Container</A> <Table border>
<TR>
<TH>Name</TH>
<TH>Expression</TH>
<TH>Return type</TH>
<TH>Semantics</TH>
</TR>
<TR>
<TD VAlign="top">Beginning of range</TD>
<TD VAlign="top"><code>rbegin(a)</code></TD>
<TD VAlign="top"><code>reverse_iterator_of&lt;X>::type</code> if
<code>a</code> is mutable, <code>const_reverse_iterator_of&lt;X>::type</code>
otherwise.</TD>
<TD VAlign="top">Equivalent to
<code>reverse_iterator_of&lt;X>::type(end(a))</code>.</TD> </TR>
<TR>
<TD VAlign="top">End of range</TD>
<TD VAlign="top"><code>rend(a)</code></TD>
<TD VAlign="top"><code>reverse_iterator_of&lt;X>::type</code> if
<code>a</code> is mutable, <code>const_reverse_iterator_of&lt;X>::type</code>
otherwise.</TD>
<TD VAlign="top">Equivalent to
<code>reverse_iterator_of&lt;X>::type(begin(a))</code>.</TD> </tr>
<br> </table>
<br>
<hr>
<br>
<a name=reversible_range><h1>ReversibleRange</h1> <h3>Complexity guarantees</h3>
<code>rbegin(a)</code> has the same complexity as <code>end(a)</code> and <code>rend(a)</code>
has the same complexity as <code>begin(a)</code> from <a
href="#forward_range">Forward Range</a>.
<h3>Invariants</h3>
<p>
<Table border="1" cellpadding="5">
<TR>
<TD VAlign="top">Valid reverse range</TD>
<TD VAlign="top">For any Bidirectional Range <code>a</code>, <code>[rbegin(a),rend(a))</code>
is a valid range, that is, <code>rend(a)</code> is reachable from <code>rbegin(a)</code>
in a finite number of increments.</TD>
</TR>
<TR>
<TD VAlign="top">Completeness</TD>
<TD VAlign="top">An algorithm that iterates through the range <code>[rbegin(a),rend(a))</code>
will pass through every element of <code>a</code>.</TD>
</tr>
</table>
</p>
<hr>
<a name=random_access_range><h2>Random Access Range</h2> <h3>Description</h3>
<p>
A range <code>X</code> where <code>iterator_of&lt;X>::type</code> is a model
of <a
href="../../iterator/doc/new-iter-concept.html#random-access-traversal-iterators
-lib-random-access-traversal-iterators">Random Access Traversal Iterator</a>
</p>
<h3>Refinement of</h3>
<p>
<a href="#bidirectional_range">Bidirectional Range</a>
</p>
<hr>
<h3>Description</h3> This concept provides access to iterators that traverse in <!--
both directions (forward and reverse). The iterator type must meet all of the <h3>Notes</h3>
requirements of <a
href="http://www.sgi.com/Technology/STL/BidirectionalIterator.html">BidirectionalIterator</a>
except that the reference type does not have to be a real C++ reference.
<h3>Refinement of</h3> Range
<P>
<A name="1">[1]</A>
<h3>Associated types</h3> The reference type does not have to be a real C++ reference. The requirements of
the reference type is that it <i>behaves</i> like a real reference. Hence the
reference type must be convertible to the value_type and assignment through
<Table border> <br>
<TR> <br>
<TD VAlign="top">Reverse Iterator type</TD> <HR>
<TD VAlign="top"><tt>X::reverse_iterator</tt></TD> <br>
<TD VAlign="top">The type of iterator used to iterate through a Range's elements -->
in reverse order. The iterator's value type is expected to be the Range's value
type. A conversion from the reverse iterator type to the const reverse iterator
type must exist. The iterator type must at least be a <a
href="http://www.sgi.com/Technology/STL/BidirectionalIterator.html">BidirectionalIterator</a>.</TD>
</TR>
<TR>
<TD VAlign="top">Const reverse iterator type</TD>
<TD VAlign="top"><tt>X::const_reverse_iterator</tt></TD>
<TD VAlign="top">A type of reverse iterator that may be used to examine, but not
to modify, a Range's elements.</TD>
</TR>
</table>
<TABLE>
<TR valign="top">
<TD nowrap>Copyright &copy 2000</TD>
<TD><A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>
</TR>
<tr >
<TD nowrap>Copyright &copy 2004</TD>
<TD>Thorsten Ottosen.
</TABLE>
<h3>Valid expressions</h3> <br>
<br>
<Table border> <br>
<TR> <br>
<TH>Name</TH> <br>
<TH>Expression</TH> <br>
<TH>Return type</TH> <br>
<TH>Semantics</TH> <br>
</TR> <br>
<TR> <br>
<TD VAlign="top">Beginning of range</TD>
<TD VAlign="top"><tt>rbegin(a)</tt></TD> </BODY>
<TD VAlign="top"><tt>reverse_iterator</tt> if <tt>a</tt> is mutable, <tt>const_reverse_iterator</tt>
otherwise.</TD>
<TD VAlign="top">Equivalent to <tt>X::reverse_iterator(end(a))</tt>.</TD> </TR>
<TR>
<TD VAlign="top">End of range</TD>
<TD VAlign="top"><tt>rend(a)</tt></TD>
<TD VAlign="top"><tt>reverse_iterator</tt> if <tt>a</tt> is mutable, <tt>const_reverse_iterator</tt>
otherwise.</TD>
<TD VAlign="top">Equivalent to
<tt>X::reverse_iterator(begin(a))</tt>.</TD> </tr>
</table>
<h3>Complexity guarantees</h3>
<tt>rbegin(a)</tt> has the same complexity as <tt>end(a)</tt> and
<tt>rend(a)</tt> has the same complexity as <tt>begin(a)</tt> from Range.
<h3>Models</h3>
<ul>
<li>
std::vector&lt;T>
<li>
std::list&lt;T>
</ul>
<hr>
<h3>Notes</h3>
<P>
<A name="1">[1]</A>
The reference type does not have to be a real C++ reference. The requirements of
the reference type is that it <i>behaves</i> like a real reference. Hence the
reference type must be convertible to the value_type and assignment through
<br>
<br>
<HR>
<br>
<TABLE>
<TR valign="top">
<TD nowrap>Copyright &copy 2000</TD>
<TD><A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>
</TR>
<tr >
<TD nowrap>Copyright &copy 2004</TD>
<TD>Thorsten Ottosen.
</TABLE>
</BODY>
</HTML> </HTML>

View File

@ -12,71 +12,65 @@
<table border="0" > <table border="0" >
<tr> <tr>
<td ><img src="cboost.gif" border="0" ></td> <td ><img src="cboost.gif" border="0" ></td>
<td ><h1 align="center">Boost.Range </h1></td> </tr> <td ><h1 align="center">Boost.Range </h1></td>
</tr>
</table> </table>
<h2>Terminology and style guidelines </h2> <h2>Terminology and style guidelines </h2>
<p> <p>
The use of a consistent terminologi is as important for iterator <a href="range.html#range">Range</a>s The use of a consistent terminology is as important for <a href="range.html#range">Range</a>s
and <a href="range.html#external_range">ExternalRange</a>-based algorithms as it and range-based algorithms as it is for iterators and iterator-based algorithms.
is for iterators and iterator-based algorithms. If a conventional set of names If a conventional set of names are adopted, we can avoid misunderstandings and
are adopted, we can avoid misunderstandings and write generic function write generic function prototypes that are <i>self-documenting</i>.
prototypes that are <i>self-documenting</i>.
</p> </p>
<p> <p>
Since iterator ranges are characterized by a specific underlying iterator type, Since ranges are characterized by a specific underlying iterator type, we get a
we get a type of iterator range for each type of iterator. Hence we can speak of type of range for each type of iterator. Hence we can speak of the following
the following types of iterator ranges: types of ranges:
<ul> <ul>
<li>
Range
<li>
ReversibleRange
<li> <li>
<i>Value access</i> category: <i>Value access</i> category:
<ul> <ul>
<li> <li>
ReadableRange Readable Range
<li> <li>
WriteableRange Writeable Range
<li> <li>
SwappableRange Swappable Range
<li> <li>
LvalueRange Lvalue Range
</ul> </ul>
<li> <li>
<i>Traversal</i> category: <i>Traversal</i> category:
<ul> <ul>
<li> <li>
IncrementableRange <a href="range.htm#single_pass_range">Single Pass Range</a>
<li> <li>
SinglePassRange <a href="range.htm#forward_range">Forward Range</a>
<li> <li>
ForwardRange <a href="range.htm#bidirectional_range">Bidirectional Range</a>
<li> <li>
BidirectionalRange <a href="range.htm#random_access_range">Random Access Range</a>
<li>
RandomAccessRange
</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 interator (and therefore an iterator range) has one <i>traversal</i> Notice that an iterator (and therefore an range) has one <i>traversal</i>
property and one or more properties from the <i>value access</i> category. So in property and one or more properties from the <i>value access</i> category. So in
reality we will mostly talk about mixtures such as reality we will mostly talk about mixtures such as
<ul> <ul>
<li> <li>
RandomAccessReadableWriteableRange Random Access Readable Writeable Range
<li> <li>
ForwardLvalueRange Forward Lvalue Range
</ul> </ul>
By convention, we should always specify the <i>travelsal</i> property first as By convention, we should always specify the <i>traversal</i> property first as
done above. This seems resonable since there will only be one <i>traversal</i> done above. This seems reasonable since there will only be one <i>traversal</i>
property, but perhaps many <i>value acccess</i> properties. property, but perhaps many <i>value access</i> properties.
</p> </p>
<p> <p>
@ -88,7 +82,7 @@
void sort( RandomAccessTraversalReadableWritableIterator first, void sort( RandomAccessTraversalReadableWritableIterator first,
RandomAccessTraversalReadableWritableIterator last ); RandomAccessTraversalReadableWritableIterator last );
</pre> </pre>
For iterator ranges the interface becomes For ranges the interface becomes
<pre> <pre>
template< class RandomAccessReadableWritableRange > template< class RandomAccessReadableWritableRange >

View File

@ -2,146 +2,179 @@
<html> <html>
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.Range Utility Classes </title> <title>Boost.Range Utilities </title>
<link rel="stylesheet" href="style.css" type="text/css"> <link rel="stylesheet" href="style.css" type="text/css">
</head> </head>
<body> <body>
<table border="0" > <table border="0" >
<tr> <tr>
<td ><img src="cboost.gif" border="0" ></td> <td ><img src="cboost.gif" border="0" ></td>
<td > <td ><h1 align="center">Boost.Range</h1></td>
<h1 align="center">Boost.Range utility classes</h1> </tr>
</td> </table>
</tr>
</table>
<h2>Utilities</h2>
<p>
Having an abstraction that encapsulates a pair of iterators is very useful. The
standard library uses <code>std::pair</code> in some circumstances, but that
class is cumbersome to use because we need to specify two template arguments,
and for all range algorithm purposes we must enforce the two template arguments
to be the same. Moreover, <code>std::pair&lt;iterator,iterator></code> is hardly
self-documenting whereas more domain specific class names are. Therefore these
two classes are provided:
<p> Having an abstraction that encapsulates a pair of iterators is very <ul>
useful. The standard library uses <code>std::pair</code> in some <li>
cercumstances, but that class is cumbersome to use because we need to Class <a href=#iter_range><code>iterator_range</code></a>
specify two template arguments, and for all range algorithm purposes, <li>
we must enforce the two template arguments to be the same. Moreover, Class <a href=#sub_range><code>sub_range</code></a>
<code>std::pair&lt;iterator,iterator></code> is hardly self-documenting </ul>
whereas more domain specific class names are. Therefore these two </ul>
classes are provided:
<ul> The <code>iterator_range</code> class is templated on an <a href="">Forward
<li>Class <a href=#iter_range><code>iterator_range</code></a> Traversal Iterator</a> and should be used whenever fairly general code is needed.
<li>Class <a href=#sub_range><code>sub_range</code></a> </ul> The <code>sub_range</code> class is templated on an <a href="range.htm#forward_range">Forward
</ul> Range</a> and it is less general, but a bit easier to use since its template
argument is easier to specify.
</p>
The <code>iterator_range</code> class is templated on an iterator and should be <hr>
used whenever super general code is needed. The <code>sub_range</code> class <a name=iter_range></a> <h1>Class <code>iterator_range</code></h1>
is templated on an <a href=range.html#external_range>ExternalRange</a> <p>
and it is less general, but a bit easier to use since its template argument The intention of the <code>iterator_range</code> class is to encapsulate two
is easier to specify. iterators so they fulfill the <a
</p> href="range.htm#forward_range">Forward Range</a> concept. A few other functions
are also provided for convenience.
</p>
<p>
If the template argument is not a model of Forward Traversal Iterator, one
can still use a subset of the interface. In particular, <code>size()</code>
requires Forward Traversal Iterators whereas <code>empty()</code> only
requires Single Pass Iterators.
</p>
<hr> <a name=iter_range></a> <h1>Class <code>iterator_range</code></h1> <h3>Synopsis</h3>
The intention of the
<code>iterator_range</code> class is to encapsulate
two iterators so they fulfill the <a href=range.html#range>Range</a> concept.
A few other functions are also provided for convinience.
<h3>Synopsis</h3> <pre>
<pre>
namespace boost namespace boost
{ {
template< class Iterator > template< class ForwardTraversalIterator >
class iterator_range class iterator_range
{ {
iterator_range(); // not implemented iterator_range(); // not implemented
public: // Range types public: // Forward Range types
typedef ... value_type; typedef ... value_type;
typedef ... difference_type; typedef ... difference_type;
typedef ... size_type; typedef ... size_type;
typedef Iterator iterator; typedef ForwardTraversalIterator iterator;
typedef Iterator const_iterator; typedef ForwardTraversalIterator const_iterator;
public: // construction, assignment public: // construction, assignment
template< class Iterator > template< class ForwardTraversalIterator2 >
iterator_range( Iterator Begin, Iterator End ); iterator_range( ForwardTraversalIterator2 Begin, ForwardTraversalIterator2 End );
template< class XRange > template< class ForwardRange >
iterator_range( XRange& r ); iterator_range( ForwardRange& r );
template< class XRange > template< class ForwardRange >
iterator_range( const XRange& r ); iterator_range( const ForwardRange& r );
template< class XRange > template< class ForwardRange >
iterator_range& operator=( XRange& r ); iterator_range& operator=( ForwardRange& r );
template< class XRange > template< class ForwardRange >
iterator_range& operator=( const XRange& r ); iterator_range& operator=( const ForwardRange& r );
public: // Range functions public: // Forward Range functions
iterator begin() const; iterator begin() const;
iterator end() const; iterator end() const;
size_type size() const; size_type size() const;
bool empty() const; bool empty() const;
public: // convenience public: // convenience
operator unspecified_bool_type() const; operator unspecified_bool_type() const;
void swap( iterator_range& r );
}; };
// stream output // stream output
template< class Iterator, class T, class Traits > template< class ForwardTraversalIterator, class T, class Traits >
std::basic_ostream&lt;T,Traits>& operator<<( std::basic_ostream&lt;T,Traits>& Os, std::basic_ostream&lt;T,Traits>& operator<<( std::basic_ostream&lt;T,Traits>& Os,
const iterator_range&lt;Iterator>& r ); const iterator_range&lt;ForwardTraversalIterator>& r );
// comparison // comparison
template< class Iterator > template< class ForwardTraversalIterator >
bool operator==( const iterator_range&lt;Iterator>& l, const iterator_range&lt;Iterator>& r ); bool operator==( const iterator_range&lt;ForwardTraversalIterator>& l, const iterator_range&lt;ForwardTraversalIterator>& r );
template< class Iterator > template< class ForwardTraversalIterator >
bool operator!=( const iterator_range&lt;Iterator>& l, const iterator_range&lt;Iterator>& r ); bool operator!=( const iterator_range&lt;ForwardTraversalIterator>& l, const iterator_range&lt;ForwardTraversalIterator>& r );
// external construction // external construction
template< class Iterator > template< class ForwardTraversalIterator >
iterator_range< Iterator > iterator_range< ForwardTraversalIterator >
make_iterator_range( Iterator Begin, Iterator End ); make_iterator_range( ForwardTraversalIterator Begin, ForwardTraversalIterator End );
template< class XRange > template< class ForwardRange >
iterator_range< typename iterator_of&lt;XRange>::type > iterator_range< typename iterator_of&lt;ForwardRange>::type >
make_iterator_range( XRange& r ); make_iterator_range( ForwardRange& r );
template< class XRange > template< class ForwardRange >
iterator_range< typename const_iterator_of&lt;XRange>::type > iterator_range< typename const_iterator_of&lt;ForwardRange>::type >
make_iterator_range( const XRange& r ); make_iterator_range( const ForwardRange& r );
// convenience // convenience
template< class Sequence, class XRange > template< class Sequence, class ForwardRange >
Sequence copy_range( const XRange& r ) Sequence copy_range( const ForwardRange& r );
template< class Sequence, class XRange, class Func > template< class Sequence, class ForwardRange, class Func >
Sequence transform_range( const XRange& r, Func func ); Sequence transform_range( const ForwardRange& r, Func func );
} // namespace 'boost' } // namespace 'boost'
</pre> </pre>
<p> <p>
It is worth noticing that the templated constructors and assignment operators It is worth noticing that the templated constructors and assignment operators
allow conversion from <code>iterator_range<iterator></code> to allow conversion from <code>iterator_range&lt;iterator></code> to
<code>iterator_range<const_iterator></code>. If an instance of <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>
<h3>Details member functions</h3>
<code>operator unspecified_bool_type() const; </code>
<blockquote>
Returns <code>!empty().</code>
<hr> <a name=sub_range></a> <!--
<h1>Class <code>sub_range</code></h1> <b>Example</b> <code> iterator_range<const char*> r( "a string" ); if( r )
do_something();</code>-->
</blockquote>
<h3>Details functions</h3>
The <code>sub_range</code> class inherits all its functionality <code>Sequence copy_range( const ForwardRange& r );</code>
from the <a href="#iter_range"><code>iterator_range</code></a> class. <blockquote>
Constructs a new sequence of the specified type from the elements
in the given range.
</blockquote>
<code>Sequence transform_range( const ForwardRange& r, Func func );</code>
<blockquote>
Constructs a new sequence from the elements in the range,
transformed by a function.
</blockquote>
<hr> <a name=sub_range></a>
<h1>Class <code>sub_range</code></h1>
The <code>sub_range</code> class inherits all its functionality
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#external_range">ExternalRange</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.
<h3>Synopsis</h3> <h3>Synopsis</h3>
@ -150,32 +183,40 @@ template argument instead of an iterator.
namespace boost namespace boost
{ {
template< class XRange > template< class ForwardRange >
class sub_range : public iterator_range< typename result_iterator_of&lt;XRange>::type > class sub_range : public iterator_range< typename result_iterator_of&lt;ForwardRange>::type >
{ {
public: // construction, assignment public: // construction, assignment
template< class Iterator > template< class ForwardTraversalIterator >
sub_range( Iterator Begin, Iterator End ); sub_range( ForwardTraversalIterator Begin, ForwardTraversalIterator End );
template< class XRange2 > template< class ForwardRange2 >
sub_range( XRange2& r ); sub_range( ForwardRange2& r );
template< class XRange2 > template< class ForwardRange2 >
sub_range( const Range2& r ); sub_range( const Range2& r );
template< class XRange2 > template< class ForwardRange2 >
sub_range& operator=( XRange2& r ); sub_range& operator=( ForwardRange2& r );
template< class XRange2 > template< class ForwardRange2 >
sub_range& operator=( const XRange2& r ); sub_range& operator=( const ForwardRange2& r );
public: public:
// rest of interface inherited from iterator_range // rest of interface inherited from iterator_range
}; };
} // namespace 'boost' } // namespace 'boost'
</pre>
</pre>
<p>
The class should be trivial to use, an example with strings is shown below.
<pre>
typedef sub_range<std::string> sub_string;
std::string s = "something";
sub_string ss( s );
sub_string ss2( begin( s ), begin( s ) + 2 );</pre>
<hr> <hr>
<p> <p>
@ -195,6 +236,6 @@ namespace boost
<br> <br>
<br> <br>
</body> </body>
</html> </html>

View File

@ -36,17 +36,19 @@
<ul> <ul>
<li> <a href=doc/intro.html>Introduction </a></code> <li> <a href=doc/intro.html>Introduction </a></code>
<li> <a href=doc/range.htm>Concepts:</a> <li><a href=doc/range.htm>Range concepts:</a>
<ul> <ul>
<li> <a href="doc/range.htm#range">Range</a> <li> <a href="doc/range.htm#single_pass_range">SinglePassRange</a>
<li> <a href="doc/range.htm#reversible_range">ReversibleRange</a> <li> <a href="doc/range.htm#range">ForwardRange</a>
<li> <a href="doc/range.htm#reversible_range">BidirectionalRange</a>
<li> <a href="doc/range.htm#random_access_range">RandomAccessRange</a>
</ul> </ul>
<li> <a href=doc/boost_range.html>Implementation</a> of Range and ReversibleRange for <ul> <li> <a href=doc/boost_range.html>Implementation</a> of Range concepts for <ul>
<li> arrays <li> standard containers
<li> Ranges <li> null-terminated strings
<li> strings
<li> pairs of iterators <li> pairs of iterators
<li> arrays
</ul> </ul>
<li> <a href=doc/utility_class.html> Utilities:</a> <li> <a href=doc/utility_class.html> Utilities:</a>