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 ----------------------------------------//
|
||||
|
||||
// (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-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.
|
||||
// (C) Copyright David Abrahams 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/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
|
||||
// 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
|
||||
// supplied arguments from actually being used (Dave Abrahams)
|
||||
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
|
||||
@@ -79,10 +66,9 @@
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
#include <boost/preprocessor/seq/cat.hpp>
|
||||
|
||||
#if defined(__sgi) && !defined(__GNUC__)
|
||||
# pragma set woff 1234
|
||||
#pragma set woff 1234
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
@@ -92,14 +78,7 @@
|
||||
namespace boost {
|
||||
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 {};
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
@@ -154,112 +133,106 @@ struct equality_comparable1 : B
|
||||
friend bool operator!=(const T& x, const T& y) { return !(x == y); }
|
||||
};
|
||||
|
||||
// A macro which produces "name_2left" from "name".
|
||||
#define BOOST_OPERATOR2_LEFT(name) BOOST_PP_SEQ_CAT_S(1,(name)(2)(_)(left))
|
||||
|
||||
// NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
|
||||
|
||||
#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; } \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct multipliable2 : B
|
||||
{
|
||||
friend T operator*(T x, const U& y) { return x *= y; }
|
||||
friend T operator*(const U& y, T x) { return x *= y; }
|
||||
};
|
||||
|
||||
#define BOOST_BINARY_OPERATOR_NON_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; } \
|
||||
}; \
|
||||
\
|
||||
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; } \
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct multipliable1 : B
|
||||
{
|
||||
friend T operator*(T x, const T& y) { return x *= y; }
|
||||
};
|
||||
|
||||
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
|
||||
|
||||
// For compilers without NRVO the following code is optimal, but not
|
||||
// symmetric! Note that the implementation of
|
||||
// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
|
||||
// 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; } \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct addable2 : B
|
||||
{
|
||||
friend T operator+(T x, const U& y) { return x += y; }
|
||||
friend T operator+(const U& y, T x) { return x += y; }
|
||||
};
|
||||
|
||||
#define BOOST_BINARY_OPERATOR_NON_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; } \
|
||||
}; \
|
||||
\
|
||||
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; } \
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct addable1 : B
|
||||
{
|
||||
friend T operator+(T x, const T& y) { return x += y; }
|
||||
};
|
||||
|
||||
#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, * )
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
|
||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
|
||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
|
||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
|
||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct subtractable1 : B
|
||||
{
|
||||
friend T operator-(T x, const T& y) { return x -= y; }
|
||||
};
|
||||
|
||||
#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
|
||||
#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
|
||||
#undef BOOST_OPERATOR2_LEFT
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct dividable2 : B
|
||||
{
|
||||
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
|
||||
|
||||
@@ -268,9 +241,9 @@ struct incrementable : B
|
||||
{
|
||||
friend T operator++(T& x, int)
|
||||
{
|
||||
incrementable_type nrv(x);
|
||||
incrementable_type tmp(x);
|
||||
++x;
|
||||
return nrv;
|
||||
return tmp;
|
||||
}
|
||||
private: // The use of this typedef works around a Borland bug
|
||||
typedef T incrementable_type;
|
||||
@@ -281,9 +254,9 @@ struct decrementable : B
|
||||
{
|
||||
friend T operator--(T& x, int)
|
||||
{
|
||||
decrementable_type nrv(x);
|
||||
decrementable_type tmp(x);
|
||||
--x;
|
||||
return nrv;
|
||||
return tmp;
|
||||
}
|
||||
private: // The use of this typedef works around a Borland bug
|
||||
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
|
||||
} // namespace boost
|
||||
#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
|
||||
// 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
|
||||
// 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.
|
||||
# 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> {};
|
||||
# if defined(BOOST_NO_USING_TEMPLATE)
|
||||
|
||||
// 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) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||
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> \
|
||||
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
|
||||
|
||||
#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
|
||||
|
||||
//
|
||||
@@ -690,7 +332,7 @@ struct random_access_iteratable
|
||||
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
|
||||
// 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
|
||||
// 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
|
||||
|
||||
// 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
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||
@@ -790,10 +414,6 @@ BOOST_OPERATOR_TEMPLATE1(template_name##1)
|
||||
|
||||
#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) \
|
||||
BOOST_IMPORT_TEMPLATE2(template_name2)
|
||||
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
||||
@@ -814,67 +434,55 @@ BOOST_OPERATOR_TEMPLATE(equality_comparable)
|
||||
BOOST_OPERATOR_TEMPLATE(multipliable)
|
||||
BOOST_OPERATOR_TEMPLATE(addable)
|
||||
BOOST_OPERATOR_TEMPLATE(subtractable)
|
||||
BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(dividable)
|
||||
BOOST_OPERATOR_TEMPLATE2(dividable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(modable)
|
||||
BOOST_OPERATOR_TEMPLATE2(modable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(xorable)
|
||||
BOOST_OPERATOR_TEMPLATE(andable)
|
||||
BOOST_OPERATOR_TEMPLATE(orable)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE1(incrementable)
|
||||
BOOST_OPERATOR_TEMPLATE1(decrementable)
|
||||
|
||||
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)
|
||||
BOOST_OPERATOR_TEMPLATE(right_shiftable)
|
||||
BOOST_OPERATOR_TEMPLATE(equivalent)
|
||||
BOOST_OPERATOR_TEMPLATE(partially_ordered)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE(totally_ordered)
|
||||
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)
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T, class I, class R, class B>
|
||||
struct is_chained_base< ::boost::indexable<T, I, R, B> > {
|
||||
typedef ::boost::detail::true_t operator_template_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
#undef BOOST_OPERATOR_TEMPLATE
|
||||
#undef BOOST_OPERATOR_TEMPLATE4
|
||||
#undef BOOST_OPERATOR_TEMPLATE3
|
||||
#undef BOOST_OPERATOR_TEMPLATE2
|
||||
#undef BOOST_OPERATOR_TEMPLATE1
|
||||
#undef BOOST_IMPORT_TEMPLATE1
|
||||
#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
|
||||
// declares ALL of the required member operators.
|
||||
template <class T, class U>
|
||||
struct operators2
|
||||
: totally_ordered2<T,U
|
||||
, integer_arithmetic2<T,U
|
||||
, bitwise2<T,U
|
||||
> > > {};
|
||||
: less_than_comparable2<T,U
|
||||
, equality_comparable2<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
|
||||
template <class T, class U = T>
|
||||
@@ -884,44 +492,32 @@ template <class T> struct operators<T, T>
|
||||
#else
|
||||
template <class T> struct operators
|
||||
#endif
|
||||
: totally_ordered<T
|
||||
, integer_arithmetic<T
|
||||
, bitwise<T
|
||||
, unit_steppable<T
|
||||
> > > > {};
|
||||
: less_than_comparable<T
|
||||
, equality_comparable<T
|
||||
, addable<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) -------------------//
|
||||
// (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,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct forward_iterator_helper
|
||||
: forward_iteratable<T, P
|
||||
, boost::iterator<std::forward_iterator_tag, V, D, P, R
|
||||
> > {};
|
||||
: equality_comparable<T
|
||||
, incrementable<T
|
||||
, dereferenceable<T,P
|
||||
, boost::iterator<std::forward_iterator_tag,V,D,P,R
|
||||
> > > > {};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
@@ -929,9 +525,12 @@ template <class T,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct bidirectional_iterator_helper
|
||||
: bidirectional_iteratable<T, P
|
||||
, boost::iterator<std::bidirectional_iterator_tag, V, D, P, R
|
||||
> > {};
|
||||
: equality_comparable<T
|
||||
, incrementable<T
|
||||
, decrementable<T
|
||||
, dereferenceable<T,P
|
||||
, boost::iterator<std::bidirectional_iterator_tag,V,D,P,R
|
||||
> > > > > {};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
@@ -939,13 +538,22 @@ template <class T,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct random_access_iterator_helper
|
||||
: random_access_iteratable<T, P, D, R
|
||||
, boost::iterator<std::random_access_iterator_tag, V, D, P, 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
|
||||
> > > > > > > > >
|
||||
{
|
||||
#ifndef __BORLANDC__
|
||||
friend D requires_difference_operator(const T& x, const T& y) {
|
||||
return x - y;
|
||||
}
|
||||
#endif
|
||||
}; // random_access_iterator_helper
|
||||
|
||||
} // 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