*** empty log message ***

[SVN r24371]
This commit is contained in:
Thorsten Jørgen Ottosen
2004-08-10 11:53:33 +00:00
parent 6157440017
commit e245cc6a7e
3 changed files with 395 additions and 310 deletions

View File

@ -6,353 +6,379 @@
<link rel="stylesheet" href="style.css" type="text/css">
</head>
<body>
<body>
<table >
<tr >
<td ><img src="cboost.gif" width="100%" border="0"></td>
<td ><h1 ><br>
Boost.Range </h1></td>
</tr>
</table>
<h2>Single Pass Range, Forward Range and Bidirectional Range Implementation</h2>
<table >
<tr >
<td ><img src="cboost.gif" width="100%" border="0"></td>
<td ><h1 ><br>
Boost.Range </h1></td>
</tr>
</table>
<ul >
<li>
<a href="#overview">Overview</a>
<li >
<a href="#Synopsis" >Synopsis</a>
</li>
<li >
<a href="#Semantics" >Semantics</a>
</li>
</ul>
<hr size="1" >
<h2>Range and ReversibleRange Implementation</h2>
<h3>Overview</h3>
<p>
Four types of objects are currently supported by the library:
<ul >
<li >
standard containers
</li>
<li >
<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 >
built-in arrays
</li>
</ul>
Even though the behavior of the primary templates are exactly such
that standard containers will be supported by default, the requirements
are much lower than the standard container requirements. For example,
the utility class <a href="utility_class#iterator_range"><code>iterator_range</code></a> implements the minimal interface required to make the class
a <a href="range.htm#forward_range">Forward Range</a>.
</p>
<p>
Please also see <a href="range.htm">Range concepts</a> for more details.
</p>
<a name="Synopsis" ></a>
<h3 >Synopsis</h3>
<ul >
<li>
<a href="#overview">Overview</a>
<li >
<a href="#Synopsis" >Synopsis</a>
</li>
<li >
<a href="#Semantics" >Semantics</a>
</li>
<li >
<a href="#Examples" >Examples</a>
</li>
</ul>
<hr size="1" >
<p >
<h3>Overview</h3>
<p>
Five types of objects are currently supported by the library:
<ul >
<li >
standard containers
</li>
<li >
<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 >
built-in arrays
</li>
</ul>
It is worth noticing that some functionality requires partial template
specialization, in particular, full array support does (remark: this is a very
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>
<p >
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>
<pre>
namespace boost
{
//
// Range metafunctions
// Single Pass Range metafunctions
//
template< class T >
struct <a href="#value_type_of" >value_type_of</a>
{
typedef ... type; // type of stored objTts
};
struct <a href="#value_type_of" >value_type_of</a>;
template< class T >
struct <a href="#iterator_of" >iterator_of</a>
{
typedef ... type; // iterator over stored objects
};
struct <a href="#iterator_of" >iterator_of</a>;
template< class T >
struct <a href="#const_iterator_of" >const_iterator_of</a>
{
typedef ... type; // iterator over immutable stored objects
};
struct <a href="#const_iterator_of" >const_iterator_of</a>;
//
// Forward Range metafunctions
//
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 );
};
struct <a href="#difference_type_of" >difference_type_of</a>;
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 ) );
};
struct <a href="#size_type_of" >size_type_of</a>;
//
// Bidirectional Range metafunctions
//
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
};
struct <a href="#reverse_iterator_of" >reverse_iterator_of</a>;
template< class T >
struct <a href="#const_reverse_iterator_of" >const_reverse_iterator_of</a>;
//
// Special metafunctions
//
template< class T >
struct <a href="#result_iterator_of" >result_iterator_of</a>;
template< class T >
struct <a href="#reverse_result_iterator_of" >reverse_result_iterator_of</a>;
//
// funtions
// Single Pass Range functions
//
template< class T >
inline typename iterator_of<T>::type
inline typename iterator_of&lt;T>::type
<a href="#begin" >begin</a>( T& c );
template< class T >
inline typename const_iterator_of< T >::type
inline typename const_iterator_of&lt;T>::type
<a href="#begin" >begin</a>( const T& c );
template< class T >
inline typename iterator_of< T >::type
inline typename iterator_of&lt;T>::type
<a href="#end" >end</a>( T& c );
template< class T >
inline typename const_iterator_of< T >::type
inline typename const_iterator_of&lt;T>::type
<a href="#end" >end</a>( const T& c );
template< class T >
inline bool
<a href="#empty" >empty</a>( const T& c );
//
// Forward Range functions
//
template< class T >
inline typename size_type_of< T >::type
inline typename size_type_of&lt;T>::type
<a href="#size" >size</a>( const T& c );
} // namespace 'boost' </pre>
</p>
<h3 >Semantics</h3><a name="Semantics" ></a>
<p >
In the table <code >C</code> is a type that conforms to the
ExternalCollectionConcept and <code >c</code> is an object of that type.<code >
SC</code>
will denote a standard container, <code >T[sz]</code> will denote an array of
type <code >T</code> of size <code >sz</code>, <code >P</code> will denote <code >
std::pair&lt;&gt;</code>,
<code >I</code> means an iterator which default construction denotes the end of
the range and <code >sc,t,p,i</code> are objects of these types, respectively.
Special cases for <code >char*</code> and <code >wchar_t*</code> are described
explicitly.
</p>
<table border="1" cellpadding="5" >
<tr >
<th >Expression</th>
<th >Return type</th>
<th >Complexity</th>
</tr>
<tr >
<a name="value_type_of" ></a>
<td ><code >value_type_of&lt;C&gt;::type</code></td>
<td ><code >SC::value_type</code><br>
<code >T</code><br>
<code >std::iterator_traits&lt;P::first_type&gt;::value_type</code><br>
<td >compile time</td>
</tr>
<tr >
<a name="iterator_of" ></a>
<td ><code >iterator_of&lt;C&gt;::type</code></td>
<td ><code >SC::iterator</code><br>
<code >T*</code><br>
<code >P::first_type</code><br>
<td >compile time</td>
</tr>
<tr >
<a name="const_iterator_of" ></a>
<td ><code >const_iterator_of&lt;C&gt;::type</code></td>
<td ><code >SC::const_iterator</code><br>
<code >const T*</code><br>
<code >P::first_type</code><br>
<td >compile time</td>
</tr>
<tr >
<a name="difference_type_of" ></a>
<td ><code >difference_type_of&lt;C&gt;::type</code></td>
<td ><code >SC::difference_type</code><br>
<code >std::ptrdiff_t</code><br>
<code >std::iterator_traits&lt;P::first_type&gt;:: difference_type</code><br>
<td >compile time</td>
</tr>
<tr >
<a name="size_type_of" ></a>
<td ><code >size_type_of&lt;C&gt;::type</code></td>
<td ><code >SC::size_type</code><br>
<code >std::size_t</code><br>
<code >std::size_t</code><br>
<td >compile time</td>
</tr>
<tr >
<a name="result_iterator_of" ></a>
<td ><code >result_iterator_of&lt;C&gt;::type</code></td>
<td ><code >const_iterator_of&lt; C&gt;::type</code> if <code >C</code> is <code >
const</code>
<br>
<code >iterator_of&lt;C&gt;::type</code> otherwise </td>
<td >compile time</td>
</tr>
<tr >
<a name="reverse_iterator_of" ></a>
<td ><code >reverse_iterator_of&lt;C&gt;::type</code></td>
<td ><code >boost::reverse_iterator< typename iterator_of&lt;T>::type
></code><br> <td >compile time</td>
</tr>
<tr >
<a name="const_reverse_iterator_of" ></a>
<td ><code >const_reverse_iterator_of&lt;C&gt;::type</code></td>
<td ><code >boost::reverse_iterator< typename const_iterator_of&lt;T>::type ></code><br>
<td >compile time</td>
</tr> <tr >
<a name="reverse_result_iterator_of" ></a>
<td ><code >reverse_result_iterator_of&lt;C&gt;::type</code></td>
<td ><code >boost::reverse_iterator< typename result_iterator_of&lt;T&gt;::
type ></code>
<td >compile time</td>
</tr>
</table>
<br>
<table border="1" cellpadding="5" >
<tr >
<th >Expression</th>
<th >Return type</th>
<th >Returns</th>
<th >Complexity</th>
</tr>
<tr >
<a name="begin" ></a>
<td ><code >begin( c )</code></td>
<td ><code >result_iterator_of&lt;C&gt;::type</code></td>
<td ><code >sc.begin()</code><br>
<code >t</code><br>
<code >p.first</code><br>
<td >constant time</td>
</tr>
<tr >
<a name="end" ></a>
<td ><code >end( c )</code></td>
<td ><code >result_iterator_of&lt;C&gt;::type</code></td>
<td ><code >sc.end()</code><br>
<code >t + std::char_traits&lt;C&gt;::length( t )</code> if <code >C</code> is <code >
char*</code>
or <code >wchar_t*</code><br>
<code >t + sz - 1</code> if <code >C</code> is <code >char[sz]</code> or <code >
wchar_t[sz]</code>
<br>
<code >t + sz</code> otherwise <br>
<code >p.second</code><br>
<td >linear if <code >C</code> is <code >char*</code> or <code >wchar_t*</code>
<br>
constant time otherwise</td>
</tr>
<tr >
<a name="empty" ></a>
<td ><code >empty( c )</code></td>
<td >Convertible to <code >bool</code></td>
<td ><code >sc.empty()</code><br>
<code >size( t ) == 0</code><br>
<code >p.first == p.second</code><br>
<td >linear if <code >C</code> is <code >char*</code> or <code >wchar_t*</code>
<br>
constant time otherwise<br>
</td>
</tr>
<tr >
<a name="size" ></a>
<td ><code >size( c )</code></td>
<td ><code >size_type_of&lt;C&gt;::type</code></td>
<td ><code >sc.size()</code><br>
<code >end( t ) - begin( t )</code><br>
<code >distance( p. first, p.second )</code><br>
<td >linear if <code >C</code> is <code >char*</code> or <code >wchar_t*</code>
<br>
or if <code >std::distance()</code> is linear <br>
constant time otherwise</td>
</tr>
<tr >
<a name="rbegin" ></a>
<td ><code >rbegin( c )</code></td>
<td ><code >reverse_result_iterator_of&lt;C&gt;::type</code></td>
<td ><code >reverse_result_iterator_of&lt;C&gt;::type( end( c ) )</code>
<br>
<td >same as <code>end()</code> </td>
</tr>
<tr >
<a name="rend" ></a>
<td ><code >rend( c )</code></td>
<td ><code >reverse_result_iterator_of&lt;C&gt;::type</code></td>
<td ><code >reverse_result_iterator_of&lt;C&gt;::type( begin( c ) )</code>
<td > same as <code>begin()</code></td>
</tr>
</table>
<p >
Please note that <code >char*</code>,<code >whar_t*</code>,<code >char[]</code>,
and <code >wchar_t[]</code> behaves differently from normal arrays only for <code >
size()</code>
and <code >end()</code>. Note that the null pointer is allowed as an argument
in these cases.
</p>
<hr size="1" ><h2 >Examples</h2><a name="Examples" ></a>
<p >
Some examples are given in the accompanying test files:
</p>
<ul >
<li >
<a href="../test/iterator.cpp" target="_self" ><code >iterator.cpp</code></a>
</li>
shows how to implement a container version of <code >std::copy()</code> that
works with <code >std::ifstream_iterator&lt;&gt;.</code>
<li >
<a href="../test/string.cpp" target="_self" ><code >string.cpp</code></a>
</li>
shows how to implement a container version of <code >std::find()</code> that
works with <code >char[],wchar_t[],char*,wchar_t*.</code>
<li >
<a href="../test/algorithm_example.cpp" target="_self" ><code >algorithm_example.cpp</code></a>
//
// Bidirectional Range functions
//
template< class T >
inline typename reverse_iterator_of&lt;T>::type
<a href="#rbegin" >rbegin</a>( T& c );
template< class T >
inline typename const_reverse_iterator_of&lt;T>::type
<a href="#rbegin" >rbegin</a>( const T& c );
</li>
shows the replace example from the introduction.
</ul>
template< class T >
inline typename reverse_iterator_of&lt;T>::type
<a href="#rend" >rend</a>( T& c );
template< class T >
inline typename const_reverse_iterator_of&lt;T>::type
<a href="#rend" >rend</a>( const T& c );
} // namespace 'boost' </pre>
</p>
<a name="Semantics" ></a>
<h3 >Semantics</h3>
<h4>notation</h4>
<p>
<table cellpadding="5" border="1">
<tr>
<th>Type
<th>Object
<th>Describes
</tr>
<tr>
<td><code>X</code>
<td> <code>x</code>
<td>any type
</tr>
<tr>
<td><code>T</code> </td>
<td><code>t</code>
<td>denotes behavior of the primary templates</td>
</tr>
<tr>
<td><code>P</code>
<td><code>p</code>
<td>denotes <code>std::pair&lt;iterator,iterator></code>
</tr>
<tr>
<td><code>A[sz]</code>
<td><code>a</code>
<td>denotes an array of type <code>A</code> of size <code>sz</code>
<tr>
<tr>
<td><code>Char*</code>
<td><code>s</code>
<td>denotes either <code>char*</code> or <code>wchar_t*</code>
</tr>
</table>
</p>
<p>
Please notice in tables below that when four lines appear in a
cell, the first line will describe the primary template, the second
line pairs of iterators, the third line arrays and the last line
null-terminated strings.
</p>
<h4>Metafunctions</h4>
<p>
<table border="1" cellpadding="5" >
<tr >
<th >Expression</th>
<th >Return type</th>
<th >Complexity</th>
</tr>
<tr >
<a name="value_type_of" ></a>
<td ><code >value_type_of&lt;X&gt;::type</code></td>
<td ><code >T::value_type</code><br>
<code >boost::iterator_value&lt;P::first_type&gt;::type</code><br>
<code >A</code><br>
<code>Char</code>
<td >compile time</td>
</tr>
<tr >
<a name="iterator_of" ></a>
<td ><code >iterator_of&lt;X&gt;::type</code></td>
<td ><code >T::iterator</code><br>
<code >P::first_type</code><br>
<code >A*</code><br>
<code>Char*</code>
<td >compile time</td>
</tr>
<tr >
<a name="const_iterator_of" ></a>
<td ><code >const_iterator_of&lt;X&gt;::type</code></td>
<td ><code >T::const_iterator</code><br>
<code >P::first_type</code><br>
<code >const A*</code><br>
<code>const Char*</code>
<td >compile time</td>
</tr>
<tr >
<a name="difference_type_of" ></a>
<td ><code >difference_type_of&lt;X&gt;::type</code></td>
<td ><code >T::difference_type</code><br>
<code
>boost_iterator_difference&lt;P::first_type&gt;::type</code><br>
<code >std::ptrdiff_t</code><br>
<code >std::ptrdiff_t</code><br>
<td >compile time</td>
</tr>
<tr >
<a name="size_type_of" ></a>
<td ><code >size_type_of&lt;X&gt;::type</code></td>
<td ><code >T::size_type</code><br>
<code >std::size_t</code><br>
<code >std::size_t</code><br>
<code >std::size_t</code><br>
<td >compile time</td>
</tr>
<tr >
<a name="result_iterator_of" ></a>
<td ><code >result_iterator_of&lt;X&gt;::type</code></td>
<td ><code >const_iterator_of&lt;X&gt;::type</code> if <code
>X</code> is <code >const</code> <br>
<code >iterator_of&lt;X&gt;::type</code> otherwise </td>
<td >compile time</td>
</tr>
<tr >
<a name="reverse_iterator_of" ></a>
<td ><code >reverse_iterator_of&lt;X&gt;::type</code></td>
<td ><code >boost::reverse_iterator< typename iterator_of&lt;T>::type ></code><br>
<td >compile time</td>
</tr>
<tr >
<a name="const_reverse_iterator_of" ></a>
<td ><code >const_reverse_iterator_of&lt;X&gt;::type</code></td>
<td ><code >boost::reverse_iterator< typename const_iterator_of&lt;T>::type ></code>
<br>
<td >compile time</td>
</tr>
<tr >
<a name="reverse_result_iterator_of" ></a>
<td ><code >reverse_result_iterator_of&lt;X&gt;::type</code></td>
<td ><code >boost::reverse_iterator< typename result_iterator_of&lt;T&gt;::type ></code>
<td >compile time</td>
</tr>
</table>
</p>
<p>
The special metafunctions <code>result_iterator_of</code> and
<code>reverse_result_iterator_of</code> are not part
of any Range concept, but they are very useful when implementing certain
Range classes like <a
href="utility_class.html#sub_range"><code>sub_range</code></a> because of
their ability to select iterators based on constness.
</p>
<h4>Functions</h4>
<p>
<table border="1" cellpadding="5" >
<tr >
<th >Expression</th>
<th >Return type</th>
<th >Returns</th>
<th >Complexity</th>
</tr>
<tr >
<a name="begin" ></a>
<td ><code >begin(x)</code></td>
<td ><code >result_iterator_of&lt;X&gt;::type</code></td>
<td ><code >t.begin()</code><br>
<code >p.first</code><br>
<code >a</code><br>
<code>s</code>
<td >constant time</td>
</tr>
<tr >
<a name="end" ></a>
<td ><code >end(x)</code></td>
<td ><code >result_iterator_of&lt;X&gt;::type</code></td>
<td ><code >t.end()</code><br>
<code >p.second</code><br>
<code >a + sz</code> <br>
<code >s + std::char_traits&lt;X&gt;::length( s )</code> if
<code >X</code> is <code >Char*</code><br>
<code >s + sz - 1</code> if <code >X</code> is <code >Char[sz]</code> <br>
<td >linear if <code >X</code> is <code >Char*</code> <br>
constant time otherwise</td>
</tr>
<tr >
<a name="empty" ></a>
<td ><code >empty(x)</code></td>
<td ><code >bool</code></td>
<td ><code >begin(x) == end( x )</code><br>
<td >linear if <code >X</code> is <code >Char*</code> <br>
constant time otherwise<br>
</td>
</tr>
<tr >
<a name="size" ></a>
<td ><code >size(x)</code></td>
<td ><code >size_type_of&lt;X&gt;::type</code></td>
<td ><code >t.size()</code><br>
<code>std::distance(p.first,p.second)</code><br>
<code >sz</code><br>
<code>end(s) - s</code>
<td >linear if <code >X</code> is <code >Char*</code> <br>
or if <code >std::distance()</code> is linear <br>
constant time otherwise</td>
</tr>
<tr >
<a name="rbegin" ></a>
<td ><code >rbegin(x)</code></td>
<td ><code >reverse_result_iterator_of&lt;X&gt;::type</code></td>
<td ><code >reverse_result_iterator_of&lt;X&gt;::type( end(x)
)</code> <br> <td >same as <code>end(x)</code> </td>
</tr>
<tr >
<a name="rend" ></a>
<td ><code >rend(x)</code></td>
<td ><code >reverse_result_iterator_of&lt;X&gt;::type</code></td>
<td ><code >reverse_result_iterator_of&lt;X&gt;::type( begin(x)
)</code> <td >same as <code>begin(x)</code></td>
</tr>
</table>
</p>
<hr>
<p>