*** 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>
<title>Boost.Range Range Implementation </title>
<meta http-equiv="Content-Type"content="text/html; charset=iso-8859-1">
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
@ -42,17 +43,14 @@ Five types of objects are currently supported by the library:
standard containers
</li>
<li >
built-in arrays
<code >std::pair&lt;iterator,iterator&gt;</code>
</li>
<li >
null terminated strings (this includes <code >char[]</code>,<code >wchar_t[]</code>,
<code >char*</code>, and <code >wchar_t*</code>)
</li>
<li >
<code >std::pair&lt;iterator,iterator&gt;</code>
</li>
<li >
iterators which when default constructed denotes the end of the range
built-in arrays
</li>
</ul>
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
treated special because of their use in string algorithms.
</p>
<h3 >ExternalCollectionConcept</h3><a name="ExternalCollectionConcept" ></a>
<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
such general requirement, that is, if one wants to extend the list of supported
types, it can be done in any namespace.
</p>
<h3 >Synopsis</h3><a name="Synopsis" ></a>
<p >
<pre>
namespace boost
{
//
// type generators
//
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 );
namespace boost
{
//
// Range metafunctions
//
template< typename EC >
inline typename const_iterator_of< EC >::type
<a href="#begin" >begin</a>( const EC& c );
template< typename EC >
inline typename iterator_of< EC >::type
<a href="#end" >end</a>( EC& c );
template< typename EC >
inline typename const_iterator_of< EC >::type
<a href="#end" >end</a>( const EC& c );
template< class T >
struct <a href="#value_type_of" >value_type_of</a>
{
typedef ... type; // type of stored objTts
};
template< class T >
struct <a href="#iterator_of" >iterator_of</a>
{
typedef ... type; // iterator over stored objects
};
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 >
inline bool
<a href="#empty" >empty</a>( const EC& c );
template< typename EC >
inline typename size_type_of< EC >::type
<a href="#size" >size</a>( const EC& c );
} // namespace 'boost' </pre>
template< class T >
inline typename iterator_of< T >::type
<a href="#end" >end</a>( T& c );
template< class T >
inline typename const_iterator_of< T >::type
<a href="#end" >end</a>( const T& c );
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>

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
the template parameter(s) must satisfy certain requirements.Often these
requirements are so important that we give them a name: we call
such a set of type requirements a <b>concept</b>. We say that a type <i>
conforms to a concept</i> or that it <i>is a model of a concept</i> if it
satisfies all of those requirements. The concept can be specified as a set
of member functions with well-defined semantics
and a set of nested typedefs with well-defined properties.</p><p >Often it much more flexible to provide free-standing functions and typedefs
which provides the exact same semantics (but a different syntax) as
specified
by the concept. This allows generic code to treat different types <i> as if
</i> they fulfilled the concept. In this case we say that the concept has
been <b> externalized </b> or that the new requirements constitutes an <b>external
concept </b>. We say that a type <i> conforms to an external concept </i>
or that it <i> is a model of an external concept </i>. A concept may exist
without a corresponding external concept and conversely.</p><p >Whenever a concept specifies a member function, the corresponding external
concept
must specify a free-standing function of the same name, same return type and
the same argument list except there is an extra first argument which must
be 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>type-generator</b>, that is, a type with a nested typedef
named <code>type</code>. The type-generator 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 type-generators 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 -->
<!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 the template parameter(s) must satisfy certain requirements.Often
these requirements are so important that we give them a name: we call such a set
of type requirements a <b>concept</b>. We say that a type <i>conforms to a
concept</i> or that it <i>is a model of a concept</i> if it satisfies all of
those requirements. The concept can be specified as a set of member functions
with well-defined semantics and a set of nested typedefs with well-defined
properties.
</p>
<p >
Often it much more flexible to provide free-standing functions and typedefs
which provides the exact same semantics (but a different syntax) as specified by
the concept. This allows generic code to treat different types <i>as if</i> they
fulfilled the concept. In this case we say that the concept has been <b>externalized
</b> or that the new requirements constitutes an <b>external concept </b>. We
say that a type <i>conforms to an external concept </i> or that it <i>is a model
of an external concept </i>. A concept may exist without a corresponding
external concept and conversely.
</p>
<p >
Whenever a concept specifies a member function, the corresponding external
concept must specify a free-standing function of the same name, same return type
and the same argument list except there is an extra first argument which must be
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>
<p>
<h2 >FAQ</h2>
<a name="FAQ" ></a>
<h2 >FAQ</h2> <a name="FAQ" ></a>
<ol >
<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>
for <code >std::pair&lt;iterator, iterator&gt;</code>.
<i>Why is there no difference between <code >iterator_of&lt;C&gt;::type</code>
and <code >const_iterator_of&lt;C&gt;::type</code> for <code >std::pair&lt;iterator,
iterator&gt;</code></i>.
</li>
<p >
In general it is not possible nor desirable to find a corresponding <code >const_iterator</code>.
@ -30,24 +30,71 @@
object.
</p>
<li >
Why is there not supplied more types or more functions?
<i>Why is there not supplied more types or more functions?</i>
<p >
The library have been kept small because its current interface will serve
most purposes. If and when a genuine need arises for more functionality, it can
be implemented.
The library have been kept small because its current interface will serve most
purposes. If and when a genuine need arises for more functionality, it can be
implemented.
</p>
</li>
<li >
How should I implement generic algorithms for ranges?
<i>How should I implement generic algorithms for ranges?</i>
<p >
One should always start with a generic algorithm that takes two
iterators (or more) as
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 algorithm is done, it makes sense <i>not</i> to expose the
iterator version in the public interface.
One should always start with a generic algorithm that takes two iterators (or
more) as 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
algorithm is done, it makes sense <i>not</i> to expose the iterator version in
the public interface.
</p>
</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>

View File

@ -22,87 +22,108 @@
<tr >
<th >Header</th>
<th >Includes</th>
<th>Related concept </th>
</tr>
<tr >
<td ><code >&lt;boost/range.hpp&gt;</code></td>
<td >everything</td>
<td>- </td>
</tr>
<tr >
<td ><code >&lt;boost/range/types.hpp&gt;</code></td>
<td >every meta-function</td>
<td ><code >&lt;boost/range/metafunctions.hpp&gt;</code></td>
<td >every metafunction</td>
<td>- </td>
</tr>
<tr >
<td ><code >&lt;boost/range/functions.hpp&gt;</code></td>
<td >every function</td>
<td>- </td>
</tr>
<tr >
<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="range.htm#single_pass_range">Single Pass Range</a></td>
</tr>
<tr >
<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="range.htm#single_pass_range">Single Pass Range</a> </td>
</tr>
<tr >
<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="range.htm#single_pass_range">Single Pass Range</a> </td>
</tr>
<tr >
<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="range.htm#forward_range">Forward Range</a> </td>
</tr>
<tr >
<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="range.htm#forward_range">Forward Range</a> </td>
</tr>
<tr >
<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>- </td>
</tr>
<tr >
<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="range.htm#bidirectional_range">Bidirectional Range</a> </td>
</tr>
<tr >
<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="range.htm#bidirectional_range">Bidirectional Range</a> </td>
</tr>
<tr >
<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>- </td>
</tr>
<tr >
<td ><code >&lt;boost/range/begin.hpp&gt;</code></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 >
<td ><code >&lt;boost/range/end.hpp&gt;</code></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 >
<td ><code >&lt;boost/range/empty.hpp&gt;</code></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 >
<td ><code >&lt;boost/range/size.hpp&gt;</code></td>
<td ><a href="boost_range.html#size" >size</a></td>
<td><a href="range.htm#forward_range">Forward Range</a> </td>
</tr>
<tr >
<td ><code >&lt;boost/range/rbegin.hpp&gt;</code></td>
<td ><a href="boost_range.html#rbegin" >rbegin</a></td>
<td><a href="range.htm#bidirectional_range">Bidirectional Range</a> </td>
</tr>
<tr >
<td ><code >&lt;boost/range/rend.hpp&gt;</code></td>
<td ><a href="boost_range.html#rend" >rend</a></td>
<td><a href="range.htm#bidirectional_range">Bidirectional Range</a> </td>
</tr>
<tr >
<td ><code >&lt;boost/range/iterator_range.hpp&gt;</code></td>
<td ><a href="utility_class.html#iter_range"
>iterator_range</a></td>
>iterator_range</a></td>
<td>- </td>
</tr>
<tr >
<td ><code >&lt;boost/range/sub_range.hpp&gt;</code></td>
<td ><a href="utility_class.html#sub_range" >sub_range</a></td>
<td>- </td>
</tr>
</table>

View File

@ -25,10 +25,25 @@
</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
treatment of character arrays.
</p>
treatment of character arrays. In the end it made sense to formalize the
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>
Special thanks goes to

View File

@ -18,22 +18,32 @@
<h2>Introduction</h2>
<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
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"
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
built-in arrays, standard containers, pairs of iterators and some iterators
uniformly.
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
built-in arrays, standard containers, pairs of iterators and some iterators
uniformly.
</p>
-->
<p >
The main advantages are
<ul >
<li >
safe use of built-in arrays
</li>
<li >
simpler implementation of generic container algorithms
simpler implementation of generic range algorithms
</li>
<li >
more flexible client code
@ -41,58 +51,69 @@
<li >
correct handling of null-terminated strings
</li>
<li >
safe use of built-in arrays (for legacy code; why else would you use
arrays?) </li>
</ul>
</p>
<p >
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 );
//
// 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 );
if( found != boost::end( c ) )
*found = replacement;
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>
return std::distance( boost::begin( c ), found );
}
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
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

View File

@ -20,7 +20,7 @@
<p >
Full support for built-in arrays require that the compiler supports class
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>
<p >
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">
</HEAD>
<table border="0" >
<tr>
<td ><img src="cboost.gif" border="0" ></td>
<td ><h1 align="center">Boost.Range </h1></td>
</tr>
</table>
<table border="0" >
<tr>
<td ><img src="cboost.gif" border="0" ></td>
<td ><h1 align="center">Boost.Range </h1></td>
</tr>
</table>
<h2>Range concepts </h2>
<h2>Range concepts </h2>
<ul>
<li>
<a href="#range">Range</a>
<li>
<a href="#reversible_range">ReversibleRange</a>
</ul>
<hr>
<ul>
<li>
<a href="#overview">Overview</a>
<li>
<a href="#single_pass_range">Single Pass Range</a>
<li>
<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
href="http://www.sgi.com/Technology/STL/Container.html">Container</a> concept. A
Range provides iterators for accessing a range of elements and provides
information about the number of elements in the Range. However, a Range has
fewer requirements than a Container. 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
<ul>
<li>
own the elements that can be accessed through it,
<li>
have copy semantics,
<!--
<li>
require that the associated reference type is a real C++ reference.
-->
</ul>
<ul>
<li>
own the elements that can be accessed through it,
<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
generic code.
Because of the second requirement, a Range object must be passed by reference in
generic code.
</p>
<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>
<Table>
<TR>
<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>
<hr>
<a name="single_pass_range">
<H2>Single Pass Range</H2>
<h3>Associated types</h3>
<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">
<h3>Notation</h3>
<Table>
<TR>
<TD VAlign="top"><tt>begin(a)</tt></TD>
<TD VAlign="top">Returns an iterator pointing to the first element in the 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>
<TD VAlign="top"><code>X</code></TD>
<TD VAlign="top">A type that is a model of Single Pass Range.</TD>
</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
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>
<TD VAlign="top"><tt>size(a)</tt></TD>
<TD VAlign="top">Returns the size of the Collection, that is, its number of
elements.</TD>
<TD VAlign="top"><tt>size(a) &gt;= 0</TD>
<TD VAlign="top"><code>empty(a)</code></TD>
<TD VAlign="top">Equivalent to <code>begin(a) == end(a)</code>. (But possibly
faster.)</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>
<TD VAlign="top"><tt>empty(a)</tt></TD>
<TD VAlign="top">Equivalent to <tt>size(a) == 0</tt>. (But
possibly faster.)</TD> <TD VAlign="top">&nbsp;-&nbsp;</TD>
<TD VAlign="top">Completeness</TD>
<TD VAlign="top">An algorithm that iterates through the range <code>[begin(a),end(a))</code>
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>
</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
purposes, one can expect <tt>begin(a)</tt>, <tt>end(a)</tt> and
<tt>empty(a)</tt> to be amortized constant time.
<h3>Refinement of</h3> <a href="#single_pass_range">Single Pass
Range</a>
<h3>Associated types</h3>
<h3>Invariants</h3>
<Table border>
<TR>
<TD VAlign="top">Valid range</TD>
<TD VAlign="top">For any Range <tt>a</tt>, <tt>[begin(a),end(a))</tt> 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>
<TD VAlign="top">Range size</TD>
<TD VAlign="top"><tt>size(a)</tt> is equal to the distance from
<tt>begin(a)</tt> to <tt>end(a)</tt>.</TD>
</TR>
<TR>
<TD VAlign="top">Completeness</TD>
<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>
</tr>
</table>
<table cellpadding="5" border="1">
<TR>
<TD VAlign="top">Distance type</TD>
<TD VAlign="top"><code>difference_type_of&lt;X>::type</code></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"><code>size_type_of&lt;X>::type</code></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>
<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>
<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>Valid expressions</h3>
<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>
<br>
<hr>
<br>
</table>
<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
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>Notes</h3>
<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>
<TR>
<TD VAlign="top">Reverse Iterator type</TD>
<TD VAlign="top"><tt>X::reverse_iterator</tt></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. 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>
<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>
<h3>Valid expressions</h3>
<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"><tt>rbegin(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(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>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
<br>
</BODY>
</HTML>

View File

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

View File

@ -2,146 +2,179 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.Range Utility Classes </title>
<link rel="stylesheet" href="style.css" type="text/css">
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Boost.Range Utilities </title>
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<table border="0" >
<tr>
<td ><img src="cboost.gif" border="0" ></td>
<td >
<h1 align="center">Boost.Range utility classes</h1>
</td>
</tr>
</table>
<body>
<table border="0" >
<tr>
<td ><img src="cboost.gif" border="0" ></td>
<td ><h1 align="center">Boost.Range</h1></td>
</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
useful. The standard library uses <code>std::pair</code> in some
cercumstances, 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:
<ul>
<li>
Class <a href=#iter_range><code>iterator_range</code></a>
<li>
Class <a href=#sub_range><code>sub_range</code></a>
</ul>
</ul>
<ul>
<li>Class <a href=#iter_range><code>iterator_range</code></a>
<li>Class <a href=#sub_range><code>sub_range</code></a> </ul>
</ul>
The <code>iterator_range</code> class is templated on an <a href="">Forward
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
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
used whenever super general code is needed. The <code>sub_range</code> class
is templated on an <a href=range.html#external_range>ExternalRange</a>
and it is less general, but a bit easier to use since its template argument
is easier to specify.
</p>
<hr>
<a name=iter_range></a> <h1>Class <code>iterator_range</code></h1>
<p>
The intention of the <code>iterator_range</code> class is to encapsulate two
iterators so they fulfill the <a
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>
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>
<h3>Synopsis</h3>
<pre>
<pre>
namespace boost
{
template< class Iterator >
template< class ForwardTraversalIterator >
class iterator_range
{
iterator_range(); // not implemented
public: // Range types
typedef ... value_type;
typedef ... difference_type;
typedef ... size_type;
typedef Iterator iterator;
typedef Iterator const_iterator;
public: // Forward Range types
typedef ... value_type;
typedef ... difference_type;
typedef ... size_type;
typedef ForwardTraversalIterator iterator;
typedef ForwardTraversalIterator const_iterator;
public: // construction, assignment
template< class Iterator >
iterator_range( Iterator Begin, Iterator End );
template< class ForwardTraversalIterator2 >
iterator_range( ForwardTraversalIterator2 Begin, ForwardTraversalIterator2 End );
template< class XRange >
iterator_range( XRange& r );
template< class ForwardRange >
iterator_range( ForwardRange& r );
template< class XRange >
iterator_range( const XRange& r );
template< class ForwardRange >
iterator_range( const ForwardRange& r );
template< class XRange >
iterator_range& operator=( XRange& r );
template< class ForwardRange >
iterator_range& operator=( ForwardRange& r );
template< class XRange >
iterator_range& operator=( const XRange& r );
template< class ForwardRange >
iterator_range& operator=( const ForwardRange& r );
public: // Range functions
iterator begin() const;
iterator end() const;
public: // Forward Range functions
iterator begin() const;
iterator end() const;
size_type size() const;
bool empty() const;
public: // convenience
operator unspecified_bool_type() const;
void swap( iterator_range& r );
operator unspecified_bool_type() const;
};
// 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,
const iterator_range&lt;Iterator>& r );
const iterator_range&lt;ForwardTraversalIterator>& r );
// comparison
template< class Iterator >
bool operator==( const iterator_range&lt;Iterator>& l, const iterator_range&lt;Iterator>& r );
template< class ForwardTraversalIterator >
bool operator==( const iterator_range&lt;ForwardTraversalIterator>& l, const iterator_range&lt;ForwardTraversalIterator>& r );
template< class Iterator >
bool operator!=( const iterator_range&lt;Iterator>& l, const iterator_range&lt;Iterator>& r );
template< class ForwardTraversalIterator >
bool operator!=( const iterator_range&lt;ForwardTraversalIterator>& l, const iterator_range&lt;ForwardTraversalIterator>& r );
// external construction
template< class Iterator >
iterator_range< Iterator >
make_iterator_range( Iterator Begin, Iterator End );
template< class ForwardTraversalIterator >
iterator_range< ForwardTraversalIterator >
make_iterator_range( ForwardTraversalIterator Begin, ForwardTraversalIterator End );
template< class XRange >
iterator_range< typename iterator_of&lt;XRange>::type >
make_iterator_range( XRange& r );
template< class ForwardRange >
iterator_range< typename iterator_of&lt;ForwardRange>::type >
make_iterator_range( ForwardRange& r );
template< class XRange >
iterator_range< typename const_iterator_of&lt;XRange>::type >
make_iterator_range( const XRange& r );
template< class ForwardRange >
iterator_range< typename const_iterator_of&lt;ForwardRange>::type >
make_iterator_range( const ForwardRange& r );
// convenience
template< class Sequence, class XRange >
Sequence copy_range( const XRange& r )
template< class Sequence, class ForwardRange >
Sequence copy_range( const ForwardRange& r );
template< class Sequence, class XRange, class Func >
Sequence transform_range( const XRange& r, Func func );
template< class Sequence, class ForwardRange, class Func >
Sequence transform_range( const ForwardRange& r, Func func );
} // namespace 'boost'
</pre>
</pre>
<p>
It is worth noticing that the templated constructors and assignment operators
allow conversion from <code>iterator_range<iterator></code> to
<code>iterator_range<const_iterator></code>. If an instance of
<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
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>. If an instance of
<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
<code>[begin,end)</code>.
</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
from the <a href="#iter_range"><code>iterator_range</code></a> class.
<code>Sequence copy_range( const ForwardRange& r );</code>
<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
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.
<h3>Synopsis</h3>
@ -150,32 +183,40 @@ template argument instead of an iterator.
namespace boost
{
template< class XRange >
class sub_range : public iterator_range< typename result_iterator_of&lt;XRange>::type >
template< class ForwardRange >
class sub_range : public iterator_range< typename result_iterator_of&lt;ForwardRange>::type >
{
public: // construction, assignment
template< class Iterator >
sub_range( Iterator Begin, Iterator End );
template< class ForwardTraversalIterator >
sub_range( ForwardTraversalIterator Begin, ForwardTraversalIterator End );
template< class XRange2 >
sub_range( XRange2& r );
template< class ForwardRange2 >
sub_range( ForwardRange2& r );
template< class XRange2 >
template< class ForwardRange2 >
sub_range( const Range2& r );
template< class XRange2 >
sub_range& operator=( XRange2& r );
template< class ForwardRange2 >
sub_range& operator=( ForwardRange2& r );
template< class XRange2 >
sub_range& operator=( const XRange2& r );
template< class ForwardRange2 >
sub_range& operator=( const ForwardRange2& r );
public:
// rest of interface inherited from iterator_range
};
} // 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>
<p>
@ -195,6 +236,6 @@ namespace boost
<br>
<br>
</body>
</body>
</html>

View File

@ -36,17 +36,19 @@
<ul>
<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>
<li> <a href="doc/range.htm#range">Range</a>
<li> <a href="doc/range.htm#reversible_range">ReversibleRange</a>
<li> <a href="doc/range.htm#single_pass_range">SinglePassRange</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>
<li> <a href=doc/boost_range.html>Implementation</a> of Range and ReversibleRange for <ul>
<li> arrays
<li> Ranges
<li> strings
<li> <a href=doc/boost_range.html>Implementation</a> of Range concepts for <ul>
<li> standard containers
<li> null-terminated strings
<li> pairs of iterators
<li> arrays
</ul>
<li> <a href=doc/utility_class.html> Utilities:</a>