mirror of
				https://github.com/boostorg/utility.git
				synced 2025-11-04 02:11:45 +01:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			svn-branch
			...
			svn-branch
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					6a0c70ce27 | 
							
								
								
									
										489
									
								
								c++_type_traits.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										489
									
								
								c++_type_traits.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,489 @@
 | 
			
		||||
<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>C++ Type traits</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
 | 
			
		||||
 | 
			
		||||
<h2 align="center">C++ Type traits</h2>
 | 
			
		||||
<p align="center"><em>by John Maddock and Steve Cleary</em></p>
 | 
			
		||||
<p align="center"><em>This is a draft of an article that will appear in a future
 | 
			
		||||
issue of </em><a href="http://www.ddj.com"><em>Dr Dobb's Journal</em></a></p>
 | 
			
		||||
<p>Generic programming (writing code which works with any data type meeting a
 | 
			
		||||
set of requirements) has become the method of choice for providing reusable
 | 
			
		||||
code. However, there are times in generic programming when "generic"
 | 
			
		||||
just isn't good enough - sometimes the differences between types are too large
 | 
			
		||||
for an efficient generic implementation. This is when the traits technique
 | 
			
		||||
becomes important - by encapsulating those properties that need to be considered
 | 
			
		||||
on a type by type basis inside a traits class, we can minimise the amount of
 | 
			
		||||
code that has to differ from one type to another, and maximise the amount of
 | 
			
		||||
generic code.</p>
 | 
			
		||||
<p>Consider an example: when working with character strings, one common
 | 
			
		||||
operation is to determine the length of a null terminated string. Clearly it's
 | 
			
		||||
possible to write generic code that can do this, but it turns out that there are
 | 
			
		||||
much more efficient methods available: for example, the C library functions <font size="2" face="Courier New">strlen</font>
 | 
			
		||||
and <font size="2" face="Courier New">wcslen</font> are usually written in
 | 
			
		||||
assembler, and with suitable hardware support can be considerably faster than a
 | 
			
		||||
generic version written in C++. The authors of the C++ standard library realised
 | 
			
		||||
this, and abstracted the properties of <font size="2" face="Courier New">char</font>
 | 
			
		||||
and <font size="2" face="Courier New">wchar_t</font> into the class <font size="2" face="Courier New">char_traits</font>.
 | 
			
		||||
Generic code that works with character strings can simply use <font size="2" face="Courier New">char_traits<>::length</font>
 | 
			
		||||
to determine the length of a null terminated string, safe in the knowledge that
 | 
			
		||||
specialisations of <font size="2" face="Courier New">char_traits</font> will use
 | 
			
		||||
the most appropriate method available to them.</p>
 | 
			
		||||
<h4>Type traits</h4>
 | 
			
		||||
<p>Class <font size="2" face="Courier New">char_traits</font> is a classic
 | 
			
		||||
example of a collection of type specific properties wrapped up in a single class
 | 
			
		||||
- what Nathan Myers termed a <i>baggage class</i>[1]. In the Boost type-traits
 | 
			
		||||
library, we[2] have written a set of very specific traits classes, each of which
 | 
			
		||||
encapsulate a single trait from the C++ type system; for example, is a type a
 | 
			
		||||
pointer or a reference type? Or does a type have a trivial constructor, or a
 | 
			
		||||
const-qualifier? The type-traits classes share a unified design: each class has
 | 
			
		||||
a single member <i>value</i>, a compile-time constant that is true if the type
 | 
			
		||||
has the specified property, and false otherwise. As we will show, these classes
 | 
			
		||||
can be used in generic programming to determine the properties of a given type
 | 
			
		||||
and introduce optimisations that are appropriate for that case.</p>
 | 
			
		||||
<p>The type-traits library also contains a set of classes that perform a
 | 
			
		||||
specific transformation on a type; for example, they can remove a top-level
 | 
			
		||||
const or volatile qualifier from a type. Each class that performs a
 | 
			
		||||
transformation defines a single typedef-member <i>type</i> that is the result of
 | 
			
		||||
the transformation. All of the type-traits classes are defined inside namespace <font size="2" face="Courier New">boost</font>;
 | 
			
		||||
for brevity, namespace-qualification is omitted in most of the code samples
 | 
			
		||||
given.</p>
 | 
			
		||||
<h4>Implementation</h4>
 | 
			
		||||
<p>There are far too many separate classes contained in the type-traits library
 | 
			
		||||
to give a full implementation here - see the source code in the Boost library
 | 
			
		||||
for the full details - however, most of the implementation is fairly repetitive
 | 
			
		||||
anyway, so here we will just give you a flavour for how some of the classes are
 | 
			
		||||
implemented. Beginning with possibly the simplest class in the library, is_void<T>
 | 
			
		||||
has a member <i>value</i> that is true only if T is void.</p>
 | 
			
		||||
<pre>template <typename T> 
 | 
			
		||||
struct is_void
 | 
			
		||||
{ static const bool value = false; };
 | 
			
		||||
 | 
			
		||||
template <> 
 | 
			
		||||
struct is_void<void>
 | 
			
		||||
{ static const bool value = true; };</pre>
 | 
			
		||||
<p>Here we define a primary version of the template class <font size="2" face="Courier New">is_void</font>,
 | 
			
		||||
and provide a full-specialisation when T is void. While full specialisation of a
 | 
			
		||||
template class is an important technique, sometimes we need a solution that is
 | 
			
		||||
halfway between a fully generic solution, and a full specialisation. This is
 | 
			
		||||
exactly the situation for which the standards committee defined partial
 | 
			
		||||
template-class specialisation. As an example, consider the class
 | 
			
		||||
boost::is_pointer<T>: here we needed a primary version that handles all
 | 
			
		||||
the cases where T is not a pointer, and a partial specialisation to handle all
 | 
			
		||||
the cases where T is a pointer:</p>
 | 
			
		||||
<pre>template <typename T> 
 | 
			
		||||
struct is_pointer 
 | 
			
		||||
{ static const bool value = false; };
 | 
			
		||||
 | 
			
		||||
template <typename T> 
 | 
			
		||||
struct is_pointer<T*> 
 | 
			
		||||
{ static const bool value = true; };</pre>
 | 
			
		||||
<p>The syntax for partial specialisation is somewhat arcane and could easily
 | 
			
		||||
occupy an article in its own right; like full specialisation, in order to write
 | 
			
		||||
a partial specialisation for a class, you must first declare the primary
 | 
			
		||||
template. The partial specialisation contains an extra <<EFBFBD>> after the
 | 
			
		||||
class name that contains the partial specialisation parameters; these define the
 | 
			
		||||
types that will bind to that partial specialisation rather than the default
 | 
			
		||||
template. The rules for what can appear in a partial specialisation are somewhat
 | 
			
		||||
convoluted, but as a rule of thumb if you can legally write two function
 | 
			
		||||
overloads of the form:</p>
 | 
			
		||||
<pre>void foo(T);
 | 
			
		||||
void foo(U);</pre>
 | 
			
		||||
<p>Then you can also write a partial specialisation of the form:</p>
 | 
			
		||||
<pre>template <typename T>
 | 
			
		||||
class c{ /*details*/ };
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
 | 
			
		||||
class c<U>{ /*details*/ };</pre>
 | 
			
		||||
<p>This rule is by no means foolproof, but it is reasonably simple to remember
 | 
			
		||||
and close enough to the actual rule to be useful for everyday use.</p>
 | 
			
		||||
<p>As a more complex example of partial specialisation consider the class
 | 
			
		||||
remove_bounds<T>. This class defines a single typedef-member <i>type</i>
 | 
			
		||||
that is the same type as T but with any top-level array bounds removed; this is
 | 
			
		||||
an example of a traits class that performs a transformation on a type:</p>
 | 
			
		||||
<pre>template <typename T> 
 | 
			
		||||
struct remove_bounds
 | 
			
		||||
{ typedef T type; };
 | 
			
		||||
 | 
			
		||||
template <typename T, std::size_t N> 
 | 
			
		||||
struct remove_bounds<T[N]>
 | 
			
		||||
{ typedef T type; };</pre>
 | 
			
		||||
<p>The aim of remove_bounds is this: imagine a generic algorithm that is passed
 | 
			
		||||
an array type as a template parameter, <font size="2" face="Courier New">remove_bounds</font>
 | 
			
		||||
provides a means of determining the underlying type of the array. For example <code>remove_bounds<int[4][5]>::type</code>
 | 
			
		||||
would evaluate to the type <code>int[5]</code>. This example also shows that the
 | 
			
		||||
number of template parameters in a partial specialisation does not have to match
 | 
			
		||||
the number in the default template. However, the number of parameters that
 | 
			
		||||
appear after the class name do have to match the number and type of the
 | 
			
		||||
parameters in the default template.</p>
 | 
			
		||||
<h4>Optimised copy</h4>
 | 
			
		||||
<p>As an example of how the type traits classes can be used, consider the
 | 
			
		||||
standard library algorithm copy:</p>
 | 
			
		||||
<pre>template<typename Iter1, typename Iter2>
 | 
			
		||||
Iter2 copy(Iter1 first, Iter1 last, Iter2 out);</pre>
 | 
			
		||||
<p>Obviously, there's no problem writing a generic version of copy that works
 | 
			
		||||
for all iterator types Iter1 and Iter2; however, there are some circumstances
 | 
			
		||||
when the copy operation can best be performed by a call to <font size="2" face="Courier New">memcpy</font>.
 | 
			
		||||
In order to implement copy in terms of <font size="2" face="Courier New">memcpy</font>
 | 
			
		||||
all of the following conditions need to be met:</p>
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>Both of the iterator types Iter1 and Iter2 must be pointers.</li>
 | 
			
		||||
  <li>Both Iter1 and Iter2 must point to the same type - excluding <font size="2" face="Courier New">const</font>
 | 
			
		||||
    and <font size="2" face="Courier New">volatile</font>-qualifiers.</li>
 | 
			
		||||
  <li>The type pointed to by Iter1 must have a trivial assignment operator.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<p>By trivial assignment operator we mean that the type is either a scalar
 | 
			
		||||
type[3] or:</p>
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>The type has no user defined assignment operator.</li>
 | 
			
		||||
  <li>The type does not have any data members that are references.</li>
 | 
			
		||||
  <li>All base classes, and all data member objects must have trivial assignment
 | 
			
		||||
    operators.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<p>If all these conditions are met then a type can be copied using <font size="2" face="Courier New">memcpy</font>
 | 
			
		||||
rather than using a compiler generated assignment operator. The type-traits
 | 
			
		||||
library provides a class <i>has_trivial_assign</i>, such that <code>has_trivial_assign<T>::value</code>
 | 
			
		||||
is true only if T has a trivial assignment operator. This class "just
 | 
			
		||||
works" for scalar types, but has to be explicitly specialised for
 | 
			
		||||
class/struct types that also happen to have a trivial assignment operator. In
 | 
			
		||||
other words if <i>has_trivial_assign</i> gives the wrong answer, it will give
 | 
			
		||||
the "safe" wrong answer - that trivial assignment is not allowable.</p>
 | 
			
		||||
<p>The code for an optimised version of copy that uses <font size="2" face="Courier New">memcpy</font>
 | 
			
		||||
where appropriate is given in listing 1. The code begins by defining a template
 | 
			
		||||
class <i>copier</i>, that takes a single Boolean template parameter, and has a
 | 
			
		||||
static template member function <font size="2" face="Courier New">do_copy</font>
 | 
			
		||||
which performs the generic version of <font size="2">copy</font> (in other words
 | 
			
		||||
the "slow but safe version"). Following that there is a specialisation
 | 
			
		||||
for <i>copier<true></i>: again this defines a static template member
 | 
			
		||||
function <font size="2" face="Courier New">do_copy</font>, but this version uses
 | 
			
		||||
memcpy to perform an "optimised" copy.</p>
 | 
			
		||||
<p>In order to complete the implementation, what we need now is a version of
 | 
			
		||||
copy, that calls <code>copier<true>::do_copy</code> if it is safe to use <font size="2" face="Courier New">memcpy</font>,
 | 
			
		||||
and otherwise calls <code>copier<false>::do_copy</code> to do a
 | 
			
		||||
"generic" copy. This is what the version in listing 1 does. To
 | 
			
		||||
understand how the code works look at the code for <font size="2" face="Courier New">copy</font>
 | 
			
		||||
and consider first the two typedefs <i>v1_t</i> and <i>v2_t</i>. These use <code>std::iterator_traits<Iter1>::value_type</code>
 | 
			
		||||
to determine what type the two iterators point to, and then feed the result into
 | 
			
		||||
another type-traits class <i>remove_cv</i> that removes the top-level
 | 
			
		||||
const-volatile-qualifiers: this will allow copy to compare the two types without
 | 
			
		||||
regard to const- or volatile-qualifiers. Next, <font size="2" face="Courier New">copy</font>
 | 
			
		||||
declares an enumerated value <i>can_opt</i> that will become the template
 | 
			
		||||
parameter to copier - declaring this here as a constant is really just a
 | 
			
		||||
convenience - the value could be passed directly to class <font size="2" face="Courier New">copier</font>.
 | 
			
		||||
The value of <i>can_opt</i> is computed by verifying that all of the following
 | 
			
		||||
are true:</p>
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>first that the two iterators point to the same type by using a type-traits
 | 
			
		||||
    class <i>is_same</i>.</li>
 | 
			
		||||
  <li>Then that both iterators are real pointers - using the class <i>is_pointer</i>
 | 
			
		||||
    described above.</li>
 | 
			
		||||
  <li>Finally that the pointed-to types have a trivial assignment operator using
 | 
			
		||||
    <i>has_trivial_assign</i>.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<p>Finally we can use the value of <i>can_opt</i> as the template argument to
 | 
			
		||||
copier - this version of copy will now adapt to whatever parameters are passed
 | 
			
		||||
to it, if its possible to use <font size="2" face="Courier New">memcpy</font>,
 | 
			
		||||
then it will do so, otherwise it will use a generic copy.</p>
 | 
			
		||||
<h4>Was it worth it?</h4>
 | 
			
		||||
<p>It has often been repeated in these columns that "premature optimisation
 | 
			
		||||
is the root of all evil" [4]. So the question must be asked: was our
 | 
			
		||||
optimisation premature? To put this in perspective the timings for our version
 | 
			
		||||
of copy compared a conventional generic copy[5] are shown in table 1.</p>
 | 
			
		||||
<p>Clearly the optimisation makes a difference in this case; but, to be fair,
 | 
			
		||||
the timings are loaded to exclude cache miss effects - without this accurate
 | 
			
		||||
comparison between algorithms becomes difficult. However, perhaps we can add a
 | 
			
		||||
couple of caveats to the premature optimisation rule:</p>
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>If you use the right algorithm for the job in the first place then
 | 
			
		||||
    optimisation will not be required; in some cases, <font size="2" face="Courier New">memcpy</font>
 | 
			
		||||
    is the right algorithm.</li>
 | 
			
		||||
  <li>If a component is going to be reused in many places by many people then
 | 
			
		||||
    optimisations may well be worthwhile where they would not be so for a single
 | 
			
		||||
    case - in other words, the likelihood that the optimisation will be
 | 
			
		||||
    absolutely necessary somewhere, sometime is that much higher. Just as
 | 
			
		||||
    importantly the perceived value of the stock implementation will be higher:
 | 
			
		||||
    there is no point standardising an algorithm if users reject it on the
 | 
			
		||||
    grounds that there are better, more heavily optimised versions available.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<h4>Table 1: Time taken to copy 1000 elements using copy<const T*, T*>
 | 
			
		||||
(times in micro-seconds)</h4>
 | 
			
		||||
<table border="1" cellpadding="7" cellspacing="1" width="529">
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="33%">
 | 
			
		||||
      <p align="center">Version</p>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="33%">
 | 
			
		||||
      <p align="center">T</p>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="33%">
 | 
			
		||||
      <p align="center">Time</p>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="33%">"Optimised" copy</td>
 | 
			
		||||
    <td valign="top" width="33%">char</td>
 | 
			
		||||
    <td valign="top" width="33%">0.99</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="33%">Conventional copy</td>
 | 
			
		||||
    <td valign="top" width="33%">char</td>
 | 
			
		||||
    <td valign="top" width="33%">8.07</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="33%">"Optimised" copy</td>
 | 
			
		||||
    <td valign="top" width="33%">int</td>
 | 
			
		||||
    <td valign="top" width="33%">2.52</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="33%">Conventional copy</td>
 | 
			
		||||
    <td valign="top" width="33%">int</td>
 | 
			
		||||
    <td valign="top" width="33%">8.02</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
</table>
 | 
			
		||||
<p> </p>
 | 
			
		||||
<h4>Pair of References</h4>
 | 
			
		||||
<p>The optimised copy example shows how type traits may be used to perform
 | 
			
		||||
optimisation decisions at compile-time. Another important usage of type traits
 | 
			
		||||
is to allow code to compile that otherwise would not do so unless excessive
 | 
			
		||||
partial specialization is used. This is possible by delegating partial
 | 
			
		||||
specialization to the type traits classes. Our example for this form of usage is
 | 
			
		||||
a pair that can hold references [6].</p>
 | 
			
		||||
<p>First, let us examine the definition of "std::pair", omitting the
 | 
			
		||||
comparision operators, default constructor, and template copy constructor for
 | 
			
		||||
simplicity:</p>
 | 
			
		||||
<pre>template <typename T1, typename T2> 
 | 
			
		||||
struct pair 
 | 
			
		||||
{
 | 
			
		||||
  typedef T1 first_type;
 | 
			
		||||
  typedef T2 second_type;
 | 
			
		||||
 | 
			
		||||
  T1 first;
 | 
			
		||||
  T2 second;
 | 
			
		||||
 | 
			
		||||
  pair(const T1 & nfirst, const T2 & nsecond)
 | 
			
		||||
  :first(nfirst), second(nsecond) { }
 | 
			
		||||
};</pre>
 | 
			
		||||
<p>Now, this "pair" cannot hold references as it currently stands,
 | 
			
		||||
because the constructor would require taking a reference to a reference, which
 | 
			
		||||
is currently illegal [7]. Let us consider what the constructor's parameters
 | 
			
		||||
would have to be in order to allow "pair" to hold non-reference types,
 | 
			
		||||
references, and constant references:</p>
 | 
			
		||||
<table border="1" cellpadding="7" cellspacing="1" width="638">
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="50%">Type of "T1"</td>
 | 
			
		||||
    <td valign="top" width="50%">Type of parameter to initializing constructor</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="50%">
 | 
			
		||||
      <pre>T</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="50%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="50%">
 | 
			
		||||
      <pre>T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="50%">
 | 
			
		||||
      <pre>T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="50%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="50%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
</table>
 | 
			
		||||
<p>A little familiarity with the type traits classes allows us to construct a
 | 
			
		||||
single mapping that allows us to determine the type of parameter from the type
 | 
			
		||||
of the contained class. The type traits classes provide a transformation "add_reference",
 | 
			
		||||
which adds a reference to its type, unless it is already a reference.</p>
 | 
			
		||||
<table border="1" cellpadding="7" cellspacing="1" width="580">
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="21%">Type of "T1"</td>
 | 
			
		||||
    <td valign="top" width="27%">Type of "const T1"</td>
 | 
			
		||||
    <td valign="top" width="53%">Type of "add_reference<const
 | 
			
		||||
      T1>::type"</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="21%">
 | 
			
		||||
      <pre>T</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="27%">
 | 
			
		||||
      <pre>const T</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="53%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="21%">
 | 
			
		||||
      <pre>T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="27%">
 | 
			
		||||
      <pre>T & [8]</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="53%">
 | 
			
		||||
      <pre>T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="21%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="27%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="53%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
</table>
 | 
			
		||||
<p>This allows us to build a primary template definition for "pair"
 | 
			
		||||
that can contain non-reference types, reference types, and constant reference
 | 
			
		||||
types:</p>
 | 
			
		||||
<pre>template <typename T1, typename T2> 
 | 
			
		||||
struct pair 
 | 
			
		||||
{
 | 
			
		||||
  typedef T1 first_type;
 | 
			
		||||
  typedef T2 second_type;
 | 
			
		||||
 | 
			
		||||
  T1 first;
 | 
			
		||||
  T2 second;
 | 
			
		||||
 | 
			
		||||
  pair(boost::add_reference<const T1>::type nfirst,
 | 
			
		||||
       boost::add_reference<const T2>::type nsecond)
 | 
			
		||||
  :first(nfirst), second(nsecond) { }
 | 
			
		||||
};</pre>
 | 
			
		||||
<p>Add back in the standard comparision operators, default constructor, and
 | 
			
		||||
template copy constructor (which are all the same), and you have a std::pair
 | 
			
		||||
that can hold reference types!</p>
 | 
			
		||||
<p>This same extension <i>could</i> have been done using partial template
 | 
			
		||||
specialization of "pair", but to specialize "pair" in this
 | 
			
		||||
way would require three partial specializations, plus the primary template. Type
 | 
			
		||||
traits allows us to define a single primary template that adjusts itself
 | 
			
		||||
auto-magically to any of these partial specializations, instead of a brute-force
 | 
			
		||||
partial specialization approach. Using type traits in this fashion allows
 | 
			
		||||
programmers to delegate partial specialization to the type traits classes,
 | 
			
		||||
resulting in code that is easier to maintain and easier to understand.</p>
 | 
			
		||||
<h4>Conclusion</h4>
 | 
			
		||||
<p>We hope that in this article we have been able to give you some idea of what
 | 
			
		||||
type-traits are all about. A more complete listing of the available classes are
 | 
			
		||||
in the boost documentation, along with further examples using type traits.
 | 
			
		||||
Templates have enabled C++ uses to take the advantage of the code reuse that
 | 
			
		||||
generic programming brings; hopefully this article has shown that generic
 | 
			
		||||
programming does not have to sink to the lowest common denominator, and that
 | 
			
		||||
templates can be optimal as well as generic.</p>
 | 
			
		||||
<h4>Acknowledgements</h4>
 | 
			
		||||
<p>The authors would like to thank Beman Dawes and Howard Hinnant for their
 | 
			
		||||
helpful comments when preparing this article.</p>
 | 
			
		||||
<h4>References</h4>
 | 
			
		||||
<ol>
 | 
			
		||||
  <li>Nathan C. Myers, C++ Report, June 1995.</li>
 | 
			
		||||
  <li>The type traits library is based upon contributions by Steve Cleary, Beman
 | 
			
		||||
    Dawes, Howard Hinnant and John Maddock: it can be found at www.boost.org.</li>
 | 
			
		||||
  <li>A scalar type is an arithmetic type (i.e. a built-in integer or floating
 | 
			
		||||
    point type), an enumeration type, a pointer, a pointer to member, or a
 | 
			
		||||
    const- or volatile-qualified version of one of these types.</li>
 | 
			
		||||
  <li>This quote is from Donald Knuth, ACM Computing Surveys, December 1974, pg
 | 
			
		||||
    268.</li>
 | 
			
		||||
  <li>The test code is available as part of the boost utility library (see
 | 
			
		||||
    algo_opt_examples.cpp), the code was compiled with gcc 2.95 with all
 | 
			
		||||
    optimisations turned on, tests were conducted on a 400MHz Pentium II machine
 | 
			
		||||
    running Microsoft Windows 98.</li>
 | 
			
		||||
  <li>John Maddock and Howard Hinnant have submitted a "compressed_pair"
 | 
			
		||||
    library to Boost, which uses a technique similar to the one described here
 | 
			
		||||
    to hold references. Their pair also uses type traits to determine if any of
 | 
			
		||||
    the types are empty, and will derive instead of contain to conserve space --
 | 
			
		||||
    hence the name "compressed".</li>
 | 
			
		||||
  <li>This is actually an issue with the C++ Core Language Working Group (issue
 | 
			
		||||
    #106), submitted by Bjarne Stroustrup. The tentative resolution is to allow
 | 
			
		||||
    a "reference to a reference to T" to mean the same thing as a
 | 
			
		||||
    "reference to T", but only in template instantiation, in a method
 | 
			
		||||
    similar to multiple cv-qualifiers.</li>
 | 
			
		||||
  <li>For those of you who are wondering why this shouldn't be const-qualified,
 | 
			
		||||
    remember that references are always implicitly constant (for example, you
 | 
			
		||||
    can't re-assign a reference). Remember also that "const T &"
 | 
			
		||||
    is something completely different. For this reason, cv-qualifiers on
 | 
			
		||||
    template type arguments that are references are ignored.</li>
 | 
			
		||||
</ol>
 | 
			
		||||
<h2>Listing 1</h2>
 | 
			
		||||
<pre>namespace detail{
 | 
			
		||||
 | 
			
		||||
template <bool b>
 | 
			
		||||
struct copier
 | 
			
		||||
{
 | 
			
		||||
   template<typename I1, typename I2>
 | 
			
		||||
   static I2 do_copy(I1 first, 
 | 
			
		||||
                     I1 last, I2 out);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <bool b>
 | 
			
		||||
template<typename I1, typename I2>
 | 
			
		||||
I2 copier<b>::do_copy(I1 first, 
 | 
			
		||||
                      I1 last, 
 | 
			
		||||
                      I2 out)
 | 
			
		||||
{
 | 
			
		||||
   while(first != last)
 | 
			
		||||
   {
 | 
			
		||||
      *out = *first;
 | 
			
		||||
      ++out;
 | 
			
		||||
      ++first;
 | 
			
		||||
   }
 | 
			
		||||
   return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct copier<true>
 | 
			
		||||
{
 | 
			
		||||
   template<typename I1, typename I2>
 | 
			
		||||
   static I2* do_copy(I1* first, I1* last, I2* out)
 | 
			
		||||
   {
 | 
			
		||||
      memcpy(out, first, (last-first)*sizeof(I2));
 | 
			
		||||
      return out+(last-first);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename I1, typename I2>
 | 
			
		||||
inline I2 copy(I1 first, I1 last, I2 out)
 | 
			
		||||
{
 | 
			
		||||
   typedef typename 
 | 
			
		||||
    boost::remove_cv<
 | 
			
		||||
     typename std::iterator_traits<I1>
 | 
			
		||||
      ::value_type>::type v1_t;
 | 
			
		||||
 | 
			
		||||
   typedef typename 
 | 
			
		||||
    boost::remove_cv<
 | 
			
		||||
     typename std::iterator_traits<I2>
 | 
			
		||||
      ::value_type>::type v2_t;
 | 
			
		||||
 | 
			
		||||
   enum{ can_opt = 
 | 
			
		||||
      boost::is_same<v1_t, v2_t>::value
 | 
			
		||||
      && boost::is_pointer<I1>::value
 | 
			
		||||
      && boost::is_pointer<I2>::value
 | 
			
		||||
      && boost::
 | 
			
		||||
      has_trivial_assign<v1_t>::value 
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   return detail::copier<can_opt>::
 | 
			
		||||
      do_copy(first, last, out);
 | 
			
		||||
}</pre>
 | 
			
		||||
<hr>
 | 
			
		||||
<p><EFBFBD> Copyright John Maddock and Steve Cleary, 2000</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										762
									
								
								call_traits.htm
									
									
									
									
									
								
							
							
						
						
									
										762
									
								
								call_traits.htm
									
									
									
									
									
								
							@@ -1,762 +0,0 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type"
 | 
			
		||||
content="text/html; charset=iso-8859-1">
 | 
			
		||||
<meta name="Template"
 | 
			
		||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
 | 
			
		||||
<title>Call Traits</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
 | 
			
		||||
vlink="#800080">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../c++boost.gif" width="276" height="86">Header
 | 
			
		||||
<<a href="../../boost/detail/call_traits.hpp">boost/call_traits.hpp</a>></h1>
 | 
			
		||||
 | 
			
		||||
<p>All of the contents of <boost/call_traits.hpp> are
 | 
			
		||||
defined inside namespace boost.</p>
 | 
			
		||||
 | 
			
		||||
<p>The template class call_traits<T> encapsulates the
 | 
			
		||||
"best" method to pass a parameter of some type T to or
 | 
			
		||||
from a function, and consists of a collection of typedefs defined
 | 
			
		||||
as in the table below. The purpose of call_traits is to ensure
 | 
			
		||||
that problems like "<a href="#refs">references to references</a>"
 | 
			
		||||
never occur, and that parameters are passed in the most efficient
 | 
			
		||||
manner possible (see <a href="#examples">examples</a>). In each
 | 
			
		||||
case if your existing practice is to use the type defined on the
 | 
			
		||||
left, then replace it with the call_traits defined type on the
 | 
			
		||||
right. </p>
 | 
			
		||||
 | 
			
		||||
<p>Note that for compilers that do not support either partial
 | 
			
		||||
specialization or member templates, no benefit will occur from
 | 
			
		||||
using call_traits: the call_traits defined types will always be
 | 
			
		||||
the same as the existing practice in this case. In addition if
 | 
			
		||||
only member templates and not partial template specialisation is
 | 
			
		||||
support by the compiler (for example Visual C++ 6) then
 | 
			
		||||
call_traits can not be used with array types (although it can be
 | 
			
		||||
used to solve the reference to reference problem).</p>
 | 
			
		||||
 | 
			
		||||
<table border="0" cellpadding="7" cellspacing="1" width="797">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#008080"><p
 | 
			
		||||
        align="center">Existing practice</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="35%" bgcolor="#008080"><p
 | 
			
		||||
        align="center">call_traits equivalent</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="32%" bgcolor="#008080"><p
 | 
			
		||||
        align="center">Description</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="16%" bgcolor="#008080"><p
 | 
			
		||||
        align="center">Notes</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">T<br>
 | 
			
		||||
        (return by value)</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="35%"><p align="center"><code>call_traits<T>::value_type</code></p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="32%">Defines a type that
 | 
			
		||||
        represents the "value" of type T. Use this for
 | 
			
		||||
        functions that return by value, or possibly for stored
 | 
			
		||||
        values of type T.</td>
 | 
			
		||||
        <td valign="top" width="16%"><p align="center">2</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">T&<br>
 | 
			
		||||
        (return value)</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="35%"><p align="center"><code>call_traits<T>::reference</code></p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="32%">Defines a type that
 | 
			
		||||
        represents a reference to type T. Use for functions that
 | 
			
		||||
        would normally return a T&.</td>
 | 
			
		||||
        <td valign="top" width="16%"><p align="center">1</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        T&<br>
 | 
			
		||||
        (return value)</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="35%"><p align="center"><code>call_traits<T>::const_reference</code></p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="32%">Defines a type that
 | 
			
		||||
        represents a constant reference to type T. Use for
 | 
			
		||||
        functions that would normally return a const T&.</td>
 | 
			
		||||
        <td valign="top" width="16%"><p align="center">1</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        T&<br>
 | 
			
		||||
        (function parameter)</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="35%"><p align="center"><code>call_traits<T>::param_type</code></p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="32%">Defines a type that
 | 
			
		||||
        represents the "best" way to pass a parameter
 | 
			
		||||
        of type T to a function.</td>
 | 
			
		||||
        <td valign="top" width="16%"><p align="center">1,3</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p>Notes:</p>
 | 
			
		||||
 | 
			
		||||
<ol>
 | 
			
		||||
    <li>If T is already reference type, then call_traits is
 | 
			
		||||
        defined such that <a href="#refs">references to
 | 
			
		||||
        references</a> do not occur (requires partial
 | 
			
		||||
        specialization).</li>
 | 
			
		||||
    <li>If T is an array type, then call_traits defines <code>value_type</code>
 | 
			
		||||
        as a "constant pointer to type" rather than an
 | 
			
		||||
        "array of type" (requires partial
 | 
			
		||||
        specialization). Note that if you are using value_type as
 | 
			
		||||
        a stored value then this will result in storing a "constant
 | 
			
		||||
        pointer to an array" rather than the array itself.
 | 
			
		||||
        This may or may not be a good thing depending upon what
 | 
			
		||||
        you actually need (in other words take care!).</li>
 | 
			
		||||
    <li>If T is a small built in type or a pointer, then <code>param_type</code>
 | 
			
		||||
        is defined as <code>T const</code>, instead of <code>T
 | 
			
		||||
        const&</code>. This can improve the ability of the
 | 
			
		||||
        compiler to optimize loops in the body of the function if
 | 
			
		||||
        they depend upon the passed parameter, the semantics of
 | 
			
		||||
        the passed parameter is otherwise unchanged (requires
 | 
			
		||||
        partial specialization).</li>
 | 
			
		||||
</ol>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<h3>Copy constructibility</h3>
 | 
			
		||||
 | 
			
		||||
<p>The following table defines which call_traits types can always
 | 
			
		||||
be copy-constructed from which other types, those entries marked
 | 
			
		||||
with a '?' are true only if and only if T is copy constructible:</p>
 | 
			
		||||
 | 
			
		||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"> </td>
 | 
			
		||||
        <td valign="top" colspan="5" width="85%"
 | 
			
		||||
        bgcolor="#008080"><p align="center">To:</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#008080">From:</td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">T</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">value_type</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">reference</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">const_reference</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">param_type</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">N</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">N</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">N</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">N</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">N</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">N</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<p>If T is an assignable type the following assignments are
 | 
			
		||||
possible:</p>
 | 
			
		||||
 | 
			
		||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"> </td>
 | 
			
		||||
        <td valign="top" colspan="5" width="85%"
 | 
			
		||||
        bgcolor="#008080"><p align="center">To:</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#008080">From:</td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">T</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">value_type</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">reference</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">const_reference</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">param_type</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<h3><a name="examples"></a>Examples</h3>
 | 
			
		||||
 | 
			
		||||
<p>The following table shows the effect that call_traits has on
 | 
			
		||||
various types, the table assumes that the compiler supports
 | 
			
		||||
partial specialization: if it doesn't then all types behave in
 | 
			
		||||
the same way as the entry for "myclass", and
 | 
			
		||||
call_traits can not be used with reference or array types.</p>
 | 
			
		||||
 | 
			
		||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"> </td>
 | 
			
		||||
        <td valign="top" colspan="5" width="85%"
 | 
			
		||||
        bgcolor="#008080"><p align="center">Call_traits type:</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#008080"><p
 | 
			
		||||
        align="center">Original type T</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">value_type</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">reference</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">const_reference</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">param_type</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">Applies to:</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">myclass</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">myclass</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">myclass&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        myclass&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">myclass
 | 
			
		||||
        const&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All user
 | 
			
		||||
        defined types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">int</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int const</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All small
 | 
			
		||||
        built-in types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">int*</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int*</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int*&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int*const&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int* const</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All
 | 
			
		||||
        pointer types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All
 | 
			
		||||
        reference types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">const int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All
 | 
			
		||||
        constant-references.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">int[3]</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int*</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int(&)[3]</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int(&)[3]</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int*
 | 
			
		||||
        const</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All array
 | 
			
		||||
        types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">const int[3]</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int*</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int(&)[3]</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int(&)[3]</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int*
 | 
			
		||||
        const</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All
 | 
			
		||||
        constant-array types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<h4>Example 1:</h4>
 | 
			
		||||
 | 
			
		||||
<p>The following class is a trivial class that stores some type T
 | 
			
		||||
by value (see the <a href="call_traits_test.cpp">call_traits_test.cpp</a>
 | 
			
		||||
file), the aim is to illustrate how each of the available
 | 
			
		||||
call_traits typedefs may be used:</p>
 | 
			
		||||
 | 
			
		||||
<pre>template <class T>
 | 
			
		||||
struct contained
 | 
			
		||||
{
 | 
			
		||||
   // define our typedefs first, arrays are stored by value
 | 
			
		||||
   // so value_type is not the same as result_type:
 | 
			
		||||
   typedef typename boost::call_traits<T>::param_type       param_type;
 | 
			
		||||
   typedef typename boost::call_traits<T>::reference        reference;
 | 
			
		||||
   typedef typename boost::call_traits<T>::const_reference  const_reference;
 | 
			
		||||
   typedef T                                                value_type;
 | 
			
		||||
   typedef typename boost::call_traits<T>::value_type       result_type;
 | 
			
		||||
 | 
			
		||||
   // stored value:
 | 
			
		||||
   value_type v_;
 | 
			
		||||
   
 | 
			
		||||
   // constructors:
 | 
			
		||||
   contained() {}
 | 
			
		||||
   contained(param_type p) : v_(p){}
 | 
			
		||||
   // return byval:
 | 
			
		||||
   result_type value() { return v_; }
 | 
			
		||||
   // return by_ref:
 | 
			
		||||
   reference get() { return v_; }
 | 
			
		||||
   const_reference const_get()const { return v_; }
 | 
			
		||||
   // pass value:
 | 
			
		||||
   void call(param_type p){}
 | 
			
		||||
 | 
			
		||||
};</pre>
 | 
			
		||||
 | 
			
		||||
<h4><a name="refs"></a>Example 2 (the reference to reference
 | 
			
		||||
problem):</h4>
 | 
			
		||||
 | 
			
		||||
<p>Consider the definition of std::binder1st:</p>
 | 
			
		||||
 | 
			
		||||
<pre>template <class Operation> 
 | 
			
		||||
class binder1st : 
 | 
			
		||||
   public unary_function<typename Operation::second_argument_type, typename Operation::result_type> 
 | 
			
		||||
{ 
 | 
			
		||||
protected: 
 | 
			
		||||
   Operation op; 
 | 
			
		||||
   typename Operation::first_argument_type value; 
 | 
			
		||||
public: 
 | 
			
		||||
   binder1st(const Operation& x, const typename Operation::first_argument_type& y); 
 | 
			
		||||
   typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const; 
 | 
			
		||||
}; </pre>
 | 
			
		||||
 | 
			
		||||
<p>Now consider what happens in the relatively common case that
 | 
			
		||||
the functor takes its second argument as a reference, that
 | 
			
		||||
implies that <code>Operation::second_argument_type</code> is a
 | 
			
		||||
reference type, <code>operator()</code> will now end up taking a
 | 
			
		||||
reference to a reference as an argument, and that is not
 | 
			
		||||
currently legal. The solution here is to modify <code>operator()</code>
 | 
			
		||||
to use call_traits:</p>
 | 
			
		||||
 | 
			
		||||
<pre>typename Operation::result_type operator()(typename call_traits<typename Operation::second_argument_type>::param_type x) const;</pre>
 | 
			
		||||
 | 
			
		||||
<p>Now in the case that <code>Operation::second_argument_type</code>
 | 
			
		||||
is a reference type, the argument is passed as a reference, and
 | 
			
		||||
the no "reference to reference" occurs.</p>
 | 
			
		||||
 | 
			
		||||
<h4><a name="ex3"></a>Example 3 (the make_pair problem):</h4>
 | 
			
		||||
 | 
			
		||||
<p>If we pass the name of an array as one (or both) arguments to <code>std::make_pair</code>,
 | 
			
		||||
then template argument deduction deduces the passed parameter as
 | 
			
		||||
"const reference to array of T", this also applies to
 | 
			
		||||
string literals (which are really array literals). Consequently
 | 
			
		||||
instead of returning a pair of pointers, it tries to return a
 | 
			
		||||
pair of arrays, and since an array type is not copy-constructible
 | 
			
		||||
the code fails to compile. One solution is to explicitly cast the
 | 
			
		||||
arguments to make_pair to pointers, but call_traits provides a
 | 
			
		||||
better (i.e. automatic) solution (and one that works safely even
 | 
			
		||||
in generic code where the cast might do the wrong thing):</p>
 | 
			
		||||
 | 
			
		||||
<pre>template <class T1, class T2>
 | 
			
		||||
std::pair<
 | 
			
		||||
   typename boost::call_traits<T1>::value_type, 
 | 
			
		||||
   typename boost::call_traits<T2>::value_type> 
 | 
			
		||||
      make_pair(const T1& t1, const T2& t2)
 | 
			
		||||
{
 | 
			
		||||
   return std::pair<
 | 
			
		||||
      typename boost::call_traits<T1>::value_type, 
 | 
			
		||||
      typename boost::call_traits<T2>::value_type>(t1, t2);
 | 
			
		||||
}</pre>
 | 
			
		||||
 | 
			
		||||
<p>Here, the deduced argument types will be automatically
 | 
			
		||||
degraded to pointers if the deduced types are arrays, similar
 | 
			
		||||
situations occur in the standard binders and adapters: in
 | 
			
		||||
principle in any function that "wraps" a temporary
 | 
			
		||||
whose type is deduced. Note that the function arguments to
 | 
			
		||||
make_pair are not expressed in terms of call_traits: doing so
 | 
			
		||||
would prevent template argument deduction from functioning.</p>
 | 
			
		||||
 | 
			
		||||
<h4><a name="ex4"></a>Example 4 (optimising fill):</h4>
 | 
			
		||||
 | 
			
		||||
<p>The call_traits template will "optimize" the passing
 | 
			
		||||
of a small built-in type as a function parameter, this mainly has
 | 
			
		||||
an effect when the parameter is used within a loop body. In the
 | 
			
		||||
following example (see <a href="algo_opt_examples.cpp">algo_opt_examples.cpp</a>),
 | 
			
		||||
a version of std::fill is optimized in two ways: if the type
 | 
			
		||||
passed is a single byte built-in type then std::memset is used to
 | 
			
		||||
effect the fill, otherwise a conventional C++ implemention is
 | 
			
		||||
used, but with the passed parameter "optimized" using
 | 
			
		||||
call_traits:</p>
 | 
			
		||||
 | 
			
		||||
<pre>namespace detail{
 | 
			
		||||
 | 
			
		||||
template <bool opt>
 | 
			
		||||
struct filler
 | 
			
		||||
{
 | 
			
		||||
   template <typename I, typename T>
 | 
			
		||||
   static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val);
 | 
			
		||||
   {
 | 
			
		||||
      while(first != last)
 | 
			
		||||
      {
 | 
			
		||||
         *first = val;
 | 
			
		||||
         ++first;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct filler<true>
 | 
			
		||||
{
 | 
			
		||||
   template <typename I, typename T>
 | 
			
		||||
   static void do_fill(I first, I last, T val)
 | 
			
		||||
   {
 | 
			
		||||
      memset(first, val, last-first);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class I, class T>
 | 
			
		||||
inline void fill(I first, I last, const T& val)
 | 
			
		||||
{
 | 
			
		||||
   enum{ can_opt = boost::is_pointer<I>::value
 | 
			
		||||
                   && boost::is_arithmetic<T>::value
 | 
			
		||||
                   && (sizeof(T) == 1) };
 | 
			
		||||
   typedef detail::filler<can_opt> filler_t;
 | 
			
		||||
   filler_t::template do_fill<I,T>(first, last, val);
 | 
			
		||||
}</pre>
 | 
			
		||||
 | 
			
		||||
<p>Footnote: the reason that this is "optimal" for
 | 
			
		||||
small built-in types is that with the value passed as "T
 | 
			
		||||
const" instead of "const T&" the compiler is
 | 
			
		||||
able to tell both that the value is constant and that it is free
 | 
			
		||||
of aliases. With this information the compiler is able to cache
 | 
			
		||||
the passed value in a register, unroll the loop, or use
 | 
			
		||||
explicitly parallel instructions: if any of these are supported.
 | 
			
		||||
Exactly how much mileage you will get from this depends upon your
 | 
			
		||||
compiler - we could really use some accurate benchmarking
 | 
			
		||||
software as part of boost for cases like this.</p>
 | 
			
		||||
 | 
			
		||||
<p>Note that the function arguments to fill are not expressed in
 | 
			
		||||
terms of call_traits: doing so would prevent template argument
 | 
			
		||||
deduction from functioning. Instead fill acts as a "thin
 | 
			
		||||
wrapper" that is there to perform template argument
 | 
			
		||||
deduction, the compiler will optimise away the call to fill all
 | 
			
		||||
together, replacing it with the call to filler<>::do_fill,
 | 
			
		||||
which does use call_traits.</p>
 | 
			
		||||
 | 
			
		||||
<h3>Rationale</h3>
 | 
			
		||||
 | 
			
		||||
<p>The following notes are intended to briefly describe the
 | 
			
		||||
rational behind choices made in call_traits.</p>
 | 
			
		||||
 | 
			
		||||
<p>All user-defined types follow "existing practice"
 | 
			
		||||
and need no comment.</p>
 | 
			
		||||
 | 
			
		||||
<p>Small built-in types (what the standard calls fundamental
 | 
			
		||||
types [3.9.1]) differ from existing practice only in the <i>param_type</i>
 | 
			
		||||
typedef. In this case passing "T const" is compatible
 | 
			
		||||
with existing practice, but may improve performance in some cases
 | 
			
		||||
(see <a href="#ex4">Example 4</a>), in any case this should never
 | 
			
		||||
be any worse than existing practice.</p>
 | 
			
		||||
 | 
			
		||||
<p>Pointers follow the same rational as small built-in types.</p>
 | 
			
		||||
 | 
			
		||||
<p>For reference types the rational follows <a href="#refs">Example
 | 
			
		||||
2</a> - references to references are not allowed, so the
 | 
			
		||||
call_traits members must be defined such that these problems do
 | 
			
		||||
not occur. There is a proposal to modify the language such that
 | 
			
		||||
"a reference to a reference is a reference" (issue #106,
 | 
			
		||||
submitted by Bjarne Stroustrup), call_traits<T>::value_type
 | 
			
		||||
and call_traits<T>::param_type both provide the same effect
 | 
			
		||||
as that proposal, without the need for a language change (in
 | 
			
		||||
other words it's a workaround).</p>
 | 
			
		||||
 | 
			
		||||
<p>For array types, a function that takes an array as an argument
 | 
			
		||||
will degrade the array type to a pointer type: this means that
 | 
			
		||||
the type of the actual parameter is different from its declared
 | 
			
		||||
type, something that can cause endless problems in template code
 | 
			
		||||
that relies on the declared type of a parameter. For example:</p>
 | 
			
		||||
 | 
			
		||||
<pre>template <class T>
 | 
			
		||||
struct A
 | 
			
		||||
{
 | 
			
		||||
   void foo(T t);
 | 
			
		||||
};</pre>
 | 
			
		||||
 | 
			
		||||
<p><font face="Times New Roman">In this case if we instantiate
 | 
			
		||||
A<int[2]> then the declared type of the parameter passed to
 | 
			
		||||
member function foo is int[2], but it's actual type is const int*,
 | 
			
		||||
if we try to use the type T within the function body, then there
 | 
			
		||||
is a strong likelyhood that our code will not compile:</font></p>
 | 
			
		||||
 | 
			
		||||
<pre>template <class T>
 | 
			
		||||
void A<T>::foo(T t)
 | 
			
		||||
{
 | 
			
		||||
   T dup(t); // doesn't compile for case that T is an array.
 | 
			
		||||
}</pre>
 | 
			
		||||
 | 
			
		||||
<p>By using call_traits the degradation from array to pointer is
 | 
			
		||||
explicit, and the type of the parameter is the same as it's
 | 
			
		||||
declared type:</p>
 | 
			
		||||
 | 
			
		||||
<pre>template <class T>
 | 
			
		||||
struct A
 | 
			
		||||
{
 | 
			
		||||
   void foo(typename call_traits<T>::value_type t);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
void A<T>::foo(typename call_traits<T>::value_type t)
 | 
			
		||||
{
 | 
			
		||||
   typename call_traits<T>::value_type dup(t); // OK even if T is an array type.
 | 
			
		||||
}</pre>
 | 
			
		||||
 | 
			
		||||
<p>For value_type (return by value), again only a pointer may be
 | 
			
		||||
returned, not a copy of the whole array, and again call_traits
 | 
			
		||||
makes the degradation explicit. The value_type member is useful
 | 
			
		||||
whenever an array must be explicitly degraded to a pointer - <a
 | 
			
		||||
href="#ex3">Example 3</a> provides the test case (Footnote: the
 | 
			
		||||
array specialisation for call_traits is the least well understood
 | 
			
		||||
of all the call_traits specialisations, if the given semantics
 | 
			
		||||
cause specific problems for you, or don't solve a particular
 | 
			
		||||
array-related problem, then I would be interested to hear about
 | 
			
		||||
it. Most people though will probably never need to use this
 | 
			
		||||
specialisation).</p>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
<p>Revised 01 September 2000</p>
 | 
			
		||||
 | 
			
		||||
<p><EFBFBD> Copyright boost.org 2000. Permission to copy, use, modify,
 | 
			
		||||
sell and distribute this document is granted provided this
 | 
			
		||||
copyright notice appears in all copies. This document is provided
 | 
			
		||||
"as is" without express or implied warranty, and with
 | 
			
		||||
no claim as to its suitability for any purpose.</p>
 | 
			
		||||
 | 
			
		||||
<p>Based on contributions by Steve Cleary, Beman Dawes, Howard
 | 
			
		||||
Hinnant and John Maddock.</p>
 | 
			
		||||
 | 
			
		||||
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
 | 
			
		||||
Maddock</a>, the latest version of this file can be found at <a
 | 
			
		||||
href="http://www.boost.org/">www.boost.org</a>, and the boost
 | 
			
		||||
discussion list at <a href="http://www.egroups.com/list/boost">www.egroups.com/list/boost</a>.</p>
 | 
			
		||||
 | 
			
		||||
<p>.</p>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
@@ -1,366 +0,0 @@
 | 
			
		||||
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears in
 | 
			
		||||
// all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
//
 | 
			
		||||
// Revision History
 | 
			
		||||
// 11 Feb 2001  Compile with Borland, re-enable failing tests (David Abrahams)
 | 
			
		||||
// 29 Jan 2001  Initial revision (David Abrahams)
 | 
			
		||||
 | 
			
		||||
#include <boost/half_open_range.hpp>
 | 
			
		||||
#include <boost/utility.hpp>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#ifndef BOOST_NO_LIMITS
 | 
			
		||||
# include <limits>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_NO_SLIST
 | 
			
		||||
# include <slist>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
inline unsigned unsigned_random(unsigned max)
 | 
			
		||||
{
 | 
			
		||||
    return (max > 0) ? (unsigned)rand() % max : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Special tests for ranges supporting random access
 | 
			
		||||
template <class T>
 | 
			
		||||
void category_test_1(
 | 
			
		||||
    const boost::half_open_range<T>& r, std::random_access_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
    typedef boost::half_open_range<T> range;
 | 
			
		||||
    typedef typename range::size_type size_type;
 | 
			
		||||
    size_type size = r.size();
 | 
			
		||||
 | 
			
		||||
    // pick a random offset
 | 
			
		||||
    size_type offset = unsigned_random(size);
 | 
			
		||||
 | 
			
		||||
    typename range::value_type x = *(r.begin() + offset);
 | 
			
		||||
    // test contains(value_type)
 | 
			
		||||
    assert(r.contains(r.start()) == !r.empty());
 | 
			
		||||
    assert(!r.contains(r.finish()));
 | 
			
		||||
    assert(r.contains(x) == (offset != size));
 | 
			
		||||
 | 
			
		||||
    range::const_iterator p = r.find(x);
 | 
			
		||||
    assert((p == r.end()) == (x == r.finish()));
 | 
			
		||||
    assert(r.find(r.finish()) == r.end());
 | 
			
		||||
 | 
			
		||||
    if (offset != size)
 | 
			
		||||
    {
 | 
			
		||||
        assert(x == r[offset]);
 | 
			
		||||
        assert(x == r.at(offset));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool caught_out_of_range = false;
 | 
			
		||||
    try {
 | 
			
		||||
        bool never_initialized = x == r.at(size);
 | 
			
		||||
        (void)never_initialized;
 | 
			
		||||
    }
 | 
			
		||||
    catch(std::out_of_range&)
 | 
			
		||||
    {
 | 
			
		||||
        caught_out_of_range = true;
 | 
			
		||||
    }
 | 
			
		||||
    catch(...)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    assert(caught_out_of_range);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Those tests must be skipped for other ranges
 | 
			
		||||
template <class T>
 | 
			
		||||
void category_test_1(
 | 
			
		||||
    const boost::half_open_range<T>&, std::forward_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned indices[][2] = { {0,0},{0,1},{0,2},{0,3},
 | 
			
		||||
                                {1,1},{1,2},{1,3},
 | 
			
		||||
                                      {2,2},{2,3},
 | 
			
		||||
                                            {3,3}};
 | 
			
		||||
 | 
			
		||||
template <class Range>
 | 
			
		||||
void category_test_2(
 | 
			
		||||
    const std::vector<Range>& ranges, unsigned i, unsigned j, std::random_access_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
    typedef Range range;
 | 
			
		||||
    const range& ri = ranges[i];
 | 
			
		||||
    const range& rj = ranges[j];
 | 
			
		||||
 | 
			
		||||
    if (indices[i][0] <= indices[j][0] && indices[i][1] >= indices[j][1])
 | 
			
		||||
        assert(ri.contains(rj));
 | 
			
		||||
 | 
			
		||||
    if (ri.contains(rj))
 | 
			
		||||
        assert((ri & rj) == rj);
 | 
			
		||||
    assert(boost::intersects(ri, rj) == !(ri & rj).empty());
 | 
			
		||||
 | 
			
		||||
    range t1(ri);
 | 
			
		||||
    t1 &= rj;
 | 
			
		||||
    assert(t1 == range(indices[i][0] > indices[j][0] ? ri.start() : rj.start(),
 | 
			
		||||
                       indices[i][1] < indices[j][1] ? ri.finish() : rj.finish()));
 | 
			
		||||
    assert(t1 == (ri & rj));
 | 
			
		||||
    
 | 
			
		||||
    range t2(ri);
 | 
			
		||||
    t2 |= rj;
 | 
			
		||||
    
 | 
			
		||||
    if (ri.empty())
 | 
			
		||||
        assert(t2 == rj);
 | 
			
		||||
    else if (rj.empty())
 | 
			
		||||
        assert(t2 == ri);
 | 
			
		||||
    else
 | 
			
		||||
        assert(t2 == range(indices[i][0] < indices[j][0] ? ri.start() : rj.start(),
 | 
			
		||||
                           indices[i][1] > indices[j][1] ? ri.finish() : rj.finish()));
 | 
			
		||||
    assert(t2 == (ri | rj));
 | 
			
		||||
    if (i == j)
 | 
			
		||||
        assert(ri == rj);
 | 
			
		||||
    
 | 
			
		||||
    if (ri.empty() || rj.empty())
 | 
			
		||||
        assert((ri == rj) == (ri.empty() && rj.empty()));
 | 
			
		||||
    else
 | 
			
		||||
        assert((ri == rj) == (ri.start() == rj.start() && ri.finish() == rj.finish()));
 | 
			
		||||
 | 
			
		||||
    assert((ri == rj) == !(ri != rj));
 | 
			
		||||
 | 
			
		||||
    bool same = ri == rj;
 | 
			
		||||
    bool one_empty = ri.empty() != rj.empty();
 | 
			
		||||
 | 
			
		||||
    std::less<range> less;
 | 
			
		||||
    std::less_equal<range> less_equal;
 | 
			
		||||
    std::greater<range> greater;
 | 
			
		||||
    std::greater_equal<range> greater_equal;
 | 
			
		||||
    
 | 
			
		||||
    if (same)
 | 
			
		||||
    {
 | 
			
		||||
        assert(greater_equal(ri,rj));
 | 
			
		||||
        assert(less_equal(ri,rj));
 | 
			
		||||
        assert(!greater(ri,rj));
 | 
			
		||||
        assert(!less(ri,rj));
 | 
			
		||||
    }
 | 
			
		||||
    else if (one_empty)
 | 
			
		||||
    {
 | 
			
		||||
        const range& empty = ri.empty() ? ri : rj;
 | 
			
		||||
        const range& non_empty = rj.empty() ? ri : rj;
 | 
			
		||||
        
 | 
			
		||||
        assert(less(empty,non_empty));
 | 
			
		||||
        assert(less_equal(empty,non_empty));
 | 
			
		||||
        assert(!greater(empty,non_empty));
 | 
			
		||||
        assert(!greater_equal(empty,non_empty));
 | 
			
		||||
        assert(!less(non_empty,empty));
 | 
			
		||||
        assert(!less_equal(non_empty,empty));
 | 
			
		||||
        assert(greater(non_empty,empty));
 | 
			
		||||
        assert(greater_equal(non_empty,empty));
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        if (indices[i][0] < indices[j][0] ||
 | 
			
		||||
            indices[i][0] == indices[j][0] && indices[i][1] < indices[j][1])
 | 
			
		||||
        {
 | 
			
		||||
            assert(!greater_equal(ri,rj));
 | 
			
		||||
            assert(less(ri,rj));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (indices[i][0] < indices[j][0] ||
 | 
			
		||||
            indices[i][0] == indices[j][0] && indices[i][1] <= indices[j][1])
 | 
			
		||||
        {
 | 
			
		||||
            assert(!greater(ri,rj));
 | 
			
		||||
            assert(less_equal(ri,rj));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (indices[i][0] > indices[j][0] ||
 | 
			
		||||
            indices[i][0] == indices[j][0] && indices[i][1] > indices[j][1])
 | 
			
		||||
        {
 | 
			
		||||
            assert(!less_equal(ri,rj));
 | 
			
		||||
            assert(greater(ri,rj));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (indices[i][0] > indices[j][0] ||
 | 
			
		||||
            indices[i][0] == indices[j][0] && indices[i][1] >= indices[j][1])
 | 
			
		||||
        {
 | 
			
		||||
            assert(!less(ri,rj));
 | 
			
		||||
            assert(greater_equal(ri,rj));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <class Range>
 | 
			
		||||
void category_test_2(
 | 
			
		||||
    const std::vector<Range>&, unsigned, unsigned, std::forward_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
void category_test_2(
 | 
			
		||||
    const std::vector<boost::half_open_range<T> >&, unsigned, unsigned, std::bidirectional_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Range>
 | 
			
		||||
void test_back(Range& x, std::bidirectional_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
    assert(x.back() == boost::prior(x.finish()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Range>
 | 
			
		||||
void test_back(Range& x, std::forward_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
boost::half_open_range<T> range_identity(const boost::half_open_range<T>& x)
 | 
			
		||||
{
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
void test(T x0, T x1, T x2, T x3)
 | 
			
		||||
{
 | 
			
		||||
    std::vector<boost::half_open_range<T> > ranges;
 | 
			
		||||
    typedef boost::half_open_range<T> range;
 | 
			
		||||
 | 
			
		||||
    T bounds[4] = { x0, x1, x2, x3 };
 | 
			
		||||
 | 
			
		||||
    const std::size_t num_ranges = sizeof(indices)/sizeof(*indices);
 | 
			
		||||
    // test construction
 | 
			
		||||
    for (std::size_t n = 0; n < num_ranges;++n)
 | 
			
		||||
    {
 | 
			
		||||
        T start = bounds[indices[n][0]];
 | 
			
		||||
        T finish = bounds[indices[n][1]];
 | 
			
		||||
        boost::half_open_range<T> r(start, finish);
 | 
			
		||||
        ranges.push_back(r);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // test implicit conversion from std::pair<T,T>
 | 
			
		||||
    range converted = std::pair<T,T>(x0,x0);
 | 
			
		||||
    (void)converted;
 | 
			
		||||
 | 
			
		||||
    // test assignment, equality and inequality
 | 
			
		||||
    range r00 = range(x0, x0);
 | 
			
		||||
    assert(r00 == range(x0,x0));
 | 
			
		||||
    assert(r00 == range(x1,x1)); // empty ranges are all equal
 | 
			
		||||
    if (x3 != x0)
 | 
			
		||||
        assert(r00 != range(x0, x3));
 | 
			
		||||
    r00 = range(x0, x3);
 | 
			
		||||
    assert(r00 == range(x0, x3));
 | 
			
		||||
    if (x3 != x0)
 | 
			
		||||
        assert(r00 != range(x0, x0));
 | 
			
		||||
 | 
			
		||||
    typedef typename range::iterator iterator;
 | 
			
		||||
    typedef typename iterator::iterator_category category;
 | 
			
		||||
    
 | 
			
		||||
    for (unsigned i = 0; i < num_ranges; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        const range& r = ranges[i];
 | 
			
		||||
            
 | 
			
		||||
        // test begin(), end(), basic iteration.
 | 
			
		||||
        unsigned count = 0;
 | 
			
		||||
        for (range::const_iterator p = r.begin(), finish = r.end();
 | 
			
		||||
             p != finish;
 | 
			
		||||
             ++p, ++count)
 | 
			
		||||
        {
 | 
			
		||||
            assert(count < 2100);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // test size(), empty(), front(), back()
 | 
			
		||||
        assert((unsigned)r.size() == count);
 | 
			
		||||
        if (indices[i][0] == indices[i][1])
 | 
			
		||||
            assert(r.empty());
 | 
			
		||||
        if (r.empty())
 | 
			
		||||
            assert(r.size() == 0);
 | 
			
		||||
        if (!r.empty())
 | 
			
		||||
        {
 | 
			
		||||
            assert(r.front() == r.start());
 | 
			
		||||
            test_back(r, category());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            // test swap
 | 
			
		||||
        range r1(r);
 | 
			
		||||
        range r2(x0,x3);
 | 
			
		||||
        const bool same = r1 == r2;
 | 
			
		||||
        r1.swap(r2);
 | 
			
		||||
        assert(r1 == range(x0,x3));
 | 
			
		||||
        assert(r2 == r);
 | 
			
		||||
        if (!same) {
 | 
			
		||||
            assert(r1 != r);
 | 
			
		||||
            assert(r2 != range(x0,x3));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // do individual tests for random-access iterators
 | 
			
		||||
        category_test_1(r, category());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (unsigned j = 0; j < num_ranges; ++j) {
 | 
			
		||||
        for (unsigned k = 0; k < num_ranges; ++k) {
 | 
			
		||||
            category_test_2(ranges, j, k, category());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Integer>
 | 
			
		||||
void test_integer(Integer* = 0) // default arg works around MSVC bug
 | 
			
		||||
{
 | 
			
		||||
    Integer a = 0;
 | 
			
		||||
    Integer b = a + unsigned_random(128 - a);
 | 
			
		||||
    Integer c = b + unsigned_random(128 - b);
 | 
			
		||||
    Integer d = c + unsigned_random(128 - c);
 | 
			
		||||
 | 
			
		||||
    test(a, b, c, d);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Container>
 | 
			
		||||
void test_container(Container* = 0)  // default arg works around MSVC bug
 | 
			
		||||
{
 | 
			
		||||
    Container c(unsigned_random(1673));
 | 
			
		||||
 | 
			
		||||
    const typename Container::size_type offset1 = unsigned_random(c.size());
 | 
			
		||||
    const typename Container::size_type offset2 = unsigned_random(c.size() - offset1);
 | 
			
		||||
    typename Container::iterator internal1 = c.begin();
 | 
			
		||||
    std::advance(internal1, offset1);
 | 
			
		||||
    typename Container::iterator internal2 = internal1;
 | 
			
		||||
    std::advance(internal2, offset2);
 | 
			
		||||
    
 | 
			
		||||
    test(c.begin(), internal1, internal2, c.end());
 | 
			
		||||
 | 
			
		||||
    typedef typename Container::const_iterator const_iterator;
 | 
			
		||||
    test(const_iterator(c.begin()),
 | 
			
		||||
         const_iterator(internal1),
 | 
			
		||||
         const_iterator(internal2),
 | 
			
		||||
         const_iterator(c.end()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    // Test the built-in integer types.
 | 
			
		||||
    test_integer<char>();
 | 
			
		||||
    test_integer<unsigned char>();
 | 
			
		||||
    test_integer<signed char>();
 | 
			
		||||
    test_integer<wchar_t>();
 | 
			
		||||
    test_integer<short>();
 | 
			
		||||
    test_integer<unsigned short>();
 | 
			
		||||
    test_integer<int>();
 | 
			
		||||
    test_integer<unsigned int>();
 | 
			
		||||
    test_integer<long>();
 | 
			
		||||
    test_integer<unsigned long>();
 | 
			
		||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
 | 
			
		||||
    test_integer<long long>();
 | 
			
		||||
    test_integer<unsigned long long>();
 | 
			
		||||
#endif
 | 
			
		||||
    // Some tests on container iterators, to prove we handle a few different categories
 | 
			
		||||
    test_container<std::vector<int> >();
 | 
			
		||||
    test_container<std::list<int> >();
 | 
			
		||||
#ifndef BOOST_NO_SLIST
 | 
			
		||||
    test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
 | 
			
		||||
#endif
 | 
			
		||||
    // Also prove that we can handle raw pointers.
 | 
			
		||||
    int array[2000];
 | 
			
		||||
    const std::size_t a = 0;
 | 
			
		||||
    const std::size_t b = a + unsigned_random(2000 - a);
 | 
			
		||||
    const std::size_t c = b + unsigned_random(2000 - b);
 | 
			
		||||
    test(array, array+b, array+c, array+2000);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,565 +0,0 @@
 | 
			
		||||
//  Boost operators.hpp header file  ----------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright David Abrahams 1999. Permission to copy, use,
 | 
			
		||||
//  modify, sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
 | 
			
		||||
//            supplied arguments from actually being used (Dave Abrahams)
 | 
			
		||||
//  04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
 | 
			
		||||
//            refactoring of compiler workarounds, additional documentation
 | 
			
		||||
//            (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
 | 
			
		||||
//            Dave Abrahams) 
 | 
			
		||||
//  28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and
 | 
			
		||||
//            Jeremy Siek (Dave Abrahams)
 | 
			
		||||
//  20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5
 | 
			
		||||
//            (Mark Rodgers)
 | 
			
		||||
//  20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy)
 | 
			
		||||
//  10 Jun 00 Support for the base class chaining technique was added
 | 
			
		||||
//            (Aleksey Gurtovoy). See documentation and the comments below 
 | 
			
		||||
//            for the details. 
 | 
			
		||||
//  12 Dec 99 Initial version with iterator operators (Jeremy Siek)
 | 
			
		||||
//  18 Nov 99 Change name "divideable" to "dividable", remove unnecessary
 | 
			
		||||
//            specializations of dividable, subtractable, modable (Ed Brey) 
 | 
			
		||||
//  17 Nov 99 Add comments (Beman Dawes)
 | 
			
		||||
//            Remove unnecessary specialization of operators<> (Ed Brey)
 | 
			
		||||
//  15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two
 | 
			
		||||
//            operators.(Beman Dawes)
 | 
			
		||||
//  12 Nov 99 Add operators templates (Ed Brey)
 | 
			
		||||
//  11 Nov 99 Add single template parameter version for compilers without
 | 
			
		||||
//            partial specialization (Beman Dawes)
 | 
			
		||||
//  10 Nov 99 Initial version
 | 
			
		||||
 | 
			
		||||
// 10 Jun 00:
 | 
			
		||||
// An additional optional template parameter was added to most of 
 | 
			
		||||
// operator templates to support the base class chaining technique (see 
 | 
			
		||||
// documentation for the details). Unfortunately, a straightforward
 | 
			
		||||
// implementation of this change would have broken compatibility with the
 | 
			
		||||
// previous version of the library by making it impossible to use the same
 | 
			
		||||
// template name (e.g. 'addable') for both the 1- and 2-argument versions of
 | 
			
		||||
// an operator template. This implementation solves the backward-compatibility
 | 
			
		||||
// issue at the cost of some simplicity.
 | 
			
		||||
//
 | 
			
		||||
// One of the complications is an existence of special auxiliary class template
 | 
			
		||||
// 'is_chained_base<>' (see 'detail' namespace below), which is used
 | 
			
		||||
// to determine whether its template parameter is a library's operator template
 | 
			
		||||
// or not. You have to specialize 'is_chained_base<>' for each new 
 | 
			
		||||
// operator template you add to the library.
 | 
			
		||||
//
 | 
			
		||||
// However, most of the non-trivial implementation details are hidden behind 
 | 
			
		||||
// several local macros defined below, and as soon as you understand them,
 | 
			
		||||
// you understand the whole library implementation. 
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_OPERATORS_HPP
 | 
			
		||||
#define BOOST_OPERATORS_HPP
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <boost/iterator.hpp>
 | 
			
		||||
 | 
			
		||||
#if defined(__sgi) && !defined(__GNUC__)
 | 
			
		||||
#pragma set woff 1234
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC)
 | 
			
		||||
#   pragma warning( disable : 4284 ) // complaint about return type of 
 | 
			
		||||
#endif                               // operator-> not begin a UDT
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
class empty_base {};
 | 
			
		||||
 | 
			
		||||
} // namespace detail
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
// In this section we supply the xxxx1 and xxxx2 forms of the operator
 | 
			
		||||
// templates, which are explicitly targeted at the 1-type-argument and
 | 
			
		||||
// 2-type-argument operator forms, respectively. Some compilers get confused
 | 
			
		||||
// when inline friend functions are overloaded in namespaces other than the
 | 
			
		||||
// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of
 | 
			
		||||
// these templates must go in the global namespace.
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//  Basic operator classes (contributed by Dave Abrahams) ------------------//
 | 
			
		||||
 | 
			
		||||
//  Note that friend functions defined in a class are implicitly inline.
 | 
			
		||||
//  See the C++ std, 11.4 [class.friend] paragraph 5
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct less_than_comparable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend bool operator<=(const T& x, const U& y) { return !(x > y); }
 | 
			
		||||
     friend bool operator>=(const T& x, const U& y) { return !(x < y); }
 | 
			
		||||
     friend bool operator>(const U& x, const T& y)  { return y < x; }
 | 
			
		||||
     friend bool operator<(const U& x, const T& y)  { return y > x; }
 | 
			
		||||
     friend bool operator<=(const U& x, const T& y) { return !(y < x); }
 | 
			
		||||
     friend bool operator>=(const U& x, const T& y) { return !(y > x); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct less_than_comparable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend bool operator>(const T& x, const T& y)  { return y < x; }
 | 
			
		||||
     friend bool operator<=(const T& x, const T& y) { return !(y < x); }
 | 
			
		||||
     friend bool operator>=(const T& x, const T& y) { return !(x < y); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct equality_comparable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend bool operator==(const U& y, const T& x) { return x == y; }
 | 
			
		||||
     friend bool operator!=(const U& y, const T& x) { return !(x == y); }
 | 
			
		||||
     friend bool operator!=(const T& y, const U& x) { return !(y == x); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct equality_comparable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend bool operator!=(const T& x, const T& y) { return !(x == y); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct multipliable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator*(T x, const U& y) { return x *= y; }
 | 
			
		||||
     friend T operator*(const U& y, T x) { return x *= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct multipliable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator*(T x, const T& y) { return x *= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct addable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator+(T x, const U& y) { return x += y; }
 | 
			
		||||
     friend T operator+(const U& y, T x) { return x += y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct addable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator+(T x, const T& y) { return x += y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct subtractable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator-(T x, const U& y) { return x -= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct subtractable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator-(T x, const T& y) { return x -= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct dividable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator/(T x, const U& y) { return x /= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct dividable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator/(T x, const T& y) { return x /= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct modable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator%(T x, const U& y) { return x %= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct modable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator%(T x, const T& y) { return x %= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct xorable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator^(T x, const U& y) { return x ^= y; }
 | 
			
		||||
     friend T operator^(const U& y, T x) { return x ^= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct xorable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator^(T x, const T& y) { return x ^= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct andable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator&(T x, const U& y) { return x &= y; }
 | 
			
		||||
     friend T operator&(const U& y, T x) { return x &= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct andable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator&(T x, const T& y) { return x &= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct orable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator|(T x, const U& y) { return x |= y; }
 | 
			
		||||
     friend T operator|(const U& y, T x) { return x |= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct orable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator|(T x, const T& y) { return x |= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//  incrementable and decrementable contributed by Jeremy Siek
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct incrementable : B
 | 
			
		||||
{
 | 
			
		||||
  friend T operator++(T& x, int)
 | 
			
		||||
  {
 | 
			
		||||
    incrementable_type tmp(x);
 | 
			
		||||
    ++x;
 | 
			
		||||
    return tmp;
 | 
			
		||||
  }
 | 
			
		||||
private: // The use of this typedef works around a Borland bug
 | 
			
		||||
  typedef T incrementable_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct decrementable : B
 | 
			
		||||
{
 | 
			
		||||
  friend T operator--(T& x, int)
 | 
			
		||||
  {
 | 
			
		||||
    decrementable_type tmp(x);
 | 
			
		||||
    --x;
 | 
			
		||||
    return tmp;
 | 
			
		||||
  }
 | 
			
		||||
private: // The use of this typedef works around a Borland bug
 | 
			
		||||
  typedef T decrementable_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//  Iterator operator classes (contributed by Jeremy Siek) ------------------//
 | 
			
		||||
 | 
			
		||||
template <class T, class P, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct dereferenceable : B
 | 
			
		||||
{
 | 
			
		||||
  P operator->() const
 | 
			
		||||
  { 
 | 
			
		||||
    return &*static_cast<const T&>(*this); 
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class I, class R, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct indexable : B
 | 
			
		||||
{
 | 
			
		||||
  R operator[](I n) const
 | 
			
		||||
  {
 | 
			
		||||
    return *(static_cast<const T&>(*this) + n);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
} // namespace boost
 | 
			
		||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// BOOST_IMPORT_TEMPLATE1/BOOST_IMPORT_TEMPLATE2 -
 | 
			
		||||
//
 | 
			
		||||
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
 | 
			
		||||
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
 | 
			
		||||
// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for
 | 
			
		||||
// two-argument forms. Note that these macros expect to be invoked from within
 | 
			
		||||
// boost.
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_NO_OPERATORS_IN_NAMESPACE)
 | 
			
		||||
 | 
			
		||||
#  if defined(BOOST_NO_USING_TEMPLATE)
 | 
			
		||||
 | 
			
		||||
     // Because a Borland C++ 5.5 bug prevents a using declaration from working,
 | 
			
		||||
     // we are forced to use inheritance for that compiler.
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE2(template_name)                              \
 | 
			
		||||
     template <class T, class U, class B = ::boost::detail::empty_base>        \
 | 
			
		||||
     struct template_name : ::template_name<T, U, B> {};
 | 
			
		||||
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE1(template_name)                              \
 | 
			
		||||
     template <class T, class B = ::boost::detail::empty_base>                 \
 | 
			
		||||
     struct template_name : ::template_name<T, B> {};
 | 
			
		||||
 | 
			
		||||
#  else
 | 
			
		||||
 | 
			
		||||
     // Otherwise, bring the names in with a using-declaration to avoid
 | 
			
		||||
     // stressing the compiler
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
 | 
			
		||||
 | 
			
		||||
#  endif // BOOST_NO_USING_TEMPLATE
 | 
			
		||||
 | 
			
		||||
#else // !BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
  // The template is already in boost so we have nothing to do.
 | 
			
		||||
# define BOOST_IMPORT_TEMPLATE2(template_name)
 | 
			
		||||
# define BOOST_IMPORT_TEMPLATE1(template_name)
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Here's where we put it all together, defining the xxxx forms of the templates
 | 
			
		||||
// in namespace boost. We also define specializations of is_chained_base<> for
 | 
			
		||||
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
 | 
			
		||||
// neccessary.
 | 
			
		||||
//
 | 
			
		||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
 | 
			
		||||
 | 
			
		||||
// is_chained_base<> - a traits class used to distinguish whether an operator
 | 
			
		||||
// template argument is being used for base class chaining, or is specifying a
 | 
			
		||||
// 2nd argument type.
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
// A type parameter is used instead of a plain bool because Borland's compiler
 | 
			
		||||
// didn't cope well with the more obvious non-type template parameter.
 | 
			
		||||
namespace detail {
 | 
			
		||||
  struct true_t {};
 | 
			
		||||
  struct false_t {};
 | 
			
		||||
} // namespace detail
 | 
			
		||||
 | 
			
		||||
// Unspecialized version assumes that most types are not being used for base
 | 
			
		||||
// class chaining. We specialize for the operator templates defined in this
 | 
			
		||||
// library.
 | 
			
		||||
template<class T> struct is_chained_base {
 | 
			
		||||
  typedef ::boost::detail::false_t value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
// Import a 2-type-argument operator template into boost (if neccessary) and
 | 
			
		||||
// provide a specialization of 'is_chained_base<>' for it.
 | 
			
		||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2)                  \
 | 
			
		||||
  BOOST_IMPORT_TEMPLATE2(template_name2)                           \
 | 
			
		||||
  template<class T, class U, class B>                              \
 | 
			
		||||
  struct is_chained_base< ::boost::template_name2<T, U, B> > {     \
 | 
			
		||||
    typedef ::boost::detail::true_t value;                         \
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
// Import a 1-type-argument operator template into boost (if neccessary) and
 | 
			
		||||
// provide a specialization of 'is_chained_base<>' for it.
 | 
			
		||||
# define BOOST_OPERATOR_TEMPLATE1(template_name1)                  \
 | 
			
		||||
  BOOST_IMPORT_TEMPLATE1(template_name1)                           \
 | 
			
		||||
  template<class T, class B>                                       \
 | 
			
		||||
  struct is_chained_base< ::boost::template_name1<T, B> > {        \
 | 
			
		||||
    typedef ::boost::detail::true_t value;                         \
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
 | 
			
		||||
// can be used for specifying both 1-argument and 2-argument forms. Requires the
 | 
			
		||||
// existence of two previously defined class templates named '<template_name>1'
 | 
			
		||||
// and '<template_name>2' which must implement the corresponding 1- and 2-
 | 
			
		||||
// argument forms.
 | 
			
		||||
//
 | 
			
		||||
// The template type parameter O == is_chained_base<U>::value is used to
 | 
			
		||||
// distinguish whether the 2nd argument to <template_name> is being used for
 | 
			
		||||
// base class chaining from another boost operator template or is describing a
 | 
			
		||||
// 2nd operand type. O == true_t only when U is actually an another operator
 | 
			
		||||
// template from the library. Partial specialization is used to select an
 | 
			
		||||
// implementation in terms of either '<template_name>1' or '<template_name>2'.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
# define BOOST_OPERATOR_TEMPLATE(template_name)                    \
 | 
			
		||||
template <class T                                                  \
 | 
			
		||||
         ,class U = T                                              \
 | 
			
		||||
         ,class B = ::boost::detail::empty_base                    \
 | 
			
		||||
         ,class O = typename is_chained_base<U>::value             \
 | 
			
		||||
         >                                                         \
 | 
			
		||||
struct template_name : template_name##2<T, U, B> {};               \
 | 
			
		||||
                                                                   \
 | 
			
		||||
template<class T, class U, class B>                                \
 | 
			
		||||
struct template_name<T, U, B, ::boost::detail::true_t>             \
 | 
			
		||||
  : template_name##1<T, U> {};                                     \
 | 
			
		||||
                                                                   \
 | 
			
		||||
template <class T, class B>                                        \
 | 
			
		||||
struct template_name<T, T, B, ::boost::detail::false_t>            \
 | 
			
		||||
  : template_name##1<T, B> {};                                     \
 | 
			
		||||
                                                                   \
 | 
			
		||||
template<class T, class U, class B, class O>                       \
 | 
			
		||||
struct is_chained_base< ::boost::template_name<T, U, B, O> > {     \
 | 
			
		||||
  typedef ::boost::detail::true_t value;                           \
 | 
			
		||||
};                                                                 \
 | 
			
		||||
                                                                   \
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE2(template_name##2)                         \
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE1(template_name##1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
 | 
			
		||||
#  define BOOST_OPERATOR_TEMPLATE2(template_name2) \
 | 
			
		||||
        BOOST_IMPORT_TEMPLATE2(template_name2)
 | 
			
		||||
#  define BOOST_OPERATOR_TEMPLATE1(template_name1) \
 | 
			
		||||
        BOOST_IMPORT_TEMPLATE1(template_name1)
 | 
			
		||||
 | 
			
		||||
   // In this case we can only assume that template_name<> is equivalent to the
 | 
			
		||||
   // more commonly needed template_name1<> form.
 | 
			
		||||
#  define BOOST_OPERATOR_TEMPLATE(template_name)                   \
 | 
			
		||||
   template <class T, class B = ::boost::detail::empty_base>       \
 | 
			
		||||
   struct template_name : template_name##1<T, B> {};
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
    
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(less_than_comparable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(equality_comparable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(multipliable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(addable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(subtractable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(dividable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(modable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(xorable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(andable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(orable)
 | 
			
		||||
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE1(incrementable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE1(decrementable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
 | 
			
		||||
 | 
			
		||||
// indexable doesn't follow the patterns above (it has 4 template arguments), so
 | 
			
		||||
// we just write out the compiler hacks explicitly.
 | 
			
		||||
#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
# ifdef BOOST_NO_USING_TEMPLATE
 | 
			
		||||
   template <class T, class I, class R, class B = ::boost::detail::empty_base>
 | 
			
		||||
   struct indexable : ::indexable<T,I,R,B> {};
 | 
			
		||||
# else
 | 
			
		||||
   using ::indexable;
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
template <class T, class I, class R, class B>
 | 
			
		||||
struct is_chained_base< ::boost::indexable<T, I, R, B> > {
 | 
			
		||||
  typedef ::boost::detail::true_t operator_template_type;
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#undef BOOST_OPERATOR_TEMPLATE
 | 
			
		||||
#undef BOOST_OPERATOR_TEMPLATE2
 | 
			
		||||
#undef BOOST_OPERATOR_TEMPLATE1
 | 
			
		||||
#undef BOOST_IMPORT_TEMPLATE1
 | 
			
		||||
#undef BOOST_IMPORT_TEMPLATE2
 | 
			
		||||
 | 
			
		||||
// The following 'operators' classes can only be used portably if the derived class
 | 
			
		||||
// declares ALL of the required member operators.
 | 
			
		||||
template <class T, class U>
 | 
			
		||||
struct operators2
 | 
			
		||||
    : less_than_comparable2<T,U
 | 
			
		||||
    , equality_comparable2<T,U
 | 
			
		||||
    , addable2<T,U
 | 
			
		||||
    , subtractable2<T,U
 | 
			
		||||
    , multipliable2<T,U
 | 
			
		||||
    , dividable2<T,U
 | 
			
		||||
    , modable2<T,U
 | 
			
		||||
    , orable2<T,U
 | 
			
		||||
    , andable2<T,U
 | 
			
		||||
    , xorable2<T,U
 | 
			
		||||
      > > > > > > > > > > {};
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
template <class T, class U = T>
 | 
			
		||||
struct operators : operators2<T, U> {};
 | 
			
		||||
 | 
			
		||||
template <class T> struct operators<T, T>
 | 
			
		||||
#else
 | 
			
		||||
template <class T> struct operators
 | 
			
		||||
#endif
 | 
			
		||||
    : less_than_comparable<T
 | 
			
		||||
    , equality_comparable<T
 | 
			
		||||
    , addable<T
 | 
			
		||||
    , subtractable<T
 | 
			
		||||
    , multipliable<T
 | 
			
		||||
    , dividable<T
 | 
			
		||||
    , modable<T
 | 
			
		||||
    , orable<T
 | 
			
		||||
    , andable<T
 | 
			
		||||
    , xorable<T
 | 
			
		||||
    , incrementable<T
 | 
			
		||||
    , decrementable<T
 | 
			
		||||
      > > > > > > > > > > > > {};
 | 
			
		||||
 | 
			
		||||
//  Iterator helper classes (contributed by Jeremy Siek) -------------------//
 | 
			
		||||
template <class T,
 | 
			
		||||
          class V,
 | 
			
		||||
          class D = std::ptrdiff_t,
 | 
			
		||||
          class P = V*,
 | 
			
		||||
          class R = V&>
 | 
			
		||||
struct forward_iterator_helper
 | 
			
		||||
  : equality_comparable<T
 | 
			
		||||
  , incrementable<T
 | 
			
		||||
  , dereferenceable<T,P
 | 
			
		||||
  , boost::iterator<std::forward_iterator_tag,V,D,P,R
 | 
			
		||||
    > > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T,
 | 
			
		||||
          class V,
 | 
			
		||||
          class D = std::ptrdiff_t,
 | 
			
		||||
          class P = V*,
 | 
			
		||||
          class R = V&>
 | 
			
		||||
struct bidirectional_iterator_helper
 | 
			
		||||
  : equality_comparable<T
 | 
			
		||||
  , incrementable<T
 | 
			
		||||
  , decrementable<T
 | 
			
		||||
  , dereferenceable<T,P
 | 
			
		||||
  , boost::iterator<std::bidirectional_iterator_tag,V,D,P,R
 | 
			
		||||
    > > > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T,
 | 
			
		||||
          class V, 
 | 
			
		||||
          class D = std::ptrdiff_t,
 | 
			
		||||
          class P = V*,
 | 
			
		||||
          class R = V&>
 | 
			
		||||
struct random_access_iterator_helper
 | 
			
		||||
  : equality_comparable<T
 | 
			
		||||
  , less_than_comparable<T
 | 
			
		||||
  , incrementable<T
 | 
			
		||||
  , decrementable<T
 | 
			
		||||
  , dereferenceable<T,P
 | 
			
		||||
  , addable2<T,D
 | 
			
		||||
  , subtractable2<T,D
 | 
			
		||||
  , indexable<T,D,R
 | 
			
		||||
  , boost::iterator<std::random_access_iterator_tag,V,D,P,R
 | 
			
		||||
    > > > > > > > > >
 | 
			
		||||
{
 | 
			
		||||
#ifndef __BORLANDC__
 | 
			
		||||
  friend D requires_difference_operator(const T& x, const T& y) {
 | 
			
		||||
    return x - y;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}; // random_access_iterator_helper
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#if defined(__sgi) && !defined(__GNUC__)
 | 
			
		||||
#pragma reset woff 1234
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_OPERATORS_HPP
 | 
			
		||||
@@ -1,61 +0,0 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  char characters[] = "abcdefg";
 | 
			
		||||
  const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
 | 
			
		||||
  char* pointers_to_chars[N];                        // at the end.
 | 
			
		||||
  for (int i = 0; i < N; ++i)
 | 
			
		||||
    pointers_to_chars[i] = &characters[i];
 | 
			
		||||
 | 
			
		||||
  // Example of using indirect_iterator_generator
 | 
			
		||||
  
 | 
			
		||||
  boost::indirect_iterator_generator<char**, char>::type 
 | 
			
		||||
    indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
 | 
			
		||||
 | 
			
		||||
  std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  // Example of using indirect_iterator_pair_generator
 | 
			
		||||
 | 
			
		||||
  typedef boost::indirect_iterator_pair_generator<char**,
 | 
			
		||||
    char, char*, char&, const char*, const char&> PairGen;
 | 
			
		||||
 | 
			
		||||
  char mutable_characters[N];
 | 
			
		||||
  char* pointers_to_mutable_chars[N];
 | 
			
		||||
  for (int i = 0; i < N; ++i)
 | 
			
		||||
    pointers_to_mutable_chars[i] = &mutable_characters[i];
 | 
			
		||||
 | 
			
		||||
  PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars),
 | 
			
		||||
    mutable_indirect_last(pointers_to_mutable_chars + N);
 | 
			
		||||
  PairGen::const_iterator const_indirect_first(pointers_to_chars),
 | 
			
		||||
    const_indirect_last(pointers_to_chars + N);
 | 
			
		||||
 | 
			
		||||
  std::transform(const_indirect_first, const_indirect_last,
 | 
			
		||||
		 mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
 | 
			
		||||
 | 
			
		||||
  std::copy(mutable_indirect_first, mutable_indirect_last,
 | 
			
		||||
	    std::ostream_iterator<char>(std::cout, ","));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  // Example of using make_indirect_iterator()
 | 
			
		||||
 | 
			
		||||
  std::copy(boost::make_indirect_iterator(pointers_to_chars), 
 | 
			
		||||
	    boost::make_indirect_iterator(pointers_to_chars + N),
 | 
			
		||||
	    std::ostream_iterator<char>(std::cout, ","));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										104
									
								
								utility.htm
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								utility.htm
									
									
									
									
									
								
							@@ -1,104 +0,0 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 | 
			
		||||
<title>Header boost/utility.hpp Documentation</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" WIDTH="277" HEIGHT="86">Header
 | 
			
		||||
<a href="../../boost/utility.hpp">boost/utility.hpp</a></h1>
 | 
			
		||||
 | 
			
		||||
<p>The entire contents of the header <code><a href="../../boost/utility.hpp"><boost/utility.hpp></a></code>
 | 
			
		||||
 are in <code>namespace boost</code>.</p>
 | 
			
		||||
 | 
			
		||||
<h2>Contents</h2>
 | 
			
		||||
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>Function templates <a href="#functions next">next() and prior()</a></li>
 | 
			
		||||
  <li>Class <a href="#Class noncopyable">noncopyable</a></li>
 | 
			
		||||
  <li>Function template <a href="tie.html">tie()</a> and supporting class tied.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<h2> <a name="functions next">Function</a> templates next() and prior()</h2>
 | 
			
		||||
 | 
			
		||||
<p>Certain data types, such as the C++ Standard Library's forward and
 | 
			
		||||
bidirectional iterators, do not provide addition and subtraction via operator+()
 | 
			
		||||
or operator-().  This means that non-modifying computation of the next or
 | 
			
		||||
prior value requires a temporary, even though operator++() or operator--() is
 | 
			
		||||
provided.  It also means that writing code like <code>itr+1</code> inside a
 | 
			
		||||
template restricts the iterator category to random access iterators.</p>
 | 
			
		||||
 | 
			
		||||
<p>The next() and prior() functions provide a simple way around these problems:</p>
 | 
			
		||||
 | 
			
		||||
<blockquote>
 | 
			
		||||
 | 
			
		||||
<pre>template <class T>
 | 
			
		||||
T next(T x) { return ++x; }
 | 
			
		||||
 | 
			
		||||
template <class X>
 | 
			
		||||
T prior(T x) { return --x; }</pre>
 | 
			
		||||
 | 
			
		||||
</blockquote>
 | 
			
		||||
 | 
			
		||||
<p>Usage is simple:</p>
 | 
			
		||||
 | 
			
		||||
<blockquote>
 | 
			
		||||
 | 
			
		||||
<pre>const std::list<T>::iterator p = get_some_iterator();
 | 
			
		||||
const std::list<T>::iterator prev = boost::prior(p);</pre>
 | 
			
		||||
 | 
			
		||||
</blockquote>
 | 
			
		||||
 | 
			
		||||
<p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.</p>
 | 
			
		||||
 | 
			
		||||
<h2><a name="Class noncopyable">Class noncopyable</a></h2>
 | 
			
		||||
 | 
			
		||||
<p>Class <strong>noncopyable</strong> is a base class.  Derive your own class from <strong>noncopyable</strong>
 | 
			
		||||
when you want to prohibit copy construction and copy assignment.</p>
 | 
			
		||||
 | 
			
		||||
<p>Some objects, particularly those which hold complex resources like files or
 | 
			
		||||
network connections, have no sensible copy semantics.  Sometimes there are
 | 
			
		||||
possible copy semantics, but these would be of very limited usefulness and be
 | 
			
		||||
very difficult to implement correctly.  Sometimes you're implementing a class that doesn't need to be copied
 | 
			
		||||
just yet and you don't want to take the time to write the appropriate functions. 
 | 
			
		||||
Deriving from <b> noncopyable</b> will prevent the otherwise implicitly-generated
 | 
			
		||||
functions (which don't have the proper semantics) from becoming a trap for other programmers.</p>
 | 
			
		||||
 | 
			
		||||
<p>The traditional way to deal with these is to declare a private copy constructor and copy assignment, and then
 | 
			
		||||
document why this is done.  But deriving from <b>noncopyable</b> is simpler
 | 
			
		||||
and clearer, and doesn't require additional documentation.</p>
 | 
			
		||||
 | 
			
		||||
<p>The program <a href="noncopyable_test.cpp">noncopyable_test.cpp</a> can be
 | 
			
		||||
used to verify class <b>noncopyable</b> works as expected. It has have been run successfully under
 | 
			
		||||
GCC 2.95, Metrowerks
 | 
			
		||||
CodeWarrior 5.0, and Microsoft Visual C++ 6.0 sp 3.</p>
 | 
			
		||||
 | 
			
		||||
<p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.</p>
 | 
			
		||||
 | 
			
		||||
<h3>Example</h3>
 | 
			
		||||
<blockquote>
 | 
			
		||||
  <pre>// inside one of your own headers ...
 | 
			
		||||
#include <boost/utility.hpp>
 | 
			
		||||
 | 
			
		||||
class ResourceLadenFileSystem : boost::noncopyable {
 | 
			
		||||
...</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
 | 
			
		||||
<h3>Rationale</h3>
 | 
			
		||||
<p>Class noncopyable has protected constructor and destructor members to
 | 
			
		||||
emphasize that it is to be used only as a base class.  Dave Abrahams notes
 | 
			
		||||
concern about the effect on compiler optimization of adding (even trivial inline)
 | 
			
		||||
destructor declarations. He says "Probably this concern is misplaced, because
 | 
			
		||||
noncopyable will be used mostly for classes which own resources and thus have non-trivial destruction semantics."</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised  <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan
 | 
			
		||||
-->16 February, 2001<!--webbot bot="Timestamp" endspan i-checksum="40407"
 | 
			
		||||
-->
 | 
			
		||||
</p>
 | 
			
		||||
<p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and
 | 
			
		||||
distribute this document is granted provided this copyright notice appears in
 | 
			
		||||
all copies. This document is provided "as is" without express or
 | 
			
		||||
implied warranty, and with no claim as to its suitability for any purpose.</p>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
		Reference in New Issue
	
	Block a user