forked from boostorg/utility
Compare commits
3 Commits
svn-branch
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
|
7ea60a96f8 | ||
|
a9adec170a | ||
|
8808f55435 |
762
call_traits.htm
Normal file
762
call_traits.htm
Normal file
@@ -0,0 +1,762 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type"
|
||||||
|
content="text/html; charset=iso-8859-1">
|
||||||
|
<meta name="Template"
|
||||||
|
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
||||||
|
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
|
||||||
|
<title>Call Traits</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
|
||||||
|
vlink="#800080">
|
||||||
|
|
||||||
|
<h1><img src="../../c++boost.gif" width="276" height="86">Header
|
||||||
|
<<a href="../../boost/detail/call_traits.hpp">boost/call_traits.hpp</a>></h1>
|
||||||
|
|
||||||
|
<p>All of the contents of <boost/call_traits.hpp> are
|
||||||
|
defined inside namespace boost.</p>
|
||||||
|
|
||||||
|
<p>The template class call_traits<T> encapsulates the
|
||||||
|
"best" method to pass a parameter of some type T to or
|
||||||
|
from a function, and consists of a collection of typedefs defined
|
||||||
|
as in the table below. The purpose of call_traits is to ensure
|
||||||
|
that problems like "<a href="#refs">references to references</a>"
|
||||||
|
never occur, and that parameters are passed in the most efficient
|
||||||
|
manner possible (see <a href="#examples">examples</a>). In each
|
||||||
|
case if your existing practice is to use the type defined on the
|
||||||
|
left, then replace it with the call_traits defined type on the
|
||||||
|
right. </p>
|
||||||
|
|
||||||
|
<p>Note that for compilers that do not support either partial
|
||||||
|
specialization or member templates, no benefit will occur from
|
||||||
|
using call_traits: the call_traits defined types will always be
|
||||||
|
the same as the existing practice in this case. In addition if
|
||||||
|
only member templates and not partial template specialisation is
|
||||||
|
support by the compiler (for example Visual C++ 6) then
|
||||||
|
call_traits can not be used with array types (although it can be
|
||||||
|
used to solve the reference to reference problem).</p>
|
||||||
|
|
||||||
|
<table border="0" cellpadding="7" cellspacing="1" width="797">
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#008080"><p
|
||||||
|
align="center">Existing practice</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="35%" bgcolor="#008080"><p
|
||||||
|
align="center">call_traits equivalent</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="32%" bgcolor="#008080"><p
|
||||||
|
align="center">Description</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="16%" bgcolor="#008080"><p
|
||||||
|
align="center">Notes</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%"><p align="center">T<br>
|
||||||
|
(return by value)</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::value_type</code></p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="32%">Defines a type that
|
||||||
|
represents the "value" of type T. Use this for
|
||||||
|
functions that return by value, or possibly for stored
|
||||||
|
values of type T.</td>
|
||||||
|
<td valign="top" width="16%"><p align="center">2</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%"><p align="center">T&<br>
|
||||||
|
(return value)</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::reference</code></p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="32%">Defines a type that
|
||||||
|
represents a reference to type T. Use for functions that
|
||||||
|
would normally return a T&.</td>
|
||||||
|
<td valign="top" width="16%"><p align="center">1</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%"><p align="center">const
|
||||||
|
T&<br>
|
||||||
|
(return value)</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::const_reference</code></p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="32%">Defines a type that
|
||||||
|
represents a constant reference to type T. Use for
|
||||||
|
functions that would normally return a const T&.</td>
|
||||||
|
<td valign="top" width="16%"><p align="center">1</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%"><p align="center">const
|
||||||
|
T&<br>
|
||||||
|
(function parameter)</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::param_type</code></p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="32%">Defines a type that
|
||||||
|
represents the "best" way to pass a parameter
|
||||||
|
of type T to a function.</td>
|
||||||
|
<td valign="top" width="16%"><p align="center">1,3</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p>Notes:</p>
|
||||||
|
|
||||||
|
<ol>
|
||||||
|
<li>If T is already reference type, then call_traits is
|
||||||
|
defined such that <a href="#refs">references to
|
||||||
|
references</a> do not occur (requires partial
|
||||||
|
specialization).</li>
|
||||||
|
<li>If T is an array type, then call_traits defines <code>value_type</code>
|
||||||
|
as a "constant pointer to type" rather than an
|
||||||
|
"array of type" (requires partial
|
||||||
|
specialization). Note that if you are using value_type as
|
||||||
|
a stored value then this will result in storing a "constant
|
||||||
|
pointer to an array" rather than the array itself.
|
||||||
|
This may or may not be a good thing depending upon what
|
||||||
|
you actually need (in other words take care!).</li>
|
||||||
|
<li>If T is a small built in type or a pointer, then <code>param_type</code>
|
||||||
|
is defined as <code>T const</code>, instead of <code>T
|
||||||
|
const&</code>. This can improve the ability of the
|
||||||
|
compiler to optimize loops in the body of the function if
|
||||||
|
they depend upon the passed parameter, the semantics of
|
||||||
|
the passed parameter is otherwise unchanged (requires
|
||||||
|
partial specialization).</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<h3>Copy constructibility</h3>
|
||||||
|
|
||||||
|
<p>The following table defines which call_traits types can always
|
||||||
|
be copy-constructed from which other types, those entries marked
|
||||||
|
with a '?' are true only if and only if T is copy constructible:</p>
|
||||||
|
|
||||||
|
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%"> </td>
|
||||||
|
<td valign="top" colspan="5" width="85%"
|
||||||
|
bgcolor="#008080"><p align="center">To:</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#008080">From:</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">T</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">value_type</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">reference</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">const_reference</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">param_type</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">?</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">?</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">?</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">?</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">N</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">N</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">?</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">?</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">?</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">N</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">N</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">?</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">?</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">N</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">N</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p>If T is an assignable type the following assignments are
|
||||||
|
possible:</p>
|
||||||
|
|
||||||
|
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%"> </td>
|
||||||
|
<td valign="top" colspan="5" width="85%"
|
||||||
|
bgcolor="#008080"><p align="center">To:</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#008080">From:</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">T</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">value_type</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">reference</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">const_reference</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">param_type</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">Y</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">-</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<h3><a name="examples"></a>Examples</h3>
|
||||||
|
|
||||||
|
<p>The following table shows the effect that call_traits has on
|
||||||
|
various types, the table assumes that the compiler supports
|
||||||
|
partial specialization: if it doesn't then all types behave in
|
||||||
|
the same way as the entry for "myclass", and
|
||||||
|
call_traits can not be used with reference or array types.</p>
|
||||||
|
|
||||||
|
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%"> </td>
|
||||||
|
<td valign="top" colspan="5" width="85%"
|
||||||
|
bgcolor="#008080"><p align="center">Call_traits type:</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#008080"><p
|
||||||
|
align="center">Original type T</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">value_type</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">reference</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">const_reference</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">param_type</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">Applies to:</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">myclass</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">myclass</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">myclass&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const
|
||||||
|
myclass&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">myclass
|
||||||
|
const&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">All user
|
||||||
|
defined types.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">int</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">int</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">int&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const
|
||||||
|
int&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">int const</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">All small
|
||||||
|
built-in types.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">int*</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">int*</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">int*&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">int*const&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">int* const</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">All
|
||||||
|
pointer types.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">int&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">int&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">int&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const
|
||||||
|
int&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">int&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">All
|
||||||
|
reference types.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">const int&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const
|
||||||
|
int&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const
|
||||||
|
int&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const
|
||||||
|
int&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const
|
||||||
|
int&</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">All
|
||||||
|
constant-references.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">int[3]</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const int*</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">int(&)[3]</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const int(&)[3]</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const int*
|
||||||
|
const</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">All array
|
||||||
|
types.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
|
align="center">const int[3]</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const int*</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const int(&)[3]</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const int(&)[3]</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">const int*
|
||||||
|
const</p>
|
||||||
|
</td>
|
||||||
|
<td valign="top" width="17%"><p align="center">All
|
||||||
|
constant-array types.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<h4>Example 1:</h4>
|
||||||
|
|
||||||
|
<p>The following class is a trivial class that stores some type T
|
||||||
|
by value (see the <a href="call_traits_test.cpp">call_traits_test.cpp</a>
|
||||||
|
file), the aim is to illustrate how each of the available
|
||||||
|
call_traits typedefs may be used:</p>
|
||||||
|
|
||||||
|
<pre>template <class T>
|
||||||
|
struct contained
|
||||||
|
{
|
||||||
|
// define our typedefs first, arrays are stored by value
|
||||||
|
// so value_type is not the same as result_type:
|
||||||
|
typedef typename boost::call_traits<T>::param_type param_type;
|
||||||
|
typedef typename boost::call_traits<T>::reference reference;
|
||||||
|
typedef typename boost::call_traits<T>::const_reference const_reference;
|
||||||
|
typedef T value_type;
|
||||||
|
typedef typename boost::call_traits<T>::value_type result_type;
|
||||||
|
|
||||||
|
// stored value:
|
||||||
|
value_type v_;
|
||||||
|
|
||||||
|
// constructors:
|
||||||
|
contained() {}
|
||||||
|
contained(param_type p) : v_(p){}
|
||||||
|
// return byval:
|
||||||
|
result_type value() { return v_; }
|
||||||
|
// return by_ref:
|
||||||
|
reference get() { return v_; }
|
||||||
|
const_reference const_get()const { return v_; }
|
||||||
|
// pass value:
|
||||||
|
void call(param_type p){}
|
||||||
|
|
||||||
|
};</pre>
|
||||||
|
|
||||||
|
<h4><a name="refs"></a>Example 2 (the reference to reference
|
||||||
|
problem):</h4>
|
||||||
|
|
||||||
|
<p>Consider the definition of std::binder1st:</p>
|
||||||
|
|
||||||
|
<pre>template <class Operation>
|
||||||
|
class binder1st :
|
||||||
|
public unary_function<typename Operation::second_argument_type, typename Operation::result_type>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
Operation op;
|
||||||
|
typename Operation::first_argument_type value;
|
||||||
|
public:
|
||||||
|
binder1st(const Operation& x, const typename Operation::first_argument_type& y);
|
||||||
|
typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const;
|
||||||
|
}; </pre>
|
||||||
|
|
||||||
|
<p>Now consider what happens in the relatively common case that
|
||||||
|
the functor takes its second argument as a reference, that
|
||||||
|
implies that <code>Operation::second_argument_type</code> is a
|
||||||
|
reference type, <code>operator()</code> will now end up taking a
|
||||||
|
reference to a reference as an argument, and that is not
|
||||||
|
currently legal. The solution here is to modify <code>operator()</code>
|
||||||
|
to use call_traits:</p>
|
||||||
|
|
||||||
|
<pre>typename Operation::result_type operator()(typename call_traits<typename Operation::second_argument_type>::param_type x) const;</pre>
|
||||||
|
|
||||||
|
<p>Now in the case that <code>Operation::second_argument_type</code>
|
||||||
|
is a reference type, the argument is passed as a reference, and
|
||||||
|
the no "reference to reference" occurs.</p>
|
||||||
|
|
||||||
|
<h4><a name="ex3"></a>Example 3 (the make_pair problem):</h4>
|
||||||
|
|
||||||
|
<p>If we pass the name of an array as one (or both) arguments to <code>std::make_pair</code>,
|
||||||
|
then template argument deduction deduces the passed parameter as
|
||||||
|
"const reference to array of T", this also applies to
|
||||||
|
string literals (which are really array literals). Consequently
|
||||||
|
instead of returning a pair of pointers, it tries to return a
|
||||||
|
pair of arrays, and since an array type is not copy-constructible
|
||||||
|
the code fails to compile. One solution is to explicitly cast the
|
||||||
|
arguments to make_pair to pointers, but call_traits provides a
|
||||||
|
better (i.e. automatic) solution (and one that works safely even
|
||||||
|
in generic code where the cast might do the wrong thing):</p>
|
||||||
|
|
||||||
|
<pre>template <class T1, class T2>
|
||||||
|
std::pair<
|
||||||
|
typename boost::call_traits<T1>::value_type,
|
||||||
|
typename boost::call_traits<T2>::value_type>
|
||||||
|
make_pair(const T1& t1, const T2& t2)
|
||||||
|
{
|
||||||
|
return std::pair<
|
||||||
|
typename boost::call_traits<T1>::value_type,
|
||||||
|
typename boost::call_traits<T2>::value_type>(t1, t2);
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<p>Here, the deduced argument types will be automatically
|
||||||
|
degraded to pointers if the deduced types are arrays, similar
|
||||||
|
situations occur in the standard binders and adapters: in
|
||||||
|
principle in any function that "wraps" a temporary
|
||||||
|
whose type is deduced. Note that the function arguments to
|
||||||
|
make_pair are not expressed in terms of call_traits: doing so
|
||||||
|
would prevent template argument deduction from functioning.</p>
|
||||||
|
|
||||||
|
<h4><a name="ex4"></a>Example 4 (optimising fill):</h4>
|
||||||
|
|
||||||
|
<p>The call_traits template will "optimize" the passing
|
||||||
|
of a small built-in type as a function parameter, this mainly has
|
||||||
|
an effect when the parameter is used within a loop body. In the
|
||||||
|
following example (see <a href="algo_opt_examples.cpp">algo_opt_examples.cpp</a>),
|
||||||
|
a version of std::fill is optimized in two ways: if the type
|
||||||
|
passed is a single byte built-in type then std::memset is used to
|
||||||
|
effect the fill, otherwise a conventional C++ implemention is
|
||||||
|
used, but with the passed parameter "optimized" using
|
||||||
|
call_traits:</p>
|
||||||
|
|
||||||
|
<pre>namespace detail{
|
||||||
|
|
||||||
|
template <bool opt>
|
||||||
|
struct filler
|
||||||
|
{
|
||||||
|
template <typename I, typename T>
|
||||||
|
static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val);
|
||||||
|
{
|
||||||
|
while(first != last)
|
||||||
|
{
|
||||||
|
*first = val;
|
||||||
|
++first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct filler<true>
|
||||||
|
{
|
||||||
|
template <typename I, typename T>
|
||||||
|
static void do_fill(I first, I last, T val)
|
||||||
|
{
|
||||||
|
memset(first, val, last-first);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class I, class T>
|
||||||
|
inline void fill(I first, I last, const T& val)
|
||||||
|
{
|
||||||
|
enum{ can_opt = boost::is_pointer<I>::value
|
||||||
|
&& boost::is_arithmetic<T>::value
|
||||||
|
&& (sizeof(T) == 1) };
|
||||||
|
typedef detail::filler<can_opt> filler_t;
|
||||||
|
filler_t::template do_fill<I,T>(first, last, val);
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<p>Footnote: the reason that this is "optimal" for
|
||||||
|
small built-in types is that with the value passed as "T
|
||||||
|
const" instead of "const T&" the compiler is
|
||||||
|
able to tell both that the value is constant and that it is free
|
||||||
|
of aliases. With this information the compiler is able to cache
|
||||||
|
the passed value in a register, unroll the loop, or use
|
||||||
|
explicitly parallel instructions: if any of these are supported.
|
||||||
|
Exactly how much mileage you will get from this depends upon your
|
||||||
|
compiler - we could really use some accurate benchmarking
|
||||||
|
software as part of boost for cases like this.</p>
|
||||||
|
|
||||||
|
<p>Note that the function arguments to fill are not expressed in
|
||||||
|
terms of call_traits: doing so would prevent template argument
|
||||||
|
deduction from functioning. Instead fill acts as a "thin
|
||||||
|
wrapper" that is there to perform template argument
|
||||||
|
deduction, the compiler will optimise away the call to fill all
|
||||||
|
together, replacing it with the call to filler<>::do_fill,
|
||||||
|
which does use call_traits.</p>
|
||||||
|
|
||||||
|
<h3>Rationale</h3>
|
||||||
|
|
||||||
|
<p>The following notes are intended to briefly describe the
|
||||||
|
rational behind choices made in call_traits.</p>
|
||||||
|
|
||||||
|
<p>All user-defined types follow "existing practice"
|
||||||
|
and need no comment.</p>
|
||||||
|
|
||||||
|
<p>Small built-in types (what the standard calls fundamental
|
||||||
|
types [3.9.1]) differ from existing practice only in the <i>param_type</i>
|
||||||
|
typedef. In this case passing "T const" is compatible
|
||||||
|
with existing practice, but may improve performance in some cases
|
||||||
|
(see <a href="#ex4">Example 4</a>), in any case this should never
|
||||||
|
be any worse than existing practice.</p>
|
||||||
|
|
||||||
|
<p>Pointers follow the same rational as small built-in types.</p>
|
||||||
|
|
||||||
|
<p>For reference types the rational follows <a href="#refs">Example
|
||||||
|
2</a> - references to references are not allowed, so the
|
||||||
|
call_traits members must be defined such that these problems do
|
||||||
|
not occur. There is a proposal to modify the language such that
|
||||||
|
"a reference to a reference is a reference" (issue #106,
|
||||||
|
submitted by Bjarne Stroustrup), call_traits<T>::value_type
|
||||||
|
and call_traits<T>::param_type both provide the same effect
|
||||||
|
as that proposal, without the need for a language change (in
|
||||||
|
other words it's a workaround).</p>
|
||||||
|
|
||||||
|
<p>For array types, a function that takes an array as an argument
|
||||||
|
will degrade the array type to a pointer type: this means that
|
||||||
|
the type of the actual parameter is different from its declared
|
||||||
|
type, something that can cause endless problems in template code
|
||||||
|
that relies on the declared type of a parameter. For example:</p>
|
||||||
|
|
||||||
|
<pre>template <class T>
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
void foo(T t);
|
||||||
|
};</pre>
|
||||||
|
|
||||||
|
<p><font face="Times New Roman">In this case if we instantiate
|
||||||
|
A<int[2]> then the declared type of the parameter passed to
|
||||||
|
member function foo is int[2], but it's actual type is const int*,
|
||||||
|
if we try to use the type T within the function body, then there
|
||||||
|
is a strong likelyhood that our code will not compile:</font></p>
|
||||||
|
|
||||||
|
<pre>template <class T>
|
||||||
|
void A<T>::foo(T t)
|
||||||
|
{
|
||||||
|
T dup(t); // doesn't compile for case that T is an array.
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<p>By using call_traits the degradation from array to pointer is
|
||||||
|
explicit, and the type of the parameter is the same as it's
|
||||||
|
declared type:</p>
|
||||||
|
|
||||||
|
<pre>template <class T>
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
void foo(typename call_traits<T>::value_type t);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void A<T>::foo(typename call_traits<T>::value_type t)
|
||||||
|
{
|
||||||
|
typename call_traits<T>::value_type dup(t); // OK even if T is an array type.
|
||||||
|
}</pre>
|
||||||
|
|
||||||
|
<p>For value_type (return by value), again only a pointer may be
|
||||||
|
returned, not a copy of the whole array, and again call_traits
|
||||||
|
makes the degradation explicit. The value_type member is useful
|
||||||
|
whenever an array must be explicitly degraded to a pointer - <a
|
||||||
|
href="#ex3">Example 3</a> provides the test case (Footnote: the
|
||||||
|
array specialisation for call_traits is the least well understood
|
||||||
|
of all the call_traits specialisations, if the given semantics
|
||||||
|
cause specific problems for you, or don't solve a particular
|
||||||
|
array-related problem, then I would be interested to hear about
|
||||||
|
it. Most people though will probably never need to use this
|
||||||
|
specialisation).</p>
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<p>Revised 01 September 2000</p>
|
||||||
|
|
||||||
|
<p><EFBFBD> Copyright boost.org 2000. Permission to copy, use, modify,
|
||||||
|
sell and distribute this document is granted provided this
|
||||||
|
copyright notice appears in all copies. This document is provided
|
||||||
|
"as is" without express or implied warranty, and with
|
||||||
|
no claim as to its suitability for any purpose.</p>
|
||||||
|
|
||||||
|
<p>Based on contributions by Steve Cleary, Beman Dawes, Howard
|
||||||
|
Hinnant and John Maddock.</p>
|
||||||
|
|
||||||
|
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
|
||||||
|
Maddock</a>, the latest version of this file can be found at <a
|
||||||
|
href="http://www.boost.org/">www.boost.org</a>, and the boost
|
||||||
|
discussion list at <a href="http://www.egroups.com/list/boost">www.egroups.com/list/boost</a>.</p>
|
||||||
|
|
||||||
|
<p>.</p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
|
||||||
|
<p> </p>
|
||||||
|
</body>
|
||||||
|
</html>
|
366
half_open_range_test.cpp
Normal file
366
half_open_range_test.cpp
Normal file
@@ -0,0 +1,366 @@
|
|||||||
|
// (C) Copyright David Abrahams 2001. 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.
|
||||||
|
//
|
||||||
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
//
|
||||||
|
// Revision History
|
||||||
|
// 11 Feb 2001 Compile with Borland, re-enable failing tests (David Abrahams)
|
||||||
|
// 29 Jan 2001 Initial revision (David Abrahams)
|
||||||
|
|
||||||
|
#include <boost/half_open_range.hpp>
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
#include <iterator>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
#include <cassert>
|
||||||
|
#include <stdexcept>
|
||||||
|
#ifndef BOOST_NO_LIMITS
|
||||||
|
# include <limits>
|
||||||
|
#endif
|
||||||
|
#ifndef BOOST_NO_SLIST
|
||||||
|
# include <slist>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline unsigned unsigned_random(unsigned max)
|
||||||
|
{
|
||||||
|
return (max > 0) ? (unsigned)rand() % max : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special tests for ranges supporting random access
|
||||||
|
template <class T>
|
||||||
|
void category_test_1(
|
||||||
|
const boost::half_open_range<T>& r, std::random_access_iterator_tag)
|
||||||
|
{
|
||||||
|
typedef boost::half_open_range<T> range;
|
||||||
|
typedef typename range::size_type size_type;
|
||||||
|
size_type size = r.size();
|
||||||
|
|
||||||
|
// pick a random offset
|
||||||
|
size_type offset = unsigned_random(size);
|
||||||
|
|
||||||
|
typename range::value_type x = *(r.begin() + offset);
|
||||||
|
// test contains(value_type)
|
||||||
|
assert(r.contains(r.start()) == !r.empty());
|
||||||
|
assert(!r.contains(r.finish()));
|
||||||
|
assert(r.contains(x) == (offset != size));
|
||||||
|
|
||||||
|
range::const_iterator p = r.find(x);
|
||||||
|
assert((p == r.end()) == (x == r.finish()));
|
||||||
|
assert(r.find(r.finish()) == r.end());
|
||||||
|
|
||||||
|
if (offset != size)
|
||||||
|
{
|
||||||
|
assert(x == r[offset]);
|
||||||
|
assert(x == r.at(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool caught_out_of_range = false;
|
||||||
|
try {
|
||||||
|
bool never_initialized = x == r.at(size);
|
||||||
|
(void)never_initialized;
|
||||||
|
}
|
||||||
|
catch(std::out_of_range&)
|
||||||
|
{
|
||||||
|
caught_out_of_range = true;
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
assert(caught_out_of_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Those tests must be skipped for other ranges
|
||||||
|
template <class T>
|
||||||
|
void category_test_1(
|
||||||
|
const boost::half_open_range<T>&, std::forward_iterator_tag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned indices[][2] = { {0,0},{0,1},{0,2},{0,3},
|
||||||
|
{1,1},{1,2},{1,3},
|
||||||
|
{2,2},{2,3},
|
||||||
|
{3,3}};
|
||||||
|
|
||||||
|
template <class Range>
|
||||||
|
void category_test_2(
|
||||||
|
const std::vector<Range>& ranges, unsigned i, unsigned j, std::random_access_iterator_tag)
|
||||||
|
{
|
||||||
|
typedef Range range;
|
||||||
|
const range& ri = ranges[i];
|
||||||
|
const range& rj = ranges[j];
|
||||||
|
|
||||||
|
if (indices[i][0] <= indices[j][0] && indices[i][1] >= indices[j][1])
|
||||||
|
assert(ri.contains(rj));
|
||||||
|
|
||||||
|
if (ri.contains(rj))
|
||||||
|
assert((ri & rj) == rj);
|
||||||
|
assert(boost::intersects(ri, rj) == !(ri & rj).empty());
|
||||||
|
|
||||||
|
range t1(ri);
|
||||||
|
t1 &= rj;
|
||||||
|
assert(t1 == range(indices[i][0] > indices[j][0] ? ri.start() : rj.start(),
|
||||||
|
indices[i][1] < indices[j][1] ? ri.finish() : rj.finish()));
|
||||||
|
assert(t1 == (ri & rj));
|
||||||
|
|
||||||
|
range t2(ri);
|
||||||
|
t2 |= rj;
|
||||||
|
|
||||||
|
if (ri.empty())
|
||||||
|
assert(t2 == rj);
|
||||||
|
else if (rj.empty())
|
||||||
|
assert(t2 == ri);
|
||||||
|
else
|
||||||
|
assert(t2 == range(indices[i][0] < indices[j][0] ? ri.start() : rj.start(),
|
||||||
|
indices[i][1] > indices[j][1] ? ri.finish() : rj.finish()));
|
||||||
|
assert(t2 == (ri | rj));
|
||||||
|
if (i == j)
|
||||||
|
assert(ri == rj);
|
||||||
|
|
||||||
|
if (ri.empty() || rj.empty())
|
||||||
|
assert((ri == rj) == (ri.empty() && rj.empty()));
|
||||||
|
else
|
||||||
|
assert((ri == rj) == (ri.start() == rj.start() && ri.finish() == rj.finish()));
|
||||||
|
|
||||||
|
assert((ri == rj) == !(ri != rj));
|
||||||
|
|
||||||
|
bool same = ri == rj;
|
||||||
|
bool one_empty = ri.empty() != rj.empty();
|
||||||
|
|
||||||
|
std::less<range> less;
|
||||||
|
std::less_equal<range> less_equal;
|
||||||
|
std::greater<range> greater;
|
||||||
|
std::greater_equal<range> greater_equal;
|
||||||
|
|
||||||
|
if (same)
|
||||||
|
{
|
||||||
|
assert(greater_equal(ri,rj));
|
||||||
|
assert(less_equal(ri,rj));
|
||||||
|
assert(!greater(ri,rj));
|
||||||
|
assert(!less(ri,rj));
|
||||||
|
}
|
||||||
|
else if (one_empty)
|
||||||
|
{
|
||||||
|
const range& empty = ri.empty() ? ri : rj;
|
||||||
|
const range& non_empty = rj.empty() ? ri : rj;
|
||||||
|
|
||||||
|
assert(less(empty,non_empty));
|
||||||
|
assert(less_equal(empty,non_empty));
|
||||||
|
assert(!greater(empty,non_empty));
|
||||||
|
assert(!greater_equal(empty,non_empty));
|
||||||
|
assert(!less(non_empty,empty));
|
||||||
|
assert(!less_equal(non_empty,empty));
|
||||||
|
assert(greater(non_empty,empty));
|
||||||
|
assert(greater_equal(non_empty,empty));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (indices[i][0] < indices[j][0] ||
|
||||||
|
indices[i][0] == indices[j][0] && indices[i][1] < indices[j][1])
|
||||||
|
{
|
||||||
|
assert(!greater_equal(ri,rj));
|
||||||
|
assert(less(ri,rj));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indices[i][0] < indices[j][0] ||
|
||||||
|
indices[i][0] == indices[j][0] && indices[i][1] <= indices[j][1])
|
||||||
|
{
|
||||||
|
assert(!greater(ri,rj));
|
||||||
|
assert(less_equal(ri,rj));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indices[i][0] > indices[j][0] ||
|
||||||
|
indices[i][0] == indices[j][0] && indices[i][1] > indices[j][1])
|
||||||
|
{
|
||||||
|
assert(!less_equal(ri,rj));
|
||||||
|
assert(greater(ri,rj));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indices[i][0] > indices[j][0] ||
|
||||||
|
indices[i][0] == indices[j][0] && indices[i][1] >= indices[j][1])
|
||||||
|
{
|
||||||
|
assert(!less(ri,rj));
|
||||||
|
assert(greater_equal(ri,rj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class Range>
|
||||||
|
void category_test_2(
|
||||||
|
const std::vector<Range>&, unsigned, unsigned, std::forward_iterator_tag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void category_test_2(
|
||||||
|
const std::vector<boost::half_open_range<T> >&, unsigned, unsigned, std::bidirectional_iterator_tag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Range>
|
||||||
|
void test_back(Range& x, std::bidirectional_iterator_tag)
|
||||||
|
{
|
||||||
|
assert(x.back() == boost::prior(x.finish()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Range>
|
||||||
|
void test_back(Range& x, std::forward_iterator_tag)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
boost::half_open_range<T> range_identity(const boost::half_open_range<T>& x)
|
||||||
|
{
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void test(T x0, T x1, T x2, T x3)
|
||||||
|
{
|
||||||
|
std::vector<boost::half_open_range<T> > ranges;
|
||||||
|
typedef boost::half_open_range<T> range;
|
||||||
|
|
||||||
|
T bounds[4] = { x0, x1, x2, x3 };
|
||||||
|
|
||||||
|
const std::size_t num_ranges = sizeof(indices)/sizeof(*indices);
|
||||||
|
// test construction
|
||||||
|
for (std::size_t n = 0; n < num_ranges;++n)
|
||||||
|
{
|
||||||
|
T start = bounds[indices[n][0]];
|
||||||
|
T finish = bounds[indices[n][1]];
|
||||||
|
boost::half_open_range<T> r(start, finish);
|
||||||
|
ranges.push_back(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test implicit conversion from std::pair<T,T>
|
||||||
|
range converted = std::pair<T,T>(x0,x0);
|
||||||
|
(void)converted;
|
||||||
|
|
||||||
|
// test assignment, equality and inequality
|
||||||
|
range r00 = range(x0, x0);
|
||||||
|
assert(r00 == range(x0,x0));
|
||||||
|
assert(r00 == range(x1,x1)); // empty ranges are all equal
|
||||||
|
if (x3 != x0)
|
||||||
|
assert(r00 != range(x0, x3));
|
||||||
|
r00 = range(x0, x3);
|
||||||
|
assert(r00 == range(x0, x3));
|
||||||
|
if (x3 != x0)
|
||||||
|
assert(r00 != range(x0, x0));
|
||||||
|
|
||||||
|
typedef typename range::iterator iterator;
|
||||||
|
typedef typename iterator::iterator_category category;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < num_ranges; ++i)
|
||||||
|
{
|
||||||
|
const range& r = ranges[i];
|
||||||
|
|
||||||
|
// test begin(), end(), basic iteration.
|
||||||
|
unsigned count = 0;
|
||||||
|
for (range::const_iterator p = r.begin(), finish = r.end();
|
||||||
|
p != finish;
|
||||||
|
++p, ++count)
|
||||||
|
{
|
||||||
|
assert(count < 2100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test size(), empty(), front(), back()
|
||||||
|
assert((unsigned)r.size() == count);
|
||||||
|
if (indices[i][0] == indices[i][1])
|
||||||
|
assert(r.empty());
|
||||||
|
if (r.empty())
|
||||||
|
assert(r.size() == 0);
|
||||||
|
if (!r.empty())
|
||||||
|
{
|
||||||
|
assert(r.front() == r.start());
|
||||||
|
test_back(r, category());
|
||||||
|
}
|
||||||
|
|
||||||
|
// test swap
|
||||||
|
range r1(r);
|
||||||
|
range r2(x0,x3);
|
||||||
|
const bool same = r1 == r2;
|
||||||
|
r1.swap(r2);
|
||||||
|
assert(r1 == range(x0,x3));
|
||||||
|
assert(r2 == r);
|
||||||
|
if (!same) {
|
||||||
|
assert(r1 != r);
|
||||||
|
assert(r2 != range(x0,x3));
|
||||||
|
}
|
||||||
|
|
||||||
|
// do individual tests for random-access iterators
|
||||||
|
category_test_1(r, category());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned j = 0; j < num_ranges; ++j) {
|
||||||
|
for (unsigned k = 0; k < num_ranges; ++k) {
|
||||||
|
category_test_2(ranges, j, k, category());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Integer>
|
||||||
|
void test_integer(Integer* = 0) // default arg works around MSVC bug
|
||||||
|
{
|
||||||
|
Integer a = 0;
|
||||||
|
Integer b = a + unsigned_random(128 - a);
|
||||||
|
Integer c = b + unsigned_random(128 - b);
|
||||||
|
Integer d = c + unsigned_random(128 - c);
|
||||||
|
|
||||||
|
test(a, b, c, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Container>
|
||||||
|
void test_container(Container* = 0) // default arg works around MSVC bug
|
||||||
|
{
|
||||||
|
Container c(unsigned_random(1673));
|
||||||
|
|
||||||
|
const typename Container::size_type offset1 = unsigned_random(c.size());
|
||||||
|
const typename Container::size_type offset2 = unsigned_random(c.size() - offset1);
|
||||||
|
typename Container::iterator internal1 = c.begin();
|
||||||
|
std::advance(internal1, offset1);
|
||||||
|
typename Container::iterator internal2 = internal1;
|
||||||
|
std::advance(internal2, offset2);
|
||||||
|
|
||||||
|
test(c.begin(), internal1, internal2, c.end());
|
||||||
|
|
||||||
|
typedef typename Container::const_iterator const_iterator;
|
||||||
|
test(const_iterator(c.begin()),
|
||||||
|
const_iterator(internal1),
|
||||||
|
const_iterator(internal2),
|
||||||
|
const_iterator(c.end()));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// Test the built-in integer types.
|
||||||
|
test_integer<char>();
|
||||||
|
test_integer<unsigned char>();
|
||||||
|
test_integer<signed char>();
|
||||||
|
test_integer<wchar_t>();
|
||||||
|
test_integer<short>();
|
||||||
|
test_integer<unsigned short>();
|
||||||
|
test_integer<int>();
|
||||||
|
test_integer<unsigned int>();
|
||||||
|
test_integer<long>();
|
||||||
|
test_integer<unsigned long>();
|
||||||
|
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
|
||||||
|
test_integer<long long>();
|
||||||
|
test_integer<unsigned long long>();
|
||||||
|
#endif
|
||||||
|
// Some tests on container iterators, to prove we handle a few different categories
|
||||||
|
test_container<std::vector<int> >();
|
||||||
|
test_container<std::list<int> >();
|
||||||
|
#ifndef BOOST_NO_SLIST
|
||||||
|
test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
|
||||||
|
#endif
|
||||||
|
// Also prove that we can handle raw pointers.
|
||||||
|
int array[2000];
|
||||||
|
const std::size_t a = 0;
|
||||||
|
const std::size_t b = a + unsigned_random(2000 - a);
|
||||||
|
const std::size_t c = b + unsigned_random(2000 - b);
|
||||||
|
test(array, array+b, array+c, array+2000);
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -1,38 +0,0 @@
|
|||||||
//
|
|
||||||
// boost/assert.hpp - BOOST_ASSERT(expr)
|
|
||||||
//
|
|
||||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// Note: There are no include guards. This is intentional.
|
|
||||||
//
|
|
||||||
// See http://www.boost.org/libs/utility/assert.html for documentation.
|
|
||||||
//
|
|
||||||
|
|
||||||
#undef BOOST_ASSERT
|
|
||||||
|
|
||||||
#if defined(BOOST_DISABLE_ASSERTS)
|
|
||||||
|
|
||||||
# define BOOST_ASSERT(expr) ((void)0)
|
|
||||||
|
|
||||||
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
|
|
||||||
|
|
||||||
#include <boost/current_function.hpp>
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
|
|
||||||
void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
|
|
||||||
|
|
||||||
#else
|
|
||||||
# include <assert.h>
|
|
||||||
# define BOOST_ASSERT(expr) assert(expr)
|
|
||||||
#endif
|
|
@@ -1,23 +0,0 @@
|
|||||||
// (C) Copyright Boost.org 2000. 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.
|
|
||||||
|
|
||||||
// See http://www.boost.org/libs/utility/call_traits.htm for Documentation.
|
|
||||||
// See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp
|
|
||||||
// for full copyright notices.
|
|
||||||
|
|
||||||
#ifndef BOOST_CALL_TRAITS_HPP
|
|
||||||
#define BOOST_CALL_TRAITS_HPP
|
|
||||||
|
|
||||||
#ifndef BOOST_CONFIG_HPP
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
#include <boost/detail/ob_call_traits.hpp>
|
|
||||||
#else
|
|
||||||
#include <boost/detail/call_traits.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // BOOST_CALL_TRAITS_HPP
|
|
@@ -1,63 +0,0 @@
|
|||||||
#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
|
|
||||||
#define BOOST_CHECKED_DELETE_HPP_INCLUDED
|
|
||||||
|
|
||||||
#if _MSC_VER >= 1020
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// boost/checked_delete.hpp
|
|
||||||
//
|
|
||||||
// Copyright (c) 1999, 2000, 2001, 2002 boost.org
|
|
||||||
// Copyright (c) 2002, 2003 Peter Dimov
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// See http://www.boost.org/libs/utility/checked_delete.html for documentation.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
|
|
||||||
// verify that types are complete for increased safety
|
|
||||||
|
|
||||||
template<class T> inline void checked_delete(T * x)
|
|
||||||
{
|
|
||||||
typedef char type_must_be_complete[sizeof(T)];
|
|
||||||
delete x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T> inline void checked_array_delete(T * x)
|
|
||||||
{
|
|
||||||
typedef char type_must_be_complete[sizeof(T)];
|
|
||||||
delete [] x;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T> struct checked_deleter
|
|
||||||
{
|
|
||||||
typedef void result_type;
|
|
||||||
typedef T * argument_type;
|
|
||||||
|
|
||||||
void operator()(T * x) const
|
|
||||||
{
|
|
||||||
boost::checked_delete(x);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class T> struct checked_array_deleter
|
|
||||||
{
|
|
||||||
typedef void result_type;
|
|
||||||
typedef T * argument_type;
|
|
||||||
|
|
||||||
void operator()(T * x) const
|
|
||||||
{
|
|
||||||
boost::checked_array_delete(x);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
|
|
@@ -1,23 +0,0 @@
|
|||||||
// (C) Copyright Boost.org 2000. 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.
|
|
||||||
|
|
||||||
// See http://www.boost.org for most recent version including documentation.
|
|
||||||
// See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp
|
|
||||||
// for full copyright notices.
|
|
||||||
|
|
||||||
#ifndef BOOST_COMPRESSED_PAIR_HPP
|
|
||||||
#define BOOST_COMPRESSED_PAIR_HPP
|
|
||||||
|
|
||||||
#ifndef BOOST_CONFIG_HPP
|
|
||||||
#include <boost/config.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
#include <boost/detail/ob_compressed_pair.hpp>
|
|
||||||
#else
|
|
||||||
#include <boost/detail/compressed_pair.hpp>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // BOOST_COMPRESSED_PAIR_HPP
|
|
@@ -1,62 +0,0 @@
|
|||||||
#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
|
||||||
#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
|
||||||
|
|
||||||
#if _MSC_VER >= 1020
|
|
||||||
#pragma once
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// boost/current_function.hpp - BOOST_CURRENT_FUNCTION
|
|
||||||
//
|
|
||||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// http://www.boost.org/libs/utility/current_function.html
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
|
|
||||||
inline void current_function_helper()
|
|
||||||
{
|
|
||||||
|
|
||||||
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600))
|
|
||||||
|
|
||||||
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
|
|
||||||
|
|
||||||
#elif defined(__FUNCSIG__)
|
|
||||||
|
|
||||||
# define BOOST_CURRENT_FUNCTION __FUNCSIG__
|
|
||||||
|
|
||||||
#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
|
|
||||||
|
|
||||||
# define BOOST_CURRENT_FUNCTION __FUNCTION__
|
|
||||||
|
|
||||||
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
|
|
||||||
|
|
||||||
# define BOOST_CURRENT_FUNCTION __FUNC__
|
|
||||||
|
|
||||||
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
|
|
||||||
|
|
||||||
# define BOOST_CURRENT_FUNCTION __func__
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
# define BOOST_CURRENT_FUNCTION "(unknown)"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
|
@@ -1,75 +0,0 @@
|
|||||||
// (C) Copyright Jens Maurer 2001. 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.
|
|
||||||
//
|
|
||||||
// Revision History:
|
|
||||||
|
|
||||||
// 15 Nov 2001 Jens Maurer
|
|
||||||
// created.
|
|
||||||
|
|
||||||
// See http://www.boost.org/libs/utility/iterator_adaptors.htm for documentation.
|
|
||||||
|
|
||||||
#ifndef BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
|
||||||
#define BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
|
||||||
|
|
||||||
#include <boost/iterator_adaptors.hpp>
|
|
||||||
#include <boost/ref.hpp>
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
template<class Generator>
|
|
||||||
class generator_iterator_policies
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
generator_iterator_policies() { }
|
|
||||||
|
|
||||||
template<class Base>
|
|
||||||
void initialize(Base& base) {
|
|
||||||
m_value = (*base)();
|
|
||||||
}
|
|
||||||
|
|
||||||
// The Iter template argument is necessary for compatibility with a MWCW
|
|
||||||
// bug workaround
|
|
||||||
template <class IteratorAdaptor>
|
|
||||||
void increment(IteratorAdaptor& iter) {
|
|
||||||
m_value = (*iter.base())();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class IteratorAdaptor>
|
|
||||||
const typename Generator::result_type&
|
|
||||||
dereference(const IteratorAdaptor&) const
|
|
||||||
{ return m_value; }
|
|
||||||
|
|
||||||
template <class IteratorAdaptor1, class IteratorAdaptor2>
|
|
||||||
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
|
|
||||||
{ return x.base() == y.base() &&
|
|
||||||
x.policies().m_value == y.policies().m_value; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
typename Generator::result_type m_value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<class Generator>
|
|
||||||
struct generator_iterator_generator
|
|
||||||
{
|
|
||||||
typedef iterator_adaptor<Generator*, generator_iterator_policies<Generator>,
|
|
||||||
typename Generator::result_type, const typename Generator::result_type&,
|
|
||||||
const typename Generator::result_type*, std::input_iterator_tag,
|
|
||||||
long> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class Generator>
|
|
||||||
inline typename generator_iterator_generator<Generator>::type
|
|
||||||
make_generator_iterator(Generator & gen)
|
|
||||||
{
|
|
||||||
typedef typename generator_iterator_generator<Generator>::type result_t;
|
|
||||||
return result_t(&gen);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
|
|
||||||
#endif // BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
|
||||||
|
|
@@ -1,33 +0,0 @@
|
|||||||
// Boost next_prior.hpp header file ---------------------------------------//
|
|
||||||
|
|
||||||
// (C) Copyright Boost.org 1999-2003. 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.
|
|
||||||
|
|
||||||
// See http://www.boost.org/libs/utility for documentation.
|
|
||||||
|
|
||||||
#ifndef BOOST_NEXT_PRIOR_HPP_INCLUDED
|
|
||||||
#define BOOST_NEXT_PRIOR_HPP_INCLUDED
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
// Helper functions for classes like bidirectional iterators not supporting
|
|
||||||
// operator+ and operator-
|
|
||||||
//
|
|
||||||
// Usage:
|
|
||||||
// const std::list<T>::iterator p = get_some_iterator();
|
|
||||||
// const std::list<T>::iterator prev = boost::prior(p);
|
|
||||||
|
|
||||||
// Contributed by Dave Abrahams
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline T next(T x) { return ++x; }
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline T prior(T x) { return --x; }
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // BOOST_NEXT_PRIOR_HPP_INCLUDED
|
|
@@ -1,33 +0,0 @@
|
|||||||
// Boost noncopyable.hpp header file --------------------------------------//
|
|
||||||
|
|
||||||
// (C) Copyright Boost.org 1999-2003. 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.
|
|
||||||
|
|
||||||
// See http://www.boost.org/libs/utility for documentation.
|
|
||||||
|
|
||||||
#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
|
|
||||||
#define BOOST_NONCOPYABLE_HPP_INCLUDED
|
|
||||||
|
|
||||||
namespace boost {
|
|
||||||
|
|
||||||
// Private copy constructor and copy assignment ensure classes derived from
|
|
||||||
// class noncopyable cannot be copied.
|
|
||||||
|
|
||||||
// Contributed by Dave Abrahams
|
|
||||||
|
|
||||||
class noncopyable
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
noncopyable() {}
|
|
||||||
~noncopyable() {}
|
|
||||||
private: // emphasize the following members are private
|
|
||||||
noncopyable( const noncopyable& );
|
|
||||||
const noncopyable& operator=( const noncopyable& );
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // BOOST_NONCOPYABLE_HPP_INCLUDED
|
|
@@ -1,33 +1,20 @@
|
|||||||
// Boost operators.hpp header file ----------------------------------------//
|
// Boost operators.hpp header file ----------------------------------------//
|
||||||
|
|
||||||
// (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-2001.
|
// (C) Copyright David Abrahams 1999. Permission to copy, use,
|
||||||
// Permission to copy, use, modify, sell and distribute this software is
|
// modify, sell and distribute this software is granted provided this
|
||||||
// granted provided this copyright notice appears in all copies. This
|
// copyright notice appears in all copies. This software is provided
|
||||||
// software is provided "as is" without express or implied warranty, and
|
// "as is" without express or implied warranty, and with no claim as
|
||||||
// with no claim as to its suitability for any purpose.
|
// to its suitability for any purpose.
|
||||||
|
|
||||||
// See http://www.boost.org/libs/utility/operators.htm for documentation.
|
// (C) Copyright Jeremy Siek 1999. 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.
|
||||||
|
|
||||||
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
// Revision History
|
// Revision History
|
||||||
// 04 May 05 Added operator class bool_testable. (Sam Partington)
|
|
||||||
// 21 Oct 02 Modified implementation of operators to allow compilers with a
|
|
||||||
// correct named return value optimization (NRVO) to produce optimal
|
|
||||||
// code. (Daniel Frey)
|
|
||||||
// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
|
|
||||||
// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
|
|
||||||
// 27 Aug 01 'left' form for non commutative operators added;
|
|
||||||
// additional classes for groups of related operators added;
|
|
||||||
// workaround for empty base class optimization
|
|
||||||
// bug of GCC 3.0 (Helmut Zeisel)
|
|
||||||
// 25 Jun 01 output_iterator_helper changes: removed default template
|
|
||||||
// parameters, added support for self-proxying, additional
|
|
||||||
// documentation and tests (Aleksey Gurtovoy)
|
|
||||||
// 29 May 01 Added operator classes for << and >>. Added input and output
|
|
||||||
// iterator helper classes. Added classes to connect equality and
|
|
||||||
// relational operators. Added classes for groups of related
|
|
||||||
// operators. Reimplemented example operator and iterator helper
|
|
||||||
// classes in terms of the new groups. (Daryle Walker, with help
|
|
||||||
// from Alexy Gurtovoy)
|
|
||||||
// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
|
// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
|
||||||
// supplied arguments from actually being used (Dave Abrahams)
|
// supplied arguments from actually being used (Dave Abrahams)
|
||||||
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
|
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
|
||||||
@@ -79,7 +66,6 @@
|
|||||||
|
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp>
|
||||||
#include <boost/iterator.hpp>
|
#include <boost/iterator.hpp>
|
||||||
#include <boost/preprocessor/seq/cat.hpp>
|
|
||||||
|
|
||||||
#if defined(__sgi) && !defined(__GNUC__)
|
#if defined(__sgi) && !defined(__GNUC__)
|
||||||
#pragma set woff 1234
|
#pragma set woff 1234
|
||||||
@@ -92,14 +78,7 @@
|
|||||||
namespace boost {
|
namespace boost {
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
// Helmut Zeisel, empty base class optimization bug with GCC 3.0.0
|
|
||||||
#if defined(__GNUC__) && __GNUC__==3 && __GNUC_MINOR__==0 && __GNU_PATCHLEVEL__==0
|
|
||||||
class empty_base {
|
|
||||||
bool dummy;
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
class empty_base {};
|
class empty_base {};
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
@@ -154,112 +133,106 @@ struct equality_comparable1 : B
|
|||||||
friend bool operator!=(const T& x, const T& y) { return !(x == y); }
|
friend bool operator!=(const T& x, const T& y) { return !(x == y); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// A macro which produces "name_2left" from "name".
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
#define BOOST_OPERATOR2_LEFT(name) BOOST_PP_SEQ_CAT_S(1,(name)(2)(_)(left))
|
struct multipliable2 : B
|
||||||
|
{
|
||||||
// NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
|
friend T operator*(T x, const U& y) { return x *= y; }
|
||||||
|
friend T operator*(const U& y, T x) { return x *= y; }
|
||||||
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
|
||||||
|
|
||||||
// This is the optimal implementation for ISO/ANSI C++,
|
|
||||||
// but it requires the compiler to implement the NRVO.
|
|
||||||
// If the compiler has no NRVO, this is the best symmetric
|
|
||||||
// implementation available.
|
|
||||||
|
|
||||||
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
|
||||||
struct NAME##2 : B \
|
|
||||||
{ \
|
|
||||||
friend T operator OP( const T& lhs, const U& rhs ) \
|
|
||||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
|
||||||
friend T operator OP( const U& lhs, const T& rhs ) \
|
|
||||||
{ T nrv( rhs ); nrv OP##= lhs; return nrv; } \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
template <class T, class B = ::boost::detail::empty_base> \
|
|
||||||
struct NAME##1 : B \
|
|
||||||
{ \
|
|
||||||
friend T operator OP( const T& lhs, const T& rhs ) \
|
|
||||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
struct multipliable1 : B
|
||||||
struct NAME##2 : B \
|
{
|
||||||
{ \
|
friend T operator*(T x, const T& y) { return x *= y; }
|
||||||
friend T operator OP( const T& lhs, const U& rhs ) \
|
|
||||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
|
||||||
struct BOOST_OPERATOR2_LEFT(NAME) : B \
|
|
||||||
{ \
|
|
||||||
friend T operator OP( const U& lhs, const T& rhs ) \
|
|
||||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
template <class T, class B = ::boost::detail::empty_base> \
|
|
||||||
struct NAME##1 : B \
|
|
||||||
{ \
|
|
||||||
friend T operator OP( const T& lhs, const T& rhs ) \
|
|
||||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct addable2 : B
|
||||||
// For compilers without NRVO the following code is optimal, but not
|
{
|
||||||
// symmetric! Note that the implementation of
|
friend T operator+(T x, const U& y) { return x += y; }
|
||||||
// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
|
friend T operator+(const U& y, T x) { return x += y; }
|
||||||
// optimization opportunities to the compiler :)
|
|
||||||
|
|
||||||
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
|
||||||
struct NAME##2 : B \
|
|
||||||
{ \
|
|
||||||
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
|
|
||||||
friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
template <class T, class B = ::boost::detail::empty_base> \
|
|
||||||
struct NAME##1 : B \
|
|
||||||
{ \
|
|
||||||
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
struct addable1 : B
|
||||||
struct NAME##2 : B \
|
{
|
||||||
{ \
|
friend T operator+(T x, const T& y) { return x += y; }
|
||||||
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
|
||||||
struct BOOST_OPERATOR2_LEFT(NAME) : B \
|
|
||||||
{ \
|
|
||||||
friend T operator OP( const U& lhs, const T& rhs ) \
|
|
||||||
{ return T( lhs ) OP##= rhs; } \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
template <class T, class B = ::boost::detail::empty_base> \
|
|
||||||
struct NAME##1 : B \
|
|
||||||
{ \
|
|
||||||
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct subtractable2 : B
|
||||||
|
{
|
||||||
|
friend T operator-(T x, const U& y) { return x -= y; }
|
||||||
|
};
|
||||||
|
|
||||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
|
struct subtractable1 : B
|
||||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
|
{
|
||||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
|
friend T operator-(T x, const T& y) { return x -= y; }
|
||||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
|
};
|
||||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
|
|
||||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
|
|
||||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
|
|
||||||
|
|
||||||
#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
|
struct dividable2 : B
|
||||||
#undef BOOST_OPERATOR2_LEFT
|
{
|
||||||
|
friend T operator/(T x, const U& y) { return x /= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct dividable1 : B
|
||||||
|
{
|
||||||
|
friend T operator/(T x, const T& y) { return x /= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct modable2 : B
|
||||||
|
{
|
||||||
|
friend T operator%(T x, const U& y) { return x %= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct modable1 : B
|
||||||
|
{
|
||||||
|
friend T operator%(T x, const T& y) { return x %= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct xorable2 : B
|
||||||
|
{
|
||||||
|
friend T operator^(T x, const U& y) { return x ^= y; }
|
||||||
|
friend T operator^(const U& y, T x) { return x ^= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct xorable1 : B
|
||||||
|
{
|
||||||
|
friend T operator^(T x, const T& y) { return x ^= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct andable2 : B
|
||||||
|
{
|
||||||
|
friend T operator&(T x, const U& y) { return x &= y; }
|
||||||
|
friend T operator&(const U& y, T x) { return x &= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct andable1 : B
|
||||||
|
{
|
||||||
|
friend T operator&(T x, const T& y) { return x &= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||||
|
struct orable2 : B
|
||||||
|
{
|
||||||
|
friend T operator|(T x, const U& y) { return x |= y; }
|
||||||
|
friend T operator|(const U& y, T x) { return x |= y; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, class B = ::boost::detail::empty_base>
|
||||||
|
struct orable1 : B
|
||||||
|
{
|
||||||
|
friend T operator|(T x, const T& y) { return x |= y; }
|
||||||
|
};
|
||||||
|
|
||||||
// incrementable and decrementable contributed by Jeremy Siek
|
// incrementable and decrementable contributed by Jeremy Siek
|
||||||
|
|
||||||
@@ -268,9 +241,9 @@ struct incrementable : B
|
|||||||
{
|
{
|
||||||
friend T operator++(T& x, int)
|
friend T operator++(T& x, int)
|
||||||
{
|
{
|
||||||
incrementable_type nrv(x);
|
incrementable_type tmp(x);
|
||||||
++x;
|
++x;
|
||||||
return nrv;
|
return tmp;
|
||||||
}
|
}
|
||||||
private: // The use of this typedef works around a Borland bug
|
private: // The use of this typedef works around a Borland bug
|
||||||
typedef T incrementable_type;
|
typedef T incrementable_type;
|
||||||
@@ -281,9 +254,9 @@ struct decrementable : B
|
|||||||
{
|
{
|
||||||
friend T operator--(T& x, int)
|
friend T operator--(T& x, int)
|
||||||
{
|
{
|
||||||
decrementable_type nrv(x);
|
decrementable_type tmp(x);
|
||||||
--x;
|
--x;
|
||||||
return nrv;
|
return tmp;
|
||||||
}
|
}
|
||||||
private: // The use of this typedef works around a Borland bug
|
private: // The use of this typedef works around a Borland bug
|
||||||
typedef T decrementable_type;
|
typedef T decrementable_type;
|
||||||
@@ -309,331 +282,12 @@ struct indexable : B
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// bool_testable -----------------------------------------------------------//
|
|
||||||
// (contributed by Sam Partington, David Abrahams and Daniel Frey) ---------//
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct bool_testable : B
|
|
||||||
{
|
|
||||||
friend bool operator!(const T& t) { return !static_cast<bool>(t); }
|
|
||||||
private:
|
|
||||||
typedef signed char private_number_type;
|
|
||||||
operator private_number_type() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
// More operator classes (contributed by Daryle Walker) --------------------//
|
|
||||||
// (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
|
|
||||||
|
|
||||||
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
|
||||||
|
|
||||||
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
|
||||||
struct NAME##2 : B \
|
|
||||||
{ \
|
|
||||||
friend T operator OP( const T& lhs, const U& rhs ) \
|
|
||||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
template <class T, class B = ::boost::detail::empty_base> \
|
|
||||||
struct NAME##1 : B \
|
|
||||||
{ \
|
|
||||||
friend T operator OP( const T& lhs, const T& rhs ) \
|
|
||||||
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
|
|
||||||
};
|
|
||||||
|
|
||||||
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
|
||||||
|
|
||||||
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
|
||||||
struct NAME##2 : B \
|
|
||||||
{ \
|
|
||||||
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
|
|
||||||
}; \
|
|
||||||
\
|
|
||||||
template <class T, class B = ::boost::detail::empty_base> \
|
|
||||||
struct NAME##1 : B \
|
|
||||||
{ \
|
|
||||||
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
|
||||||
|
|
||||||
BOOST_BINARY_OPERATOR( left_shiftable, << )
|
|
||||||
BOOST_BINARY_OPERATOR( right_shiftable, >> )
|
|
||||||
|
|
||||||
#undef BOOST_BINARY_OPERATOR
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct equivalent2 : B
|
|
||||||
{
|
|
||||||
friend bool operator==(const T& x, const U& y)
|
|
||||||
{
|
|
||||||
return !(x < y) && !(x > y);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct equivalent1 : B
|
|
||||||
{
|
|
||||||
friend bool operator==(const T&x, const T&y)
|
|
||||||
{
|
|
||||||
return !(x < y) && !(y < x);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct partially_ordered2 : B
|
|
||||||
{
|
|
||||||
friend bool operator<=(const T& x, const U& y)
|
|
||||||
{ return (x < y) || (x == y); }
|
|
||||||
friend bool operator>=(const T& x, const U& y)
|
|
||||||
{ return (x > y) || (x == y); }
|
|
||||||
friend bool operator>(const U& x, const T& y)
|
|
||||||
{ return y < x; }
|
|
||||||
friend bool operator<(const U& x, const T& y)
|
|
||||||
{ return y > x; }
|
|
||||||
friend bool operator<=(const U& x, const T& y)
|
|
||||||
{ return (y > x) || (y == x); }
|
|
||||||
friend bool operator>=(const U& x, const T& y)
|
|
||||||
{ return (y < x) || (y == x); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct partially_ordered1 : B
|
|
||||||
{
|
|
||||||
friend bool operator>(const T& x, const T& y)
|
|
||||||
{ return y < x; }
|
|
||||||
friend bool operator<=(const T& x, const T& y)
|
|
||||||
{ return (x < y) || (x == y); }
|
|
||||||
friend bool operator>=(const T& x, const T& y)
|
|
||||||
{ return (y < x) || (x == y); }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Combined operator classes (contributed by Daryle Walker) ----------------//
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct totally_ordered2
|
|
||||||
: less_than_comparable2<T, U
|
|
||||||
, equality_comparable2<T, U, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct totally_ordered1
|
|
||||||
: less_than_comparable1<T
|
|
||||||
, equality_comparable1<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct additive2
|
|
||||||
: addable2<T, U
|
|
||||||
, subtractable2<T, U, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct additive1
|
|
||||||
: addable1<T
|
|
||||||
, subtractable1<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct multiplicative2
|
|
||||||
: multipliable2<T, U
|
|
||||||
, dividable2<T, U, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct multiplicative1
|
|
||||||
: multipliable1<T
|
|
||||||
, dividable1<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct integer_multiplicative2
|
|
||||||
: multiplicative2<T, U
|
|
||||||
, modable2<T, U, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct integer_multiplicative1
|
|
||||||
: multiplicative1<T
|
|
||||||
, modable1<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct arithmetic2
|
|
||||||
: additive2<T, U
|
|
||||||
, multiplicative2<T, U, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct arithmetic1
|
|
||||||
: additive1<T
|
|
||||||
, multiplicative1<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct integer_arithmetic2
|
|
||||||
: additive2<T, U
|
|
||||||
, integer_multiplicative2<T, U, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct integer_arithmetic1
|
|
||||||
: additive1<T
|
|
||||||
, integer_multiplicative1<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct bitwise2
|
|
||||||
: xorable2<T, U
|
|
||||||
, andable2<T, U
|
|
||||||
, orable2<T, U, B
|
|
||||||
> > > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct bitwise1
|
|
||||||
: xorable1<T
|
|
||||||
, andable1<T
|
|
||||||
, orable1<T, B
|
|
||||||
> > > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct unit_steppable
|
|
||||||
: incrementable<T
|
|
||||||
, decrementable<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct shiftable2
|
|
||||||
: left_shiftable2<T, U
|
|
||||||
, right_shiftable2<T, U, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct shiftable1
|
|
||||||
: left_shiftable1<T
|
|
||||||
, right_shiftable1<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct ring_operators2
|
|
||||||
: additive2<T, U
|
|
||||||
, subtractable2_left<T, U
|
|
||||||
, multipliable2<T, U, B
|
|
||||||
> > > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct ring_operators1
|
|
||||||
: additive1<T
|
|
||||||
, multipliable1<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct ordered_ring_operators2
|
|
||||||
: ring_operators2<T, U
|
|
||||||
, totally_ordered2<T, U, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct ordered_ring_operators1
|
|
||||||
: ring_operators1<T
|
|
||||||
, totally_ordered1<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct field_operators2
|
|
||||||
: ring_operators2<T, U
|
|
||||||
, dividable2<T, U
|
|
||||||
, dividable2_left<T, U, B
|
|
||||||
> > > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct field_operators1
|
|
||||||
: ring_operators1<T
|
|
||||||
, dividable1<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct ordered_field_operators2
|
|
||||||
: field_operators2<T, U
|
|
||||||
, totally_ordered2<T, U, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct ordered_field_operators1
|
|
||||||
: field_operators1<T
|
|
||||||
, totally_ordered1<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct euclidian_ring_operators2
|
|
||||||
: ring_operators2<T, U
|
|
||||||
, dividable2<T, U
|
|
||||||
, dividable2_left<T, U
|
|
||||||
, modable2<T, U
|
|
||||||
, modable2_left<T, U, B
|
|
||||||
> > > > > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct euclidian_ring_operators1
|
|
||||||
: ring_operators1<T
|
|
||||||
, dividable1<T
|
|
||||||
, modable1<T, B
|
|
||||||
> > > {};
|
|
||||||
|
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
|
||||||
struct ordered_euclidian_ring_operators2
|
|
||||||
: totally_ordered2<T, U
|
|
||||||
, euclidian_ring_operators2<T, U, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct ordered_euclidian_ring_operators1
|
|
||||||
: totally_ordered1<T
|
|
||||||
, euclidian_ring_operators1<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
|
||||||
struct input_iteratable
|
|
||||||
: equality_comparable1<T
|
|
||||||
, incrementable<T
|
|
||||||
, dereferenceable<T, P, B
|
|
||||||
> > > {};
|
|
||||||
|
|
||||||
template <class T, class B = ::boost::detail::empty_base>
|
|
||||||
struct output_iteratable
|
|
||||||
: incrementable<T, B
|
|
||||||
> {};
|
|
||||||
|
|
||||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
|
||||||
struct forward_iteratable
|
|
||||||
: input_iteratable<T, P, B
|
|
||||||
> {};
|
|
||||||
|
|
||||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
|
||||||
struct bidirectional_iteratable
|
|
||||||
: forward_iteratable<T, P
|
|
||||||
, decrementable<T, B
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
// To avoid repeated derivation from equality_comparable,
|
|
||||||
// which is an indirect base class of bidirectional_iterable,
|
|
||||||
// random_access_iteratable must not be derived from totally_ordered1
|
|
||||||
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
|
|
||||||
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base>
|
|
||||||
struct random_access_iteratable
|
|
||||||
: bidirectional_iteratable<T, P
|
|
||||||
, less_than_comparable1<T
|
|
||||||
, additive2<T, D
|
|
||||||
, indexable<T, D, R, B
|
|
||||||
> > > > {};
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
|
||||||
|
|
||||||
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 -
|
// BOOST_IMPORT_TEMPLATE1/BOOST_IMPORT_TEMPLATE2 -
|
||||||
//
|
//
|
||||||
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
|
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
|
||||||
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
|
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
|
||||||
@@ -641,37 +295,12 @@ struct random_access_iteratable
|
|||||||
// two-argument forms. Note that these macros expect to be invoked from within
|
// two-argument forms. Note that these macros expect to be invoked from within
|
||||||
// boost.
|
// boost.
|
||||||
|
|
||||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
#if defined(BOOST_NO_OPERATORS_IN_NAMESPACE)
|
||||||
|
|
||||||
// The template is already in boost so we have nothing to do.
|
# if defined(BOOST_NO_USING_TEMPLATE)
|
||||||
# define BOOST_IMPORT_TEMPLATE4(template_name)
|
|
||||||
# define BOOST_IMPORT_TEMPLATE3(template_name)
|
|
||||||
# define BOOST_IMPORT_TEMPLATE2(template_name)
|
|
||||||
# define BOOST_IMPORT_TEMPLATE1(template_name)
|
|
||||||
|
|
||||||
#else // BOOST_NO_OPERATORS_IN_NAMESPACE
|
|
||||||
|
|
||||||
# ifndef BOOST_NO_USING_TEMPLATE
|
|
||||||
|
|
||||||
// Bring the names in with a using-declaration
|
|
||||||
// to avoid stressing the compiler.
|
|
||||||
# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name;
|
|
||||||
# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
|
|
||||||
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
|
|
||||||
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
|
|
||||||
|
|
||||||
# else
|
|
||||||
|
|
||||||
// Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
|
|
||||||
// from working, we are forced to use inheritance for that compiler.
|
|
||||||
# define BOOST_IMPORT_TEMPLATE4(template_name) \
|
|
||||||
template <class T, class U, class V, class W, class B = ::boost::detail::empty_base> \
|
|
||||||
struct template_name : ::template_name<T, U, V, W, B> {};
|
|
||||||
|
|
||||||
# define BOOST_IMPORT_TEMPLATE3(template_name) \
|
|
||||||
template <class T, class U, class V, class B = ::boost::detail::empty_base> \
|
|
||||||
struct template_name : ::template_name<T, U, V, B> {};
|
|
||||||
|
|
||||||
|
// Because a Borland C++ 5.5 bug prevents a using declaration from working,
|
||||||
|
// we are forced to use inheritance for that compiler.
|
||||||
# define BOOST_IMPORT_TEMPLATE2(template_name) \
|
# define BOOST_IMPORT_TEMPLATE2(template_name) \
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||||
struct template_name : ::template_name<T, U, B> {};
|
struct template_name : ::template_name<T, U, B> {};
|
||||||
@@ -680,8 +309,21 @@ struct random_access_iteratable
|
|||||||
template <class T, class B = ::boost::detail::empty_base> \
|
template <class T, class B = ::boost::detail::empty_base> \
|
||||||
struct template_name : ::template_name<T, B> {};
|
struct template_name : ::template_name<T, B> {};
|
||||||
|
|
||||||
|
# else
|
||||||
|
|
||||||
|
// Otherwise, bring the names in with a using-declaration to avoid
|
||||||
|
// stressing the compiler
|
||||||
|
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
|
||||||
|
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
|
||||||
|
|
||||||
# endif // BOOST_NO_USING_TEMPLATE
|
# endif // BOOST_NO_USING_TEMPLATE
|
||||||
|
|
||||||
|
#else // !BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
|
||||||
|
// The template is already in boost so we have nothing to do.
|
||||||
|
# define BOOST_IMPORT_TEMPLATE2(template_name)
|
||||||
|
# define BOOST_IMPORT_TEMPLATE1(template_name)
|
||||||
|
|
||||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -690,7 +332,7 @@ struct random_access_iteratable
|
|||||||
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
|
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
|
||||||
// neccessary.
|
// neccessary.
|
||||||
//
|
//
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||||
|
|
||||||
// is_chained_base<> - a traits class used to distinguish whether an operator
|
// is_chained_base<> - a traits class used to distinguish whether an operator
|
||||||
// template argument is being used for base class chaining, or is specifying a
|
// template argument is being used for base class chaining, or is specifying a
|
||||||
@@ -713,24 +355,6 @@ template<class T> struct is_chained_base {
|
|||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
|
||||||
// Import a 4-type-argument operator template into boost (if neccessary) and
|
|
||||||
// provide a specialization of 'is_chained_base<>' for it.
|
|
||||||
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
|
|
||||||
BOOST_IMPORT_TEMPLATE4(template_name4) \
|
|
||||||
template<class T, class U, class V, class W, class B> \
|
|
||||||
struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > { \
|
|
||||||
typedef ::boost::detail::true_t value; \
|
|
||||||
};
|
|
||||||
|
|
||||||
// Import a 3-type-argument operator template into boost (if neccessary) and
|
|
||||||
// provide a specialization of 'is_chained_base<>' for it.
|
|
||||||
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
|
|
||||||
BOOST_IMPORT_TEMPLATE3(template_name3) \
|
|
||||||
template<class T, class U, class V, class B> \
|
|
||||||
struct is_chained_base< ::boost::template_name3<T, U, V, B> > { \
|
|
||||||
typedef ::boost::detail::true_t value; \
|
|
||||||
};
|
|
||||||
|
|
||||||
// Import a 2-type-argument operator template into boost (if neccessary) and
|
// Import a 2-type-argument operator template into boost (if neccessary) and
|
||||||
// provide a specialization of 'is_chained_base<>' for it.
|
// provide a specialization of 'is_chained_base<>' for it.
|
||||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||||
@@ -790,10 +414,6 @@ BOOST_OPERATOR_TEMPLATE1(template_name##1)
|
|||||||
|
|
||||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
|
||||||
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
|
|
||||||
BOOST_IMPORT_TEMPLATE4(template_name4)
|
|
||||||
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
|
|
||||||
BOOST_IMPORT_TEMPLATE3(template_name3)
|
|
||||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||||
BOOST_IMPORT_TEMPLATE2(template_name2)
|
BOOST_IMPORT_TEMPLATE2(template_name2)
|
||||||
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
||||||
@@ -814,67 +434,55 @@ BOOST_OPERATOR_TEMPLATE(equality_comparable)
|
|||||||
BOOST_OPERATOR_TEMPLATE(multipliable)
|
BOOST_OPERATOR_TEMPLATE(multipliable)
|
||||||
BOOST_OPERATOR_TEMPLATE(addable)
|
BOOST_OPERATOR_TEMPLATE(addable)
|
||||||
BOOST_OPERATOR_TEMPLATE(subtractable)
|
BOOST_OPERATOR_TEMPLATE(subtractable)
|
||||||
BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(dividable)
|
BOOST_OPERATOR_TEMPLATE(dividable)
|
||||||
BOOST_OPERATOR_TEMPLATE2(dividable2_left)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(modable)
|
BOOST_OPERATOR_TEMPLATE(modable)
|
||||||
BOOST_OPERATOR_TEMPLATE2(modable2_left)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(xorable)
|
BOOST_OPERATOR_TEMPLATE(xorable)
|
||||||
BOOST_OPERATOR_TEMPLATE(andable)
|
BOOST_OPERATOR_TEMPLATE(andable)
|
||||||
BOOST_OPERATOR_TEMPLATE(orable)
|
BOOST_OPERATOR_TEMPLATE(orable)
|
||||||
|
|
||||||
BOOST_OPERATOR_TEMPLATE1(incrementable)
|
BOOST_OPERATOR_TEMPLATE1(incrementable)
|
||||||
BOOST_OPERATOR_TEMPLATE1(decrementable)
|
BOOST_OPERATOR_TEMPLATE1(decrementable)
|
||||||
|
|
||||||
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
|
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
|
||||||
BOOST_OPERATOR_TEMPLATE3(indexable)
|
|
||||||
|
|
||||||
BOOST_OPERATOR_TEMPLATE1(bool_testable)
|
// indexable doesn't follow the patterns above (it has 4 template arguments), so
|
||||||
|
// we just write out the compiler hacks explicitly.
|
||||||
|
#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
# ifdef BOOST_NO_USING_TEMPLATE
|
||||||
|
template <class T, class I, class R, class B = ::boost::detail::empty_base>
|
||||||
|
struct indexable : ::indexable<T,I,R,B> {};
|
||||||
|
# else
|
||||||
|
using ::indexable;
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
BOOST_OPERATOR_TEMPLATE(left_shiftable)
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
BOOST_OPERATOR_TEMPLATE(right_shiftable)
|
template <class T, class I, class R, class B>
|
||||||
BOOST_OPERATOR_TEMPLATE(equivalent)
|
struct is_chained_base< ::boost::indexable<T, I, R, B> > {
|
||||||
BOOST_OPERATOR_TEMPLATE(partially_ordered)
|
typedef ::boost::detail::true_t operator_template_type;
|
||||||
|
};
|
||||||
BOOST_OPERATOR_TEMPLATE(totally_ordered)
|
#endif
|
||||||
BOOST_OPERATOR_TEMPLATE(additive)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(multiplicative)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(arithmetic)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(bitwise)
|
|
||||||
BOOST_OPERATOR_TEMPLATE1(unit_steppable)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(shiftable)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(ring_operators)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(field_operators)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
|
|
||||||
BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
|
|
||||||
BOOST_OPERATOR_TEMPLATE2(input_iteratable)
|
|
||||||
BOOST_OPERATOR_TEMPLATE1(output_iteratable)
|
|
||||||
BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
|
|
||||||
BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
|
|
||||||
BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
|
|
||||||
|
|
||||||
#undef BOOST_OPERATOR_TEMPLATE
|
#undef BOOST_OPERATOR_TEMPLATE
|
||||||
#undef BOOST_OPERATOR_TEMPLATE4
|
|
||||||
#undef BOOST_OPERATOR_TEMPLATE3
|
|
||||||
#undef BOOST_OPERATOR_TEMPLATE2
|
#undef BOOST_OPERATOR_TEMPLATE2
|
||||||
#undef BOOST_OPERATOR_TEMPLATE1
|
#undef BOOST_OPERATOR_TEMPLATE1
|
||||||
#undef BOOST_IMPORT_TEMPLATE1
|
#undef BOOST_IMPORT_TEMPLATE1
|
||||||
#undef BOOST_IMPORT_TEMPLATE2
|
#undef BOOST_IMPORT_TEMPLATE2
|
||||||
#undef BOOST_IMPORT_TEMPLATE3
|
|
||||||
#undef BOOST_IMPORT_TEMPLATE4
|
|
||||||
|
|
||||||
// The following 'operators' classes can only be used portably if the derived class
|
// The following 'operators' classes can only be used portably if the derived class
|
||||||
// declares ALL of the required member operators.
|
// declares ALL of the required member operators.
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
struct operators2
|
struct operators2
|
||||||
: totally_ordered2<T,U
|
: less_than_comparable2<T,U
|
||||||
, integer_arithmetic2<T,U
|
, equality_comparable2<T,U
|
||||||
, bitwise2<T,U
|
, addable2<T,U
|
||||||
> > > {};
|
, subtractable2<T,U
|
||||||
|
, multipliable2<T,U
|
||||||
|
, dividable2<T,U
|
||||||
|
, modable2<T,U
|
||||||
|
, orable2<T,U
|
||||||
|
, andable2<T,U
|
||||||
|
, xorable2<T,U
|
||||||
|
> > > > > > > > > > {};
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
template <class T, class U = T>
|
template <class T, class U = T>
|
||||||
@@ -884,44 +492,32 @@ template <class T> struct operators<T, T>
|
|||||||
#else
|
#else
|
||||||
template <class T> struct operators
|
template <class T> struct operators
|
||||||
#endif
|
#endif
|
||||||
: totally_ordered<T
|
: less_than_comparable<T
|
||||||
, integer_arithmetic<T
|
, equality_comparable<T
|
||||||
, bitwise<T
|
, addable<T
|
||||||
, unit_steppable<T
|
, subtractable<T
|
||||||
> > > > {};
|
, multipliable<T
|
||||||
|
, dividable<T
|
||||||
|
, modable<T
|
||||||
|
, orable<T
|
||||||
|
, andable<T
|
||||||
|
, xorable<T
|
||||||
|
, incrementable<T
|
||||||
|
, decrementable<T
|
||||||
|
> > > > > > > > > > > > {};
|
||||||
|
|
||||||
// Iterator helper classes (contributed by Jeremy Siek) -------------------//
|
// Iterator helper classes (contributed by Jeremy Siek) -------------------//
|
||||||
// (Input and output iterator helpers contributed by Daryle Walker) -------//
|
|
||||||
// (Changed to use combined operator classes by Daryle Walker) ------------//
|
|
||||||
template <class T,
|
|
||||||
class V,
|
|
||||||
class D = std::ptrdiff_t,
|
|
||||||
class P = V const *,
|
|
||||||
class R = V const &>
|
|
||||||
struct input_iterator_helper
|
|
||||||
: input_iteratable<T, P
|
|
||||||
, boost::iterator<std::input_iterator_tag, V, D, P, R
|
|
||||||
> > {};
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct output_iterator_helper
|
|
||||||
: output_iteratable<T
|
|
||||||
, boost::iterator<std::output_iterator_tag, void, void, void, void
|
|
||||||
> >
|
|
||||||
{
|
|
||||||
T& operator*() { return static_cast<T&>(*this); }
|
|
||||||
T& operator++() { return static_cast<T&>(*this); }
|
|
||||||
};
|
|
||||||
|
|
||||||
template <class T,
|
template <class T,
|
||||||
class V,
|
class V,
|
||||||
class D = std::ptrdiff_t,
|
class D = std::ptrdiff_t,
|
||||||
class P = V*,
|
class P = V*,
|
||||||
class R = V&>
|
class R = V&>
|
||||||
struct forward_iterator_helper
|
struct forward_iterator_helper
|
||||||
: forward_iteratable<T, P
|
: equality_comparable<T
|
||||||
|
, incrementable<T
|
||||||
|
, dereferenceable<T,P
|
||||||
, boost::iterator<std::forward_iterator_tag,V,D,P,R
|
, boost::iterator<std::forward_iterator_tag,V,D,P,R
|
||||||
> > {};
|
> > > > {};
|
||||||
|
|
||||||
template <class T,
|
template <class T,
|
||||||
class V,
|
class V,
|
||||||
@@ -929,9 +525,12 @@ template <class T,
|
|||||||
class P = V*,
|
class P = V*,
|
||||||
class R = V&>
|
class R = V&>
|
||||||
struct bidirectional_iterator_helper
|
struct bidirectional_iterator_helper
|
||||||
: bidirectional_iteratable<T, P
|
: equality_comparable<T
|
||||||
|
, incrementable<T
|
||||||
|
, decrementable<T
|
||||||
|
, dereferenceable<T,P
|
||||||
, boost::iterator<std::bidirectional_iterator_tag,V,D,P,R
|
, boost::iterator<std::bidirectional_iterator_tag,V,D,P,R
|
||||||
> > {};
|
> > > > > {};
|
||||||
|
|
||||||
template <class T,
|
template <class T,
|
||||||
class V,
|
class V,
|
||||||
@@ -939,13 +538,22 @@ template <class T,
|
|||||||
class P = V*,
|
class P = V*,
|
||||||
class R = V&>
|
class R = V&>
|
||||||
struct random_access_iterator_helper
|
struct random_access_iterator_helper
|
||||||
: random_access_iteratable<T, P, D, R
|
: equality_comparable<T
|
||||||
|
, less_than_comparable<T
|
||||||
|
, incrementable<T
|
||||||
|
, decrementable<T
|
||||||
|
, dereferenceable<T,P
|
||||||
|
, addable2<T,D
|
||||||
|
, subtractable2<T,D
|
||||||
|
, indexable<T,D,R
|
||||||
, boost::iterator<std::random_access_iterator_tag,V,D,P,R
|
, boost::iterator<std::random_access_iterator_tag,V,D,P,R
|
||||||
> >
|
> > > > > > > > >
|
||||||
{
|
{
|
||||||
|
#ifndef __BORLANDC__
|
||||||
friend D requires_difference_operator(const T& x, const T& y) {
|
friend D requires_difference_operator(const T& x, const T& y) {
|
||||||
return x - y;
|
return x - y;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}; // random_access_iterator_helper
|
}; // random_access_iterator_helper
|
||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
@@ -1,163 +0,0 @@
|
|||||||
#ifndef BOOST_REF_HPP_INCLUDED
|
|
||||||
# define BOOST_REF_HPP_INCLUDED
|
|
||||||
|
|
||||||
# if _MSC_VER+0 >= 1020
|
|
||||||
# pragma once
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# include <boost/config.hpp>
|
|
||||||
# include <boost/utility/addressof.hpp>
|
|
||||||
# include <boost/mpl/bool.hpp>
|
|
||||||
|
|
||||||
//
|
|
||||||
// ref.hpp - ref/cref, useful helper functions
|
|
||||||
//
|
|
||||||
// Copyright (C) 1999, 2000 Jaakko J<>rvi (jaakko.jarvi@cs.utu.fi)
|
|
||||||
// Copyright (C) 2001, 2002 Peter Dimov
|
|
||||||
// Copyright (C) 2002 David Abrahams
|
|
||||||
//
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// See http://www.boost.org/libs/bind/ref.html for documentation.
|
|
||||||
//
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
|
|
||||||
template<class T> class reference_wrapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef T type;
|
|
||||||
|
|
||||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
|
|
||||||
|
|
||||||
explicit reference_wrapper(T& t): t_(&t) {}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
explicit reference_wrapper(T& t): t_(addressof(t)) {}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
operator T& () const { return *t_; }
|
|
||||||
|
|
||||||
T& get() const { return *t_; }
|
|
||||||
|
|
||||||
T* get_pointer() const { return t_; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
T* t_;
|
|
||||||
};
|
|
||||||
|
|
||||||
# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x570)
|
|
||||||
# define BOOST_REF_CONST
|
|
||||||
# else
|
|
||||||
# define BOOST_REF_CONST const
|
|
||||||
# endif
|
|
||||||
|
|
||||||
template<class T> inline reference_wrapper<T> BOOST_REF_CONST ref(T & t)
|
|
||||||
{
|
|
||||||
return reference_wrapper<T>(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T> inline reference_wrapper<T const> BOOST_REF_CONST cref(T const & t)
|
|
||||||
{
|
|
||||||
return reference_wrapper<T const>(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
# undef BOOST_REF_CONST
|
|
||||||
|
|
||||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
template<typename T>
|
|
||||||
class is_reference_wrapper
|
|
||||||
: public mpl::false_
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class is_reference_wrapper<reference_wrapper<T> >
|
|
||||||
: public mpl::true_
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class unwrap_reference
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef T type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class unwrap_reference<reference_wrapper<T> >
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef T type;
|
|
||||||
};
|
|
||||||
# else // no partial specialization
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#include <boost/type.hpp>
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
typedef char (&yes_reference_wrapper_t)[1];
|
|
||||||
typedef char (&no_reference_wrapper_t)[2];
|
|
||||||
|
|
||||||
no_reference_wrapper_t is_reference_wrapper_test(...);
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
yes_reference_wrapper_t is_reference_wrapper_test(type< reference_wrapper<T> >);
|
|
||||||
|
|
||||||
template<bool wrapped>
|
|
||||||
struct reference_unwrapper
|
|
||||||
{
|
|
||||||
template <class T>
|
|
||||||
struct apply
|
|
||||||
{
|
|
||||||
typedef T type;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct reference_unwrapper<true>
|
|
||||||
{
|
|
||||||
template <class T>
|
|
||||||
struct apply
|
|
||||||
{
|
|
||||||
typedef typename T::type type;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
class is_reference_wrapper
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BOOST_STATIC_CONSTANT(
|
|
||||||
bool, value = (
|
|
||||||
sizeof(detail::is_reference_wrapper_test(type<T>()))
|
|
||||||
== sizeof(detail::yes_reference_wrapper_t)));
|
|
||||||
|
|
||||||
typedef ::boost::mpl::bool_<value> type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class unwrap_reference
|
|
||||||
: public detail::reference_unwrapper<
|
|
||||||
is_reference_wrapper<T>::value
|
|
||||||
>::template apply<T>
|
|
||||||
{};
|
|
||||||
|
|
||||||
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
#endif // #ifndef BOOST_REF_HPP_INCLUDED
|
|
@@ -1,21 +0,0 @@
|
|||||||
// Boost utility.hpp header file -------------------------------------------//
|
|
||||||
|
|
||||||
// (C) Copyright Boost.org 1999-2003. 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.
|
|
||||||
|
|
||||||
// See http://www.boost.org/libs/utility for documentation.
|
|
||||||
|
|
||||||
#ifndef BOOST_UTILITY_HPP
|
|
||||||
#define BOOST_UTILITY_HPP
|
|
||||||
|
|
||||||
#include <boost/utility/addressof.hpp>
|
|
||||||
#include <boost/utility/base_from_member.hpp>
|
|
||||||
#include <boost/checked_delete.hpp>
|
|
||||||
#include <boost/next_prior.hpp>
|
|
||||||
#include <boost/noncopyable.hpp>
|
|
||||||
|
|
||||||
#endif // BOOST_UTILITY_HPP
|
|
||||||
|
|
@@ -1,34 +0,0 @@
|
|||||||
// Boost utility_fwd.hpp header file ---------------------------------------//
|
|
||||||
|
|
||||||
// (C) Copyright boost.org 2001. 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.
|
|
||||||
|
|
||||||
// See http://www.boost.org/libs/utility for documentation.
|
|
||||||
|
|
||||||
#ifndef BOOST_UTILITY_FWD_HPP
|
|
||||||
#define BOOST_UTILITY_FWD_HPP
|
|
||||||
|
|
||||||
|
|
||||||
namespace boost
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
// From <boost/utility/base_from_member.hpp> -------------------------------//
|
|
||||||
|
|
||||||
template < typename MemberType, int UniqueID = 0 >
|
|
||||||
class base_from_member;
|
|
||||||
|
|
||||||
|
|
||||||
// From <boost/utility.hpp> ------------------------------------------------//
|
|
||||||
|
|
||||||
class noncopyable;
|
|
||||||
|
|
||||||
// Also has a few function templates
|
|
||||||
|
|
||||||
} // namespace boost
|
|
||||||
|
|
||||||
|
|
||||||
#endif // BOOST_UTILITY_FWD_HPP
|
|
61
indirect_iterator_example.cpp
Normal file
61
indirect_iterator_example.cpp
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
// (C) Copyright Jeremy Siek 2000. 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.
|
||||||
|
|
||||||
|
#include <boost/config.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <iterator>
|
||||||
|
#include <functional>
|
||||||
|
#include <boost/iterator_adaptors.hpp>
|
||||||
|
|
||||||
|
int main(int, char*[])
|
||||||
|
{
|
||||||
|
char characters[] = "abcdefg";
|
||||||
|
const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
|
||||||
|
char* pointers_to_chars[N]; // at the end.
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
pointers_to_chars[i] = &characters[i];
|
||||||
|
|
||||||
|
// Example of using indirect_iterator_generator
|
||||||
|
|
||||||
|
boost::indirect_iterator_generator<char**, char>::type
|
||||||
|
indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
|
||||||
|
|
||||||
|
std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
// Example of using indirect_iterator_pair_generator
|
||||||
|
|
||||||
|
typedef boost::indirect_iterator_pair_generator<char**,
|
||||||
|
char, char*, char&, const char*, const char&> PairGen;
|
||||||
|
|
||||||
|
char mutable_characters[N];
|
||||||
|
char* pointers_to_mutable_chars[N];
|
||||||
|
for (int i = 0; i < N; ++i)
|
||||||
|
pointers_to_mutable_chars[i] = &mutable_characters[i];
|
||||||
|
|
||||||
|
PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars),
|
||||||
|
mutable_indirect_last(pointers_to_mutable_chars + N);
|
||||||
|
PairGen::const_iterator const_indirect_first(pointers_to_chars),
|
||||||
|
const_indirect_last(pointers_to_chars + N);
|
||||||
|
|
||||||
|
std::transform(const_indirect_first, const_indirect_last,
|
||||||
|
mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
|
||||||
|
|
||||||
|
std::copy(mutable_indirect_first, mutable_indirect_last,
|
||||||
|
std::ostream_iterator<char>(std::cout, ","));
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
// Example of using make_indirect_iterator()
|
||||||
|
|
||||||
|
std::copy(boost::make_indirect_iterator(pointers_to_chars),
|
||||||
|
boost::make_indirect_iterator(pointers_to_chars + N),
|
||||||
|
std::ostream_iterator<char>(std::cout, ","));
|
||||||
|
std::cout << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
104
utility.htm
Normal file
104
utility.htm
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<html>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||||
|
<title>Header boost/utility.hpp Documentation</title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body bgcolor="#FFFFFF" text="#000000">
|
||||||
|
|
||||||
|
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" WIDTH="277" HEIGHT="86">Header
|
||||||
|
<a href="../../boost/utility.hpp">boost/utility.hpp</a></h1>
|
||||||
|
|
||||||
|
<p>The entire contents of the header <code><a href="../../boost/utility.hpp"><boost/utility.hpp></a></code>
|
||||||
|
are in <code>namespace boost</code>.</p>
|
||||||
|
|
||||||
|
<h2>Contents</h2>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li>Function templates <a href="#functions next">next() and prior()</a></li>
|
||||||
|
<li>Class <a href="#Class noncopyable">noncopyable</a></li>
|
||||||
|
<li>Function template <a href="tie.html">tie()</a> and supporting class tied.</li>
|
||||||
|
</ul>
|
||||||
|
<h2> <a name="functions next">Function</a> templates next() and prior()</h2>
|
||||||
|
|
||||||
|
<p>Certain data types, such as the C++ Standard Library's forward and
|
||||||
|
bidirectional iterators, do not provide addition and subtraction via operator+()
|
||||||
|
or operator-(). This means that non-modifying computation of the next or
|
||||||
|
prior value requires a temporary, even though operator++() or operator--() is
|
||||||
|
provided. It also means that writing code like <code>itr+1</code> inside a
|
||||||
|
template restricts the iterator category to random access iterators.</p>
|
||||||
|
|
||||||
|
<p>The next() and prior() functions provide a simple way around these problems:</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
|
||||||
|
<pre>template <class T>
|
||||||
|
T next(T x) { return ++x; }
|
||||||
|
|
||||||
|
template <class X>
|
||||||
|
T prior(T x) { return --x; }</pre>
|
||||||
|
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p>Usage is simple:</p>
|
||||||
|
|
||||||
|
<blockquote>
|
||||||
|
|
||||||
|
<pre>const std::list<T>::iterator p = get_some_iterator();
|
||||||
|
const std::list<T>::iterator prev = boost::prior(p);</pre>
|
||||||
|
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.</p>
|
||||||
|
|
||||||
|
<h2><a name="Class noncopyable">Class noncopyable</a></h2>
|
||||||
|
|
||||||
|
<p>Class <strong>noncopyable</strong> is a base class. Derive your own class from <strong>noncopyable</strong>
|
||||||
|
when you want to prohibit copy construction and copy assignment.</p>
|
||||||
|
|
||||||
|
<p>Some objects, particularly those which hold complex resources like files or
|
||||||
|
network connections, have no sensible copy semantics. Sometimes there are
|
||||||
|
possible copy semantics, but these would be of very limited usefulness and be
|
||||||
|
very difficult to implement correctly. Sometimes you're implementing a class that doesn't need to be copied
|
||||||
|
just yet and you don't want to take the time to write the appropriate functions.
|
||||||
|
Deriving from <b> noncopyable</b> will prevent the otherwise implicitly-generated
|
||||||
|
functions (which don't have the proper semantics) from becoming a trap for other programmers.</p>
|
||||||
|
|
||||||
|
<p>The traditional way to deal with these is to declare a private copy constructor and copy assignment, and then
|
||||||
|
document why this is done. But deriving from <b>noncopyable</b> is simpler
|
||||||
|
and clearer, and doesn't require additional documentation.</p>
|
||||||
|
|
||||||
|
<p>The program <a href="noncopyable_test.cpp">noncopyable_test.cpp</a> can be
|
||||||
|
used to verify class <b>noncopyable</b> works as expected. It has have been run successfully under
|
||||||
|
GCC 2.95, Metrowerks
|
||||||
|
CodeWarrior 5.0, and Microsoft Visual C++ 6.0 sp 3.</p>
|
||||||
|
|
||||||
|
<p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.</p>
|
||||||
|
|
||||||
|
<h3>Example</h3>
|
||||||
|
<blockquote>
|
||||||
|
<pre>// inside one of your own headers ...
|
||||||
|
#include <boost/utility.hpp>
|
||||||
|
|
||||||
|
class ResourceLadenFileSystem : boost::noncopyable {
|
||||||
|
...</pre>
|
||||||
|
</blockquote>
|
||||||
|
|
||||||
|
<h3>Rationale</h3>
|
||||||
|
<p>Class noncopyable has protected constructor and destructor members to
|
||||||
|
emphasize that it is to be used only as a base class. Dave Abrahams notes
|
||||||
|
concern about the effect on compiler optimization of adding (even trivial inline)
|
||||||
|
destructor declarations. He says "Probably this concern is misplaced, because
|
||||||
|
noncopyable will be used mostly for classes which own resources and thus have non-trivial destruction semantics."</p>
|
||||||
|
<hr>
|
||||||
|
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan
|
||||||
|
-->16 February, 2001<!--webbot bot="Timestamp" endspan i-checksum="40407"
|
||||||
|
-->
|
||||||
|
</p>
|
||||||
|
<p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and
|
||||||
|
distribute this document is granted provided this copyright notice appears in
|
||||||
|
all copies. This document is provided "as is" without express or
|
||||||
|
implied warranty, and with no claim as to its suitability for any purpose.</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
Reference in New Issue
Block a user