mirror of
https://github.com/boostorg/utility.git
synced 2025-05-09 15:04:00 +00:00
Initial HTML commit
[SVN r7634]
This commit is contained in:
parent
777c931b5d
commit
d83ea9e52e
738
call_traits.htm
Normal file
738
call_traits.htm
Normal file
@ -0,0 +1,738 @@
|
||||
<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. Note that for compilers that do not support partial
|
||||
specialization, 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.</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<Operation::second_argument_type, Operation::result_type>
|
||||
{
|
||||
protected:
|
||||
Operation op;
|
||||
Operation::first_argument_type value;
|
||||
public:
|
||||
binder1st(const Operation& x, const Operation::first_argument_type& y);
|
||||
Operation::result_type operator()(const 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>Operation::result_type operator()(call_traits<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.</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>
|
||||
|
||||
<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(call_traits<T>::value_type t);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void A<T>::foo(call_traits<T>::value_type t)
|
||||
{
|
||||
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 18 June 2000</p>
|
||||
|
||||
<p>© 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>
|
148
cast.htm
Normal file
148
cast.htm
Normal file
@ -0,0 +1,148 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Header boost/cast.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/cast.hpp">boost/cast.hpp</a></h1>
|
||||
<h2><a name="Cast Functions">Cast Functions</a></h2>
|
||||
<p>The <code>header <a href="../../boost/cast.hpp">boost/cast.hpp</a></code>
|
||||
provides <a href="#Polymorphic_cast"><b>polymorphic_cast</b></a>, <a href="#Polymorphic_cast"><b>polymorphic_downcast</b></a>,
|
||||
and <a href="#numeric_cast"><b>numeric_cast</b></a> template functions designed
|
||||
to complement the C++ Standard's built-in casts.</p>
|
||||
<p>The program <a href="cast_test.cpp">cast_test.cpp</a> can be used to
|
||||
verify these function templates work as expected.</p>
|
||||
<p><b>polymorphic_cast</b> was suggested by Bjarne Stroustrup in "The C++
|
||||
Programming Language".<br>
|
||||
<b>polymorphic_downcast</b> was contributed by <a href="../../people/dave_abrahams.htm">Dave
|
||||
Abrahams</a>.<b><br>
|
||||
numeric_cast</b> was contributed by <a href="../../people/kevlin_henney.htm">Kevlin
|
||||
Henney</a>.</p>
|
||||
<h3>Namespace synopsis</h3>
|
||||
<blockquote>
|
||||
<pre>namespace boost {
|
||||
namespace cast {
|
||||
// all synopsis below included here
|
||||
}
|
||||
using ::boost::cast::polymorphic_cast;
|
||||
using ::boost::cast::polymorphic_downcast;
|
||||
using ::boost::cast::bad_numeric_cast;
|
||||
using ::boost::cast::numeric_cast;
|
||||
}</pre>
|
||||
</blockquote>
|
||||
<h3><a name="Polymorphic_cast">Polymorphic casts</a></h3>
|
||||
<p>Pointers to polymorphic objects (objects of classes which define at least one
|
||||
virtual function) are sometimes downcast or crosscast. Downcasting means
|
||||
casting from a base class to a derived class. Crosscasting means casting
|
||||
across an inheritance hierarchy diagram, such as from one base to the other in a
|
||||
<b>Y</b> diagram hierarchy.</p>
|
||||
<p>Such casts can be done with old-style casts, but this approach is never to be
|
||||
recommended. Old-style casts are sorely lacking in type safety, suffer
|
||||
poor readability, and are difficult to locate with search tools.</p>
|
||||
<p>The C++ built-in <b>static_cast</b> can be used for efficiently downcasting
|
||||
pointers to polymorphic objects, but provides no error detection for the case
|
||||
where the pointer being cast actually points to the wrong derived class. The <b>polymorphic_downcast</b>
|
||||
template retains the efficiency of <b>static_cast</b> for non-debug
|
||||
compilations, but for debug compilations adds safety via an assert() that a <b>dynamic_cast</b>
|
||||
succeeds. <b> </b></p>
|
||||
<p>The C++ built-in <b>dynamic_cast</b> can be used for downcasts and crosscasts
|
||||
of pointers to polymorphic objects, but error notification in the form of a
|
||||
returned value of 0 is inconvenient to test, or worse yet, easy to forget to
|
||||
test. The <b>polymorphic_cast</b> template performs a <b>dynamic_cast</b>,
|
||||
and throws an exception if the <b>dynamic_cast</b> returns 0.</p>
|
||||
<p>A <b>polymorphic_downcast</b> is preferred when debug-mode tests will cover
|
||||
100% of the object types possibly cast and when non-debug-mode efficiency is an
|
||||
issue. If these two conditions are not present, <b>polymorphic_cast</b> is
|
||||
preferred. It must also be used for crosscasts. It does an assert(
|
||||
dynamic_cast<Derived>(x) == x ) where x is the base pointer, ensuring that
|
||||
not only is a non-zero pointer returned, but also that it correct in the
|
||||
presence of multiple inheritance. .<b> Warning:</b>: Because <b>polymorphic_downcast</b>
|
||||
uses assert(), it violates the One Definition Rule if NDEBUG is inconsistently
|
||||
defined across translation units.</p>
|
||||
<p>The C++ built-in <b>dynamic_cast</b> must be used to cast references rather
|
||||
than pointers. It is also the only cast that can be used to check whether
|
||||
a given interface is supported; in that case a return of 0 isn't an error
|
||||
condition.</p>
|
||||
<h3>polymorphic_cast and polymorphic_downcast synopsis</h3>
|
||||
<blockquote>
|
||||
<pre>template <class Derived, class Base>
|
||||
inline Derived polymorphic_cast(Base* x);
|
||||
// Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 )
|
||||
// Returns: dynamic_cast<Derived>(x)
|
||||
|
||||
template <class Derived, class Base>
|
||||
inline Derived polymorphic_downcast(Base* x);
|
||||
// Effects: assert( dynamic_cast<Derived>(x) == x );
|
||||
// Returns: static_cast<Derived>(x)</pre>
|
||||
</blockquote>
|
||||
<h3>polymorphic_downcast example</h3>
|
||||
<blockquote>
|
||||
<pre>#include <boost/cast.hpp>
|
||||
...
|
||||
class Fruit { public: virtual ~Fruit(){}; ... };
|
||||
class Banana : public Fruit { ... };
|
||||
...
|
||||
void f( Fruit * fruit ) {
|
||||
// ... logic which leads us to believe it is a Banana
|
||||
Banana * banana = boost::polymorphic_downcast<Banana*>(fruit);
|
||||
...</pre>
|
||||
</blockquote>
|
||||
<h3><a name="numeric_cast">numeric_cast</a></h3>
|
||||
<p>A <b>static_cast</b>, <b>implicit_cast</b> or implicit conversion will not
|
||||
detect failure to preserve range for numeric casts. The <b>numeric_cast</b>
|
||||
template function are similar to <b>static_cast</b> and certain (dubious)
|
||||
implicit conversions in this respect, except that they detect loss of numeric
|
||||
range. An exception is thrown when a runtime value preservation check fails.</p>
|
||||
<p>The requirements on the argument and result types are:</p>
|
||||
<blockquote>
|
||||
<ul>
|
||||
<li>Both argument and result types are CopyConstructible [20.1.3].</li>
|
||||
<li>Both argument and result types are Numeric, defined by <code>std::numeric_limits<>::is_specialized</code>
|
||||
being true.</li>
|
||||
<li>The argument can be converted to the result type using <b>static_cast</b>.</li>
|
||||
</ul>
|
||||
</blockquote>
|
||||
<h3>numeric_cast synopsis</h3>
|
||||
<blockquote>
|
||||
<pre>class bad_numeric_cast : public std::bad_cast {...};
|
||||
|
||||
template<typename Target, typename Source>
|
||||
inline Target numeric_cast(Source arg);
|
||||
// Throws: bad_numeric_cast unless, in converting arg from Source to Target,
|
||||
// there is no loss of negative range, and no underflow, and no
|
||||
// overflow, as determined by std::numeric_limits
|
||||
// Returns: static_cast<Target>(arg)</pre>
|
||||
</blockquote>
|
||||
<h3>numeric_cast example</h3>
|
||||
<blockquote>
|
||||
<pre>#include <boost/cast.hpp>
|
||||
using namespace boost::cast;
|
||||
|
||||
void ariane(double vx)
|
||||
{
|
||||
...
|
||||
unsigned short dx = numeric_cast<unsigned short>(vx);
|
||||
...
|
||||
}</pre>
|
||||
</blockquote>
|
||||
<h3>numeric_cast rationale</h3>
|
||||
<p>The form of the throws condition is specified so that != is not a required
|
||||
operation.</p>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
|
||||
-->28 June, 2000<!--webbot bot="Timestamp" endspan i-checksum="19846"
|
||||
--></p>
|
||||
<p>© 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>
|
92
compressed_pair.htm
Normal file
92
compressed_pair.htm
Normal file
@ -0,0 +1,92 @@
|
||||
<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>Header <boost/compressed_pair.hpp></title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
|
||||
vlink="#800080">
|
||||
|
||||
<h2><img src="../../c++boost.gif" width="276" height="86">Header
|
||||
<<a href="../../boost/detail/call_traits.hpp">boost/compressed_pair.hpp</a>></h2>
|
||||
|
||||
<p>All of the contents of <boost/compressed_pair.hpp> are
|
||||
defined inside namespace boost.</p>
|
||||
|
||||
<p>The class compressed pair is very similar to std::pair, but if
|
||||
either of the template arguments are empty classes, then the
|
||||
"empty member optimisation" is applied to compress the
|
||||
size of the pair.</p>
|
||||
|
||||
<pre>template <class T1, class T2>
|
||||
class compressed_pair
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair() : base() {}
|
||||
compressed_pair(first_param_type x, second_param_type y);
|
||||
explicit compressed_pair(first_param_type x);
|
||||
explicit compressed_pair(second_param_type y);
|
||||
|
||||
first_reference first();
|
||||
first_const_reference first() const;
|
||||
|
||||
second_reference second();
|
||||
second_const_reference second() const;
|
||||
|
||||
void swap(compressed_pair& y);
|
||||
};</pre>
|
||||
|
||||
<p>The two members of the pair can be accessed using the member
|
||||
functions first() and second(). Note that not all member
|
||||
functions can be instantiated for all template parameter types.
|
||||
In particular compressed_pair can be instantiated for reference
|
||||
and array types, however in these cases the range of constructors
|
||||
that can be used are limited. If types T1 and T2 are the same
|
||||
type, then there is only one version of the single-argument
|
||||
constructor, and this constructor initialises both values in the
|
||||
pair to the passed value.</p>
|
||||
|
||||
<p>Note that compressed_pair can not be instantiated if either of
|
||||
the template arguments is an enumerator type, unless there is
|
||||
compiler support for boost::is_enum, or if boost::is_enum is
|
||||
specialised for the enumerator type.</p>
|
||||
|
||||
<p>Finally, compressed_pair requires compiler support for partial
|
||||
specialisation of class templates - without that support
|
||||
compressed_pair behaves just like std::pair.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised 08 March 2000</p>
|
||||
|
||||
<p>© 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>
|
||||
</body>
|
||||
</html>
|
72
index.htm
Normal file
72
index.htm
Normal file
@ -0,0 +1,72 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Boost Utility Library</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<table border="1" cellpadding="2" bgcolor="#007F7F">
|
||||
<tr>
|
||||
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" height="86"></td>
|
||||
<td><a href="../../index.htm"><font color="#FFFFFF" size="4" face="Arial">Home</font></a></td>
|
||||
<td><a href="../../libraries.htm"><font color="#FFFFFF" size="4" face="Arial">Libraries</font></a></td>
|
||||
<td><a href="../../people.htm"><font color="#FFFFFF" size="4" face="Arial">People</font></a></td>
|
||||
<td><a href="../../more/faq.htm"><font color="#FFFFFF" size="4" face="Arial">FAQ</font></a></td>
|
||||
<td><a href="../../more/index.htm"><font color="#FFFFFF" size="4" face="Arial">More</font></a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<h1>Boost Utility Library</h1>
|
||||
<table border="1" cellpadding="5">
|
||||
<tr>
|
||||
<td><b><i>Header</i></b></td>
|
||||
<td><b><i>Contents</i></b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../../boost/utility.hpp"><code>boost/utility.hpp<br>
|
||||
</code></a><a href="utility.htm">[Documentation]</a></td>
|
||||
<td>Class <b>noncopyable</b> plus <b>next()</b> and <b>prior()</b> template
|
||||
functions.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../../boost/cast.hpp"><code>boost/cast.hpp</code></a><br>
|
||||
<a href="cast.htm">[Documentation]</a></td>
|
||||
<td><b>polymorphic_cast</b>, <b>implicit_cast</b>, and <b>numeric_cast</b>
|
||||
function templates.
|
||||
<p><i>[Beta.]</i></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../../boost/operators.hpp">boost/operators.hpp</a><br>
|
||||
<a href="operators.htm">[Documentation]</a></td>
|
||||
<td>Templates <b>equality_comparable</b>, <b>less_than_comparable</b>, <b>addable</b>,
|
||||
and the like ease the task of defining comparison and arithmetic
|
||||
operators, and iterators.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../../boost/detail/type_traits.hpp">boost/type_traits.hpp</a><br>
|
||||
[<a href="type_traits.htm">Documentation</a>]<br>
|
||||
[<a href="c++_type_traits.htm">DDJ Article "C++ type traits"</a>]</td>
|
||||
<td>Template classes that describe the fundamental properties of a type.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../../boost/detail/call_traits.hpp">boost/call_traits.hpp</a><br>
|
||||
[<a href="call_traits.htm">Documentation</a>]</td>
|
||||
<td>Template class call_traits<T>, that defines types used for passing
|
||||
parameters to and from a proceedure.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="../../boost/detail/compressed_pair.hpp">boost/compressed_pair.hpp</a><br>
|
||||
[<a href="compressed_pair.htm">Documentation</a>]</td>
|
||||
<td>Template class compressed_pait<T1, T2> which pairs two values
|
||||
using the empty member optimisation where appropriate.</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B %Y" startspan -->24 July 2000<!--webbot bot="Timestamp" endspan i-checksum="18764" --></p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
598
operators.htm
Normal file
598
operators.htm
Normal file
@ -0,0 +1,598 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<title>Header boost/operators.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/operators.hpp">boost/operators.hpp</a></h1>
|
||||
<p>Header <a href="http://www.boost.org/boost/operators.hpp">boost/operators.hpp</a>
|
||||
supplies (in namespace boost) several sets of templates:</p>
|
||||
<ul>
|
||||
<li><a href="#Arithmetic">Arithmetic operators</a>.
|
||||
<li><a href="#deref and helpers">Dereference operators and iterator helpers.</a></li>
|
||||
</ul>
|
||||
<p>These templates define many global operators in terms of a minimal number of
|
||||
fundamental operators.</p>
|
||||
<h1><a name="Arithmetic">Arithmetic</a> Operators</h1>
|
||||
<p>If, for example, you declare a class like this:</p>
|
||||
<blockquote>
|
||||
<pre>class MyInt : boost::operators<MyInt>
|
||||
{
|
||||
bool operator<(const MyInt& x) const;
|
||||
bool operator==(const MyInt& x) const;
|
||||
MyInt& operator+=(const MyInt& x);
|
||||
MyInt& operator-=(const MyInt& x);
|
||||
MyInt& operator*=(const MyInt& x);
|
||||
MyInt& operator/=(const MyInt& x);
|
||||
MyInt& operator%=(const MyInt& x);
|
||||
MyInt& operator|=(const MyInt& x);
|
||||
MyInt& operator&=(const MyInt& x);
|
||||
MyInt& operator^=(const MyInt& x);
|
||||
MyInt& operator++();
|
||||
MyInt& operator--();
|
||||
};</pre>
|
||||
</blockquote>
|
||||
<p>then the <code>operators<></code> template adds more than a dozen
|
||||
additional operators, such as operator>, <=, >=, and +. <a href="#two_arg">Two-argument
|
||||
forms</a> of the templates are also provided to allow interaction with other
|
||||
types.</p>
|
||||
<p><a href="http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a>
|
||||
started the library and contributed the arithmetic operators in <a href="http://www.boost.org/boost/operators.hpp">boost/operators.hpp</a>.<br>
|
||||
<a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>
|
||||
contributed the <a href="#deref and helpers">dereference operators and iterator
|
||||
helpers</a> in <a href="http://www.boost.org/boost/operators.hpp">boost/operators.hpp</a>.<br>
|
||||
<a href="http://www.boost.org/people/aleksey_gurtovoy.htm">Aleksey Gurtovoy</a>
|
||||
contributed the code to support <a href="#chaining">base class chaining</a>
|
||||
while remaining backward-compatible with old versions of the library.<br>
|
||||
<a href="http://www.boost.org/people/beman_dawes.html">Beman Dawes</a>
|
||||
contributed <a href="http://www.boost.org/libs/utility/operators_test.cpp">test_operators.cpp</a>.</p>
|
||||
<h2>Rationale</h2>
|
||||
<p>Overloaded operators for class types typically occur in groups. If you can
|
||||
write <code>x + y</code>, you probably also want to be able to write <code>x +=
|
||||
y</code>. If you can write <code>x < y,</code> you also want <code>x > y,
|
||||
x >= y,</code> and <code>x <= y</code>. Moreover, unless your class has
|
||||
really surprising behavior, some of these related operators can be defined in
|
||||
terms of others (e.g. <code>x >= y <b><=></b> !(x < y)</code>).
|
||||
Replicating this boilerplate for multiple classes is both tedious and
|
||||
error-prone. The <a href="http://www.boost.org/boost/operators.hpp">boost/operators.hpp</a>
|
||||
templates help by generating operators for you at namespace scope based on other
|
||||
operators you've defined in your class.</p>
|
||||
<a name="two_arg">
|
||||
<h2>Two-Argument Template Forms</h2>
|
||||
</a>
|
||||
<p>The arguments to a binary operator commonly have identical types, but it is
|
||||
not unusual to want to define operators which combine different types. For <a href="#usage">example</a>,
|
||||
one might want to multiply a mathematical vector by a scalar. The two-argument
|
||||
template forms of the arithmetic operator templates are supplied for this
|
||||
purpose. When applying the two-argument form of a template, the desired return
|
||||
type of the operators typically determines which of the two types in question
|
||||
should be derived from the operator template. For example, if the result of <code>T + U</code>
|
||||
is of type <code>T</code>, then <code>T</code> (not <code>U</code>) should be
|
||||
derived from <code>addable<T,U></code>. The comparison templates <code><a href="#less_than_comparable">less_than_comparable<></a></code>
|
||||
and <code><a href="#equality_comparable">equality_comparable<></a></code>
|
||||
are exceptions to this guideline, since the return type of the operators they
|
||||
define is <code>bool</code>.</p>
|
||||
<p>On compilers which do not support partial specialization, the two-argument
|
||||
forms must be specified by using the names shown below with the trailing <code>'2'</code>.
|
||||
The single-argument forms with the trailing <code>'1'</code> are provided for
|
||||
symmetry and to enable certain applications of the <a href="#chaining">base
|
||||
class chaining</a> technique.</p>
|
||||
<h2>Arithmetic operators table</h2>
|
||||
<p>The requirements for the types used to instantiate operator templates are
|
||||
specified in terms of expressions which must be valid and by the return type of
|
||||
the expression. In the following table <code>t</code> and <code>t1</code> are
|
||||
values of type <code>T</code>, and <code>u</code> is a value of type <code>U</code>.
|
||||
Every template in the library other than <a href="#operators"><code>operators<></code></a>
|
||||
and <a href="#operators"><code>operators2<></code></a> has an additional
|
||||
optional template parameter <code>B</code> which is not shown in the table, but
|
||||
is explained <a href="#chaining">below</a></p>
|
||||
<table cellpadding="5" border="1">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><b>template</b></td>
|
||||
<td><b>template will supply</b></td>
|
||||
<td><b>Requirements</b></td>
|
||||
</tr>
|
||||
<a name="operators">
|
||||
<tr>
|
||||
<td><code>operators<T></code></td>
|
||||
<td>All the other <T> templates in this table.</td>
|
||||
<td>All the <T> requirements in this table.</td>
|
||||
<tr>
|
||||
<td><code>operators<T,U><br>
|
||||
operators2<T,U></code></td>
|
||||
<td>All the other <T,U> templates in this table, plus incrementable<T>
|
||||
and decrementable<T>.</td>
|
||||
<td><b>All</b> the <T,U> requirements in this table</a><a href="#portability">*</a>,
|
||||
plus incrementable<T> and decrementable<T>.</td>
|
||||
</tr>
|
||||
<a name="less_than_comparable">
|
||||
<tr>
|
||||
<td><code>less_than_comparable<T><br>
|
||||
less_than_comparable1<T></code></td>
|
||||
<td><code>bool operator>(const T&, const T&) <br>
|
||||
bool operator<=(const T&, const T&)<br>
|
||||
bool operator>=(const T&, const T&)</code></td>
|
||||
<td><code>t<t1</code>. Return convertible to bool</td>
|
||||
<tr>
|
||||
<td><code>less_than_comparable<T,U><br>
|
||||
less_than_comparable2<T,U></code></td>
|
||||
<td><code>bool operator<=(const T&, const U&)<br>
|
||||
bool operator>=(const T&, const U&)<br>
|
||||
bool operator>(const U&, const T&) <br>
|
||||
bool operator<(const U&, const T&) <br>
|
||||
bool operator<=(const U&, const T&)<br>
|
||||
bool operator>=(const U&, const T&)</code></td>
|
||||
<td><code>t<u</code>. Return convertible to bool<br>
|
||||
<code>t>u</code>. Return convertible to bool</td>
|
||||
</tr>
|
||||
</a><a name="equality_comparable">
|
||||
<tr>
|
||||
<td><code>equality_comparable<T><br>
|
||||
equality_comparable1<T></code></td>
|
||||
<td><code>bool operator!=(const T&, const T&)</code></td>
|
||||
<td><code>t==t1</code>. Return convertible to bool</td>
|
||||
<tr>
|
||||
<td><code>equality_comparable<T,U><br>
|
||||
equality_comparable2<T,U></code></td>
|
||||
<td><code>friend bool operator==(const U&, const T&)<br>
|
||||
friend bool operator!=(const U&, const T&)<br>
|
||||
friend bool operator!=( const T&, const U&)</code></td>
|
||||
<td><code>t==u</code>. Return convertible to bool</td>
|
||||
</tr>
|
||||
</a>
|
||||
<tr>
|
||||
<td><code>addable<T><br>
|
||||
addable1<T></code></td>
|
||||
<td><code>T operator+(T, const T&)</code></td>
|
||||
<td><code>t+=t1</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>addable<T,U><br>
|
||||
addable2<T,U></code></td>
|
||||
<td><code>T operator+(T, const U&)<br>
|
||||
T operator+(const U&, T )</code></td>
|
||||
<td><code>t+=u</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>subtractable<T><br>
|
||||
subtractable1<T></code></td>
|
||||
<td><code>T operator-(T, const T&)</code></td>
|
||||
<td><code>t-=t1</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>subtractable<T,U><br>
|
||||
subtractable2<T,U></code></td>
|
||||
<td><code>T operator-(T, const U&)</code></td>
|
||||
<td><code>t-=u</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>multipliable<T><br>
|
||||
multipliable1<T></code></td>
|
||||
<td><code>T operator*(T, const T&)</code></td>
|
||||
<td><code>t*=t1</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>multipliable<T,U><br>
|
||||
multipliable2<T,U></code></td>
|
||||
<td><code>T operator*(T, const U&)<br>
|
||||
T operator*(const U&, T )</code></td>
|
||||
<td><code>t*=u</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dividable<T><br>
|
||||
dividable1<T></code></td>
|
||||
<td><code>T operator/(T, const T&)</code></td>
|
||||
<td><code>t/=t1</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dividable<T,U><br>
|
||||
dividable2<T,U></code></td>
|
||||
<td><code>T operator/(T, const U&)</code></td>
|
||||
<td><code>t/=u</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>modable<T><br>
|
||||
modable1<T></code></td>
|
||||
<td><code>T operator%(T, const T&)</code></td>
|
||||
<td><code>t%=t1</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>modable<T,U><br>
|
||||
modable2<T,U></code></td>
|
||||
<td><code>T operator%(T, const U&)</code></td>
|
||||
<td><code>t%=u</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>orable<T><br>
|
||||
orable1<T></code></td>
|
||||
<td><code>T operator|(T, const T&)</code></td>
|
||||
<td><code>t|=t1</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>orable<T,U><br>
|
||||
orable2<T,U></code></td>
|
||||
<td><code>T operator|(T, const U&)<br>
|
||||
T operator|(const U&, T )</code></td>
|
||||
<td><code>t|=u</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>andable<T><br>
|
||||
andable1<T></code></td>
|
||||
<td><code>T operator&(T, const T&)</code></td>
|
||||
<td><code>t&=t1</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>andable<T,U><br>
|
||||
andable2<T,U></code></td>
|
||||
<td><code>T operator&(T, const U&)<br>
|
||||
T operator&(const U&, T)</code></td>
|
||||
<td><code>t&=u</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>xorable<T><br>
|
||||
xorable1<T></code></td>
|
||||
<td><code>T operator^(T, const T&)</code></td>
|
||||
<td><code>t^=t1</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>xorable<T,U><br>
|
||||
xorable2<T,U></code></td>
|
||||
<td><code>T operator^(T, const U&)<br>
|
||||
T operator^(const U&, T )</code></td>
|
||||
<td><code>t^=u</code>. Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>incrementable<T><br>
|
||||
incrementable1<T></code></td>
|
||||
<td><code>T operator++(T& x, int)</code></td>
|
||||
<td><code>T temp(x); ++x; return temp;</code><br>
|
||||
Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>decrementable<T><br>
|
||||
decrementable1<T></code></td>
|
||||
<td><code>T operator--(T& x, int)</code></td>
|
||||
<td><code>T temp(x); --x; return temp;</code><br>
|
||||
Return convertible to <code>T</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<b><a name="portability">Portability Note:</a></b> many compilers (e.g. MSVC6.3,
|
||||
GCC 2.95.2) will not enforce the requirements in this table unless the
|
||||
operations which depend on them are actually used. This is not
|
||||
standard-conforming behavior. If you are trying to write portable code it is
|
||||
important not to rely on this bug. In particular, it would be convenient to
|
||||
derive all your classes which need binary operators from the <a href="#operators"><code>operators<></code></a>
|
||||
and <a href="#operators"><code>operators2<></code></a> templates,
|
||||
regardless of whether they implement all the requirements in the table. Even if
|
||||
this works with your compiler today, it may not work tomorrow.
|
||||
<h2><a name="chaining">Base Class Chaining</a> and Object Size</h2>
|
||||
<p>Every template listed in the table except <a href="#operators"><code>operators<></code></a>
|
||||
and <a href="#operators"><code>operators2<></code></a> has an additional
|
||||
optional template parameter <code>B</code>. If supplied, <code>B</code>
|
||||
must be a class type; the resulting class will be publicly derived from B. This
|
||||
can be used to avoid the object size bloat commonly associated with multiple
|
||||
empty base classes (see the <a href="#old_lib_note">note for users of older
|
||||
versions</a> below for more details). To provide support for several groups of
|
||||
operators, use the additional parameter to chain operator templates into a
|
||||
single-base class hierarchy, as in the following <a href="#usage">example</a>.</p>
|
||||
<p><b>Caveat:</b> to chain to a base class which is <i>not</i> a boost operator
|
||||
template when using the <a href="#two_arg">single-argument form</a><a> of a
|
||||
boost operator template, you must specify the operator template with the
|
||||
trailing <code>'1'</code> in its name. Otherwise the library will assume you
|
||||
mean to define a binary operation combining the class you intend to use as a
|
||||
base class and the class you're deriving.</p>
|
||||
<p><b>Borland users</b>: even single-inheritance seems to cause an increase in
|
||||
object size in some cases. If you are not defining a template, you may get
|
||||
better object-size performance by avoiding derivation altogether, and instead
|
||||
explicitly instantiating the operator template as follows:
|
||||
<pre>
|
||||
class myclass // lose the inheritance...
|
||||
{
|
||||
//...
|
||||
};
|
||||
// explicitly instantiate the operators I need.
|
||||
template class less_than_comparable<myclass>;
|
||||
template class equality_comparable<myclass>;
|
||||
template class incrementable<myclass>;
|
||||
template class decrementable<myclass>;
|
||||
template class addable<myclass,long>;
|
||||
template class subtractable<myclass,long>;
|
||||
</pre>
|
||||
</a><a name="usage">
|
||||
<h2>Usage example</h2>
|
||||
</a>
|
||||
<pre>template <class T>
|
||||
class point // note: private inheritance is OK here!
|
||||
: boost::addable< point<T> // point + point
|
||||
, boost::subtractable< point<T> // point - point
|
||||
, boost::dividable2< point<T>, T // point / T
|
||||
, boost::multipliable2< point<T>, T // point * T, T * point
|
||||
> > > >
|
||||
{
|
||||
public:
|
||||
point(T, T);
|
||||
T x() const;
|
||||
T y() const;
|
||||
|
||||
point operator+=(const point&);
|
||||
// point operator+(point, const point&) automatically
|
||||
// generated by addable.
|
||||
|
||||
point operator-=(const point&);
|
||||
// point operator-(point, const point&) automatically
|
||||
// generated by subtractable.
|
||||
|
||||
point operator*=(T);
|
||||
// point operator*(point, const T&) and
|
||||
// point operator*(const T&, point) auto-generated
|
||||
// by multipliable.
|
||||
|
||||
point operator/=(T);
|
||||
// point operator/(point, const T&) auto-generated
|
||||
// by dividable.
|
||||
private:
|
||||
T x_;
|
||||
T y_;
|
||||
};
|
||||
|
||||
// now use the point<> class:
|
||||
|
||||
template <class T>
|
||||
T length(const point<T> p)
|
||||
{
|
||||
return sqrt(p.x()*p.x() + p.y()*p.y());
|
||||
}
|
||||
|
||||
const point<float> right(0, 1);
|
||||
const point<float> up(1, 0);
|
||||
const point<float> pi_over_4 = up + right;
|
||||
const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4);</pre>
|
||||
<h2>Arithmetic operators demonstration and test program</h2>
|
||||
<p>The <a href="http://www.boost.org/libs/utility/operators_test.cpp">operators_test.cpp</a>
|
||||
program demonstrates the use of the arithmetic operator templates, and can also
|
||||
be used to verify correct operation.</p>
|
||||
<p>The test program has been compiled and run successfully with: </p>
|
||||
<ul>
|
||||
<li>GCC 2.95.2
|
||||
<li>GCC 2.95.2 / STLport 4.0b8.
|
||||
<li>Metrowerks Codewarrior 5.3
|
||||
<li>KAI C++ 3.3
|
||||
<li>Microsoft Visual C++ 6.0 SP3.
|
||||
<li>Microsoft Visual C++ 6.0 SP3 / STLport 4.0b8.</li>
|
||||
</ul>
|
||||
<h1><a name="deref and helpers">Dereference</a> operators and iterator helpers</h1>
|
||||
<p>The <a href="#Iterator helpers">iterator helper</a> templates ease the task
|
||||
of creating a custom iterator. Similar to arithmetic types, a complete iterator
|
||||
has many operators that are "redundant" and can be implemented in
|
||||
terms of the core set of operators.</p>
|
||||
<p>The <a href="#dereference">dereference operators</a> were motivated by the <a href="#Iterator helpers">iterator
|
||||
helpers</a>, but are often useful in non-iterator contexts as well. Many of the
|
||||
redundant iterator operators are also arithmetic operators, so the iterator
|
||||
helper classes borrow many of the operators defined above. In fact, only two new
|
||||
operators need to be defined! (the pointer-to-member <code>operator-></code>
|
||||
and the subscript <code>operator[]</code>). </PP>
|
||||
<h3>Notation</h3>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td valign="top"><code>T</code></td>
|
||||
<td valign="top">is the user-defined type for which the operations are
|
||||
being supplied.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>V</code></td>
|
||||
<td valign="top">is the type which the resulting <code>dereferenceable</code>
|
||||
type "points to", or the <code>value_type</code> of the custom
|
||||
iterator.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>D</code></td>
|
||||
<td valign="top">is the type used to index the resulting <code>indexable</code>
|
||||
type or the <code>difference_type</code> of the custom iterator.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>P</code></td>
|
||||
<td valign="top">is a type which can be dereferenced to access <code>V</code>,
|
||||
or the <code>pointer</code> type of the custom iterator.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>R</code></td>
|
||||
<td valign="top">is the type returned by indexing the <code>indexable</code>
|
||||
type or the <code>reference</code> type of the custom iterator.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>i</code></td>
|
||||
<td valign="top">is short for <code>static_cast<const T&>(*this)</code>,
|
||||
where <code>this</code> is a pointer to the helper class.<br>
|
||||
Another words, <code>i</code> should be an object of the custom iterator
|
||||
type.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>x,x1,x2</code></td>
|
||||
<td valign="top">are objects of type <code>T</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top"><code>n</code></td>
|
||||
<td valign="top">is an object of type <code>D</code>.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>The requirements for the types used to instantiate the dereference operators
|
||||
and iterator helpers are specified in terms of expressions which must be valid
|
||||
and their return type. </p>
|
||||
<h2><a name="dereference">Dereference operators</a></h2>
|
||||
<p>The dereference operator templates in this table all accept an optional
|
||||
template parameter (not shown) to be used for <a href="#chaining">base class
|
||||
chaining</a>.
|
||||
<table cellpadding="5" border="1">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><b>template</b></td>
|
||||
<td><b>template will supply</b></td>
|
||||
<td><b>Requirements</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dereferenceable<T,P></code></td>
|
||||
<td><code>P operator->() const</code></td>
|
||||
<td><code>(&*i.)</code>. Return convertible to <code>P</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>indexable<T,D,R></code></td>
|
||||
<td><code>R operator[](D n) const</code></td>
|
||||
<td><code>*(i + n)</code>. Return of type <code>R</code>.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2><a name="Iterator helpers">Iterator</a> helpers</h2>
|
||||
<p>There are three separate iterator helper classes, each for a different
|
||||
category of iterator. Here is a summary of the core set of operators that the
|
||||
custom iterator must define, and the extra operators that are created by the
|
||||
helper classes. For convenience, the helper classes also fill in all of the
|
||||
typedef's required of iterators by the C++ standard (<code>iterator_category</code>,
|
||||
<code>value_type</code>, etc.).</p>
|
||||
<table cellpadding="5" border="1" valign="top">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><b>template</b></td>
|
||||
<td><b>template will supply</b></td>
|
||||
<td><b>Requirements</b></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>forward_iterator_helper</code><br>
|
||||
<code><T,V,D,P,R></code></td>
|
||||
<td><code>bool operator!=(const T& x1, const T& x2)</code><br>
|
||||
<code>T operator++(T& x, int)</code><br>
|
||||
<code>V* operator->() const</code><br>
|
||||
</td>
|
||||
<td><code>x1==x2</code>. Return convertible to bool<br>
|
||||
<code>T temp(x); ++x; return temp;</code><br>
|
||||
<code>(&*i.)</code>. Return convertible to <code>V*</code>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>bidirectional_iterator_helper</code><br>
|
||||
<code><T,V,D,P,R></code></td>
|
||||
<td>Same as above, plus<br>
|
||||
<code>T operator--(T& x, int)</code></td>
|
||||
<td>Same as above, plus<br>
|
||||
<code>T temp(x); --x; return temp;</code></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>random_access_iterator_helper</code><br>
|
||||
<code><T,V,D,P,R></code></td>
|
||||
<td>Same as above, plus<br>
|
||||
<code>T operator+(T x, const D&)<br>
|
||||
T operator+(const D& n, T x)<br>
|
||||
T operator-(T x, const D& n)<br>
|
||||
R operator[](D n) const<br>
|
||||
bool operator>(const T& x1, const T& x2) <br>
|
||||
bool operator<=(const T& x1, const T& x2)<br>
|
||||
bool operator>=(const T& x1, const T& x2)</code></td>
|
||||
<td>Same as above, plus<br>
|
||||
<code>x+=n</code>. Return convertible to <code>T</code><br>
|
||||
<code>x-=n</code>. Return convertible to <code>T</code><br>
|
||||
<code>x1<x2</code>. Return convertible to bool<br>
|
||||
And to satisfy <a href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">RandomAccessIterator</a>:<br>
|
||||
<code>x1-x2</code>. Return convertible to <code>D</code></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h2>Iterator demonstration and test program</h2>
|
||||
<p>The <a href="http://www.boost.org/libs/utility/iterators_test.cpp">iterators_test.cpp</a>
|
||||
program demonstrates the use of the iterator templates, and can also be used to
|
||||
verify correct operation. The following is the custom iterator defined in the
|
||||
test program. It demonstrates a correct (though trivial) implementation of the
|
||||
core operations that must be defined in order for the iterator helpers to
|
||||
"fill in" the rest of the iterator operations.</p>
|
||||
<blockquote>
|
||||
<pre>template <class T, class R, class P>
|
||||
struct test_iter
|
||||
: public boost::random_access_iterator_helper<
|
||||
test_iter<T,R,P>, T, std::ptrdiff_t, P, R>
|
||||
{
|
||||
typedef test_iter self;
|
||||
typedef R Reference;
|
||||
typedef std::ptrdiff_t Distance;
|
||||
|
||||
public:
|
||||
test_iter(T* i) : _i(i) { }
|
||||
test_iter(const self& x) : _i(x._i) { }
|
||||
self& operator=(const self& x) { _i = x._i; return *this; }
|
||||
Reference operator*() const { return *_i; }
|
||||
self& operator++() { ++_i; return *this; }
|
||||
self& operator--() { --_i; return *this; }
|
||||
self& operator+=(Distance n) { _i += n; return *this; }
|
||||
self& operator-=(Distance n) { _i -= n; return *this; }
|
||||
bool operator==(const self& x) const { return _i == x._i; }
|
||||
bool operator<(const self& x) const { return _i < x._i; }
|
||||
friend Distance operator-(const self& x, const self& y) {
|
||||
return x._i - y._i;
|
||||
}
|
||||
protected:
|
||||
T* _i;
|
||||
};</pre>
|
||||
</blockquote>
|
||||
<p>It has been compiled and run successfully with:</p>
|
||||
<ul>
|
||||
<li>GCC 2.95.2
|
||||
<li>Metrowerks Codewarrior 5.2
|
||||
<li>Microsoft Visual C++ 6.0 SP3</li>
|
||||
</ul>
|
||||
<p><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a>
|
||||
contributed the iterator operators and helpers. He also contributed <a href="http://www.boost.org/libs/utility/iterators_test.cpp">iterators_test.cpp</a>. </p>
|
||||
<hr>
|
||||
<h2><a name="old_lib_note">Note for users of older versions</a></h2>
|
||||
<p>The <a href="#chaining">changes in the library interface and recommended
|
||||
usage</a> were motivated by some practical issues described below. The new
|
||||
version of the library is still backward-compatible with the former one (so
|
||||
you're not <i>forced</i> change any existing code), but the old usage is
|
||||
deprecated. Though it was arguably simpler and more intuitive than using <a href="#chaining">base
|
||||
class chaining</a>, it has been discovered that the old practice of deriving
|
||||
from multiple operator templates can cause the resulting classes to be much
|
||||
larger than they should be. Most modern C++ compilers significantly bloat the
|
||||
size of classes derived from multiple empty base classes, even though the base
|
||||
classes themselves have no state. For instance, the size of <code>point<int></code>
|
||||
from the <a href="#usage">example</a> above was 12-24 bytes on various compilers
|
||||
for the Win32 platform, instead of the expected 8 bytes.
|
||||
<p>Strictly speaking, it was not the library's fault - the language rules allow
|
||||
the compiler to apply the empty base class optimization in that situation. In
|
||||
principle an arbitrary number of empty base classes can be allocated at the same
|
||||
offset, provided that none of them have a common ancestor (see section 10.5 [class.derived],
|
||||
par. 5 of the standard). But the language definition also doesn't <i>require</i>
|
||||
implementations to do the optimization, and few if any of today's compilers
|
||||
implement it when multiple inheritance is involved. What's worse, it is very
|
||||
unlikely that implementors will adopt it as a future enhancement to existing
|
||||
compilers, because it would break binary compatibility between code generated by
|
||||
two different versions of the same compiler. As Matt Austern said, "One of
|
||||
the few times when you have the freedom to do this sort of thing is when you're
|
||||
targeting a new architecture...". On the other hand, many common compilers
|
||||
will use the empty base optimization for single inheritance hierarchies.</p>
|
||||
<p>Given the importance of the issue for the users of the library (which aims to
|
||||
be useful for writing light-weight classes like <code>MyInt</code> or <code>point<></code>),
|
||||
and the forces described above, we decided to change the library interface so
|
||||
that the object size bloat could be eliminated even on compilers that support
|
||||
only the simplest form of the empty base class optimization. The current library
|
||||
interface is the result of those changes. Though the new usage is a bit more
|
||||
complicated than the old one, we think it's worth it to make the library more
|
||||
useful in real world. Alexy Gurtovoy contributed the code which supports the new
|
||||
usage idiom while allowing the library remain backward-compatible.</p>
|
||||
<hr>
|
||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->28 Jun 2000<!--webbot bot="Timestamp" endspan i-checksum="15058" -->
|
||||
</p>
|
||||
<p>© Copyright David Abrahams and Beman Dawes 1999-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>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
588
type_traits.htm
Normal file
588
type_traits.htm
Normal file
@ -0,0 +1,588 @@
|
||||
<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>Type Traits</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
|
||||
|
||||
<h1><img src="../../c++boost.gif" width="276" height="86">Header
|
||||
<<a href="../../boost/detail/type_traits.hpp">boost/type_traits.hpp</a>></h1>
|
||||
|
||||
<p>The contents of <boost/type_traits.hpp> are declared in
|
||||
namespace boost.</p>
|
||||
|
||||
<p>The file <<a href="../../boost/detail/type_traits.hpp">boost/type_traits.hpp</a>>
|
||||
contains various template classes that describe the fundamental
|
||||
properties of a type; each class represents a single type
|
||||
property or a single type transformation. This documentation is
|
||||
divided up into the following sections:</p>
|
||||
|
||||
<pre><a href="#fop">Fundamental type operations</a>
|
||||
<a href="#fp">Fundamental type properties</a>
|
||||
<code> </code><a href="#cv">cv-Qualifiers</a>
|
||||
<code> </code><a href="#ft">Fundamental Types</a>
|
||||
<code> </code><a href="#ct">Compound Types</a>
|
||||
<code> </code><a href="#ot">Object/Scalar Types</a>
|
||||
<a href="#cs">Compiler Support Information</a>
|
||||
<a href="#ec">Example Code</a></pre>
|
||||
|
||||
<h2><a name="fop"></a>Fundamental type operations</h2>
|
||||
|
||||
<p>Usage: "class_name<T>::type" performs
|
||||
indicated transformation on type T.</p>
|
||||
|
||||
<table border="1" cellpadding="7" cellspacing="1" width="624">
|
||||
<tr>
|
||||
<td valign="top" width="45%"><p align="center">Expression.</p>
|
||||
</td>
|
||||
<td valign="top" width="45%"><p align="center">Description.</p>
|
||||
</td>
|
||||
<td valign="top" width="33%"><p align="center">Compiler.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>remove_volatile<T>::type</code></td>
|
||||
<td valign="top" width="45%">Creates a type the same as T
|
||||
but with any top level volatile qualifier removed. For
|
||||
example "volatile int" would become "int".</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>remove_const<T>::type</code></td>
|
||||
<td valign="top" width="45%">Creates a type the same as T
|
||||
but with any top level const qualifier removed. For
|
||||
example "const int" would become "int".</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>remove_cv<T>::type</code></td>
|
||||
<td valign="top" width="45%">Creates a type the same as T
|
||||
but with any top level cv-qualifiers removed. For example
|
||||
"const int" would become "int", and
|
||||
"volatile double" would become "double".</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>remove_reference<T>::type</code></td>
|
||||
<td valign="top" width="45%">If T is a reference type
|
||||
then removes the reference, otherwise leaves T unchanged.
|
||||
For example "int&" becomes "int"
|
||||
but "int*" remains unchanged.</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>add_reference<T>::type</code></td>
|
||||
<td valign="top" width="45%">If T is a reference type
|
||||
then leaves T unchanged, otherwise converts T to a
|
||||
reference type. For example "int&" remains
|
||||
unchanged, but "double" becomes "double&".</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>remove_bounds<T>::type</code></td>
|
||||
<td valign="top" width="45%">If T is an array type then
|
||||
removes the top level array qualifier from T, otherwise
|
||||
leaves T unchanged. For example "int[2][3]"
|
||||
becomes "int[3]".</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<h2><a name="fp"></a>Fundamental type properties</h2>
|
||||
|
||||
<p>Usage: "class_name<T>::value" is true if
|
||||
indicated property is true, false otherwise. (Note that class_name<T>::value
|
||||
is always defined as a compile time constant).</p>
|
||||
|
||||
<h3><a name="cv"></a>cv-Qualifiers</h3>
|
||||
|
||||
<p>The following classes determine what cv-qualifiers are present
|
||||
on a type (see 3.93).</p>
|
||||
|
||||
<table border="1" cellpadding="7" cellspacing="1" width="624">
|
||||
<tr>
|
||||
<td valign="top" width="45%"><p align="center">Expression.</p>
|
||||
</td>
|
||||
<td valign="top" width="45%"><p align="center">Description.</p>
|
||||
</td>
|
||||
<td valign="top" width="33%"><p align="center">Compiler.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_const<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if type T is top-level
|
||||
const qualified.</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_volatile<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if type T is top-level
|
||||
volatile qualified.</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_same<T,U>::value</code></td>
|
||||
<td valign="top" width="45%">True if T and U are the same
|
||||
type.</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<h3><a name="ft"></a>Fundamental Types</h3>
|
||||
|
||||
<p>The following will only ever be true for cv-unqualified types;
|
||||
these are closely based on the section 3.9 of the C++ Standard.</p>
|
||||
|
||||
<table border="1" cellpadding="7" cellspacing="1" width="624">
|
||||
<tr>
|
||||
<td valign="top" width="45%"><p align="center">Expression.</p>
|
||||
</td>
|
||||
<td valign="top" width="45%"><p align="center">Description.</p>
|
||||
</td>
|
||||
<td valign="top" width="33%"><p align="center">Compiler.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_void<T>::value</code></td>
|
||||
<td valign="top" width="45%">True only if T is void.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_standard_unsigned_integral<T>::value</code></td>
|
||||
<td valign="top" width="45%">True only if T is one of the
|
||||
standard unsigned integral types (3.9.1 p3) - unsigned
|
||||
char, unsigned short, unsigned int, and unsigned long.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_standard_signed_integral<T>::value</code></td>
|
||||
<td valign="top" width="45%">True only if T is one of the
|
||||
standard signed integral types (3.9.1 p2) - signed char,
|
||||
short, int, and long.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_standard_integral<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is a standard
|
||||
integral type(3.9.1 p7) - T is either char, wchar_t, bool
|
||||
or either is_standard_signed_integral<T>::value or
|
||||
is_standard_integral<T>::value is true.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_standard_float<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is one of the
|
||||
standard floating point types(3.9.1 p8) - float, double
|
||||
or long double.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_standard_arithmetic<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is a standard
|
||||
arithmetic type(3.9.1 p8) - implies is_standard_integral
|
||||
or is_standard_float is true.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_standard_fundamental<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is a standard
|
||||
arithmetic type or if T is void.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_extension_unsigned_integral<T>::value</code></td>
|
||||
<td valign="top" width="45%">True for compiler specific
|
||||
unsigned integral types.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_extension_signed_integral<T>>:value</code></td>
|
||||
<td valign="top" width="45%">True for compiler specific
|
||||
signed integral types.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_extension_integral<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if either is_extension_unsigned_integral<T>::value
|
||||
or is_extension_signed_integral<T>::value is true.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_extension_float<T>::value</code></td>
|
||||
<td valign="top" width="45%">True for compiler specific
|
||||
floating point types.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_extension_arithmetic<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if either is_extension_integral<T>::value
|
||||
or is_extension_float<T>::value are true.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code> is_extension_fundamental<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if either is_extension_arithmetic<T>::value
|
||||
or is_void<T>::value are true.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code> is_unsigned_integral<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if either is_standard_unsigned_integral<T>::value
|
||||
or is_extention_unsigned_integral<T>::value are
|
||||
true.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_signed_integral<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if either is_standard_signed_integral<T>::value
|
||||
or is_extention_signed_integral<T>>::value are
|
||||
true.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_integral<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if either is_standard_integral<T>::value
|
||||
or is_extention_integral<T>::value are true.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_float<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if either is_standard_float<T>::value
|
||||
or is_extention_float<T>::value are true.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_arithmetic<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if either is_integral<T>::value
|
||||
or is_float<T>::value are true.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_fundamental<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if either is_arithmetic<T>::value
|
||||
or is_void<T>::value are true.</td>
|
||||
<td valign="top" width="33%"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<h3><a name="ct"></a>Compound Types</h3>
|
||||
|
||||
<p>The following will only ever be true for cv-unqualified types,
|
||||
as defined by the Standard. </p>
|
||||
|
||||
<table border="1" cellpadding="7" cellspacing="1" width="624">
|
||||
<tr>
|
||||
<td valign="top" width="45%"><p align="center">Expression</p>
|
||||
</td>
|
||||
<td valign="top" width="45%"><p align="center">Description</p>
|
||||
</td>
|
||||
<td valign="top" width="33%"><p align="center">Compiler</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_array<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is an array type.</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_pointer<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is a regular
|
||||
pointer type - including function pointers - but
|
||||
excluding pointers to member functions (3.9.2 p1 and 8.3.1).</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_member_pointer<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is a pointer to a
|
||||
non-static class member (3.9.2 p1 and 8.3.1).</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_reference<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is a reference
|
||||
type (3.9.2 p1 and 8.3.2).</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_class<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is a class or
|
||||
struct type.</td>
|
||||
<td valign="top" width="33%"><p align="center">PD</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_union<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is a union type.</td>
|
||||
<td valign="top" width="33%"><p align="center">C</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_enum<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is an enumerator
|
||||
type.</td>
|
||||
<td valign="top" width="33%"><p align="center">C</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_compound<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is any of the
|
||||
above compound types.</td>
|
||||
<td valign="top" width="33%"><p align="center">PD</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<h3><a name="ot"></a>Object/Scalar Types</h3>
|
||||
|
||||
<p>The following ignore any top level cv-qualifiers: if <code>class_name<T>::value</code>
|
||||
is true then <code>class_name<cv-qualified-T>::value</code>
|
||||
will also be true.</p>
|
||||
|
||||
<table border="1" cellpadding="7" cellspacing="1" width="624">
|
||||
<tr>
|
||||
<td valign="top" width="45%"><p align="center">Expression</p>
|
||||
</td>
|
||||
<td valign="top" width="45%"><p align="center">Description</p>
|
||||
</td>
|
||||
<td valign="top" width="33%"><p align="center">Compiler</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_object<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is not a reference
|
||||
type, or a (possibly cv-qualified) void type.</td>
|
||||
<td valign="top" width="33%"><p align="center">P</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_standard_scalar<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is a standard
|
||||
arithmetic type, an enumerated type, a pointer or a
|
||||
member pointer.</td>
|
||||
<td valign="top" width="33%"><p align="center">PD</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_extension_scalar<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is an extentions
|
||||
arithmetic type, an enumerated type, a pointer or a
|
||||
member pointer.</td>
|
||||
<td valign="top" width="33%"><p align="center">PD</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_scalar<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is an arithmetic
|
||||
type, an enumerated type, a pointer or a member pointer.</td>
|
||||
<td valign="top" width="33%"><p align="center">PD</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_POD<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is a "Plain
|
||||
Old Data" type (see 3.9 p2&p3). Note that
|
||||
although this requires compiler support to be correct in
|
||||
all cases, if T is a scalar or an array of scalars then
|
||||
we can correctly define T as a POD.</td>
|
||||
<td valign="top" width="33%"><p align="center">PC</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>is_empty<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T is an empty struct
|
||||
or class. If the compiler implements the "zero sized
|
||||
empty base classes" optimisation, then is_empty will
|
||||
correctly guess whether T is empty. Relies upon is_class
|
||||
to determine whether T is a class type - as a result will
|
||||
not compile when passed an enumerated type unless there
|
||||
is compiler support for is_enum.</td>
|
||||
<td valign="top" width="33%"><p align="center">PCD</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>has_trivial_constructor<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T has a trivial
|
||||
default constructor - that is T() is equivalent to memset.</td>
|
||||
<td valign="top" width="33%"><p align="center">PC</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>has_trivial_copy<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T has a trivial copy
|
||||
constructor - that is T(const T&) is equivalent to
|
||||
memcpy.</td>
|
||||
<td valign="top" width="33%"><p align="center">PC</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>has_trivial_assign<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T has a trivial
|
||||
assignment operator - that is if T::operator=(const T&)
|
||||
is equivalent to memcpy.</td>
|
||||
<td valign="top" width="33%"><p align="center">PC</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="45%"><code>has_trivial_destructor<T>::value</code></td>
|
||||
<td valign="top" width="45%">True if T has a trivial
|
||||
destructor - that is if T::~T() has no effect.</td>
|
||||
<td valign="top" width="33%"><p align="center">PC</p>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<h2><a name="cs"></a>Compiler Support Information</h2>
|
||||
|
||||
<p>The legends used in the tables above have the following
|
||||
meanings:</p>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="480">
|
||||
<tr>
|
||||
<td valign="top" width="50%"><p align="center">P</p>
|
||||
</td>
|
||||
<td valign="top" width="90%">Denotes that the class
|
||||
requires support for partial specialisation of class
|
||||
templates to work correctly.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="50%"><p align="center">C</p>
|
||||
</td>
|
||||
<td valign="top" width="90%">Denotes that direct compiler
|
||||
support for that traits class is required.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="50%"><p align="center">D</p>
|
||||
</td>
|
||||
<td valign="top" width="90%">Denotes that the traits
|
||||
class is dependent upon a class that requires direct
|
||||
compiler support.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<p>For those classes that are marked with a D or C, if compiler
|
||||
support is not provided, this type trait may return "false"
|
||||
when the correct value is actually "true". The single
|
||||
exception to this rule is "is_class", which attempts to
|
||||
guess whether or not T is really a class, and may return "true"
|
||||
when the correct value is actually "false". This can
|
||||
happen if: T is a union, T is an enum, or T is a compiler-supplied
|
||||
scalar type that is not specialised for in these type traits.</p>
|
||||
|
||||
<p><i>If there is no compiler support</i>, to ensure that these
|
||||
traits <i>always</i> return the correct values, specialise 'is_enum'
|
||||
for each user-defined enumeration type, 'is_union' for each user-defined
|
||||
union type, 'is_empty' for each user-defined empty composite type,
|
||||
and 'is_POD' for each user-defined POD type. The 'has_*' traits
|
||||
should also be specialized if the user-defined type has those
|
||||
traits and is <i>not</i> a POD.</p>
|
||||
|
||||
<p>The following rules are automatically enforced:</p>
|
||||
|
||||
<p>is_enum implies is_POD</p>
|
||||
|
||||
<p>is_POD implies has_*</p>
|
||||
|
||||
<p>This means, for example, if you have an empty POD-struct, just
|
||||
specialize is_empty and is_POD, which will cause all the has_* to
|
||||
also return true.</p>
|
||||
|
||||
<h2><a name="ec"></a>Example code</h2>
|
||||
|
||||
<p>Type-traits comes with two sample programs: <a
|
||||
href="type_traits_test.cpp">type_traits_test.cpp</a> tests the
|
||||
type traits classes - mostly this is a test of your compiler's
|
||||
support for the concepts used in the type traits implementation,
|
||||
while <a href="algo_opt_examples.cpp">algo_opt_examples.cpp</a>
|
||||
uses the type traits classes to "optimise" some
|
||||
familiar standard library algorithms.</p>
|
||||
|
||||
<p>There are four algorithm examples in algo_opt_examples.cpp:</p>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="0" width="638">
|
||||
<tr>
|
||||
<td valign="top" width="50%"><pre>opt::copy</pre>
|
||||
</td>
|
||||
<td valign="top" width="50%">If the copy operation can be
|
||||
performed using memcpy then does so, otherwise uses a
|
||||
regular element by element copy (<i>c.f.</i> std::copy).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="50%"><pre>opt::fill</pre>
|
||||
</td>
|
||||
<td valign="top" width="50%">If the fill operation can be
|
||||
performed by memset, then does so, otherwise uses a
|
||||
regular element by element assign. Also uses call_traits
|
||||
to optimise how the parameters can be passed (<i>c.f.</i>
|
||||
std::fill).</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="50%"><pre>opt::destroy_array</pre>
|
||||
</td>
|
||||
<td valign="top" width="50%">If the type in the array has
|
||||
a trivial destructor then does nothing, otherwise calls
|
||||
destructors for all elements in the array - this
|
||||
algorithm is the reverse of std::uninitialized_copy / std::uninitialized_fill.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="50%"><pre>opt::iter_swap</pre>
|
||||
</td>
|
||||
<td valign="top" width="50%">Determines whether the
|
||||
iterator is a proxy-iterator: if it is then does a "slow
|
||||
and safe" swap, otherwise calls std::swap on the
|
||||
assumption that std::swap may be specialised for the
|
||||
iterated type.</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p> </p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised 08<sup>th</sup> March 2000</p>
|
||||
|
||||
<p>© 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>
|
||||
</body>
|
||||
</html>
|
103
utility.htm
Normal file
103
utility.htm
Normal file
@ -0,0 +1,103 @@
|
||||
<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>Template functions <a href="#functions next">next() and prior()</a></li>
|
||||
<li>Class <a href="#Class noncopyable">noncopyable</a></li>
|
||||
</ul>
|
||||
<h2>Template <a name="functions next">functions next</a>() 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 : 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
|
||||
-->26 January, 2000<!--webbot bot="Timestamp" endspan i-checksum="38194"
|
||||
-->
|
||||
</p>
|
||||
<p>© 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>
|
Loading…
x
Reference in New Issue
Block a user