Compare commits

..

1 Commits

Author SHA1 Message Date
96757e3d68 This commit was manufactured by cvs2svn to create branch
'compiler_supported_error_messages'.

[SVN r13249]
2002-03-22 12:16:42 +00:00
113 changed files with 8685 additions and 8236 deletions

View File

@ -1,109 +1,116 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<!--
-- Copyright (c) Jeremy Siek 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Silicon Graphics makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Assignable</Title>
</HEAD>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<!--end header-->
<BR Clear>
<H1>Assignable</H1>
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<h3>Description</h3>
A type is Assignable if it is possible to assign one object of the type
to another object of that type.
<title>Assignable</title>
</head>
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86"><br clear="none">
<h3>Notation</h3>
<Table>
<TR>
<TD VAlign=top>
<tt>T</tt>
</TD>
<TD VAlign=top>
is type that is a model of Assignable
</TD>
</TR>
<h1>Assignable</h1>
<TR>
<TD VAlign=top>
<tt>t</tt>
</TD>
<TD VAlign=top>
is an object of type <tt>T</tt>
</TD>
</tr>
<h3>Description</h3>
<TR>
<TD VAlign=top>
<tt>u</tt>
</TD>
<TD VAlign=top>
is an object of type <tt>T</tt> or possibly <tt>const T</tt>
</TD>
</tr>
<p>A type is Assignable if it is possible to assign one object of the type
to another object of that type.</p>
</table>
<h3>Definitions</h3>
<h3>Valid expressions</h3>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Return type
</TH>
<TH>
Semantics
</TH>
</TR>
<TR>
<TD VAlign=top>
Assignment
</TD>
<TD VAlign=top>
<tt>t = u</tt>
</TD>
<TD VAlign=top>
<tt>T&amp;</tt>
</TD>
<TD VAlign=top>
<tt>t</tt> is equivalent to <tt>u</tt>
</TD>
</TR>
<h3>Notation</h3>
</table>
<table summary="">
<tr>
<td valign="top"><tt>T</tt></td>
<td valign="top">is type that is a model of Assignable</td>
</tr>
</table>
<h3>Models</h3>
<tr>
<td valign="top"><tt>t</tt></td>
<UL>
<LI><tt>int</tt>
<LI><tt>std::pair</tt>
</UL>
<td valign="top">is an object of type <tt>T</tt></td>
</tr>
<h3>See also</h3>
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</A>
and
<A href="./CopyConstructible.html">CopyConstructible</A>
<tr>
<td valign="top"><tt>u</tt></td>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF=http://www.lsc.nd.edu/~jsiek>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
</TD></TR></TABLE>
<td valign="top">is an object of type <tt>T</tt> or possibly <tt>const
T</tt></td>
</tr>
</table>
<h3>Definitions</h3>
<h3>Valid expressions</h3>
<table border summary="">
<tr>
<th>Name</th>
<th>Expression</th>
<th>Return type</th>
<th>Semantics</th>
</tr>
<tr>
<td valign="top">Assignment</td>
<td valign="top"><tt>t = u</tt></td>
<td valign="top"><tt>T&amp;</tt></td>
<td valign="top"><tt>t</tt> is equivalent to <tt>u</tt></td>
</tr>
</table>
<h3>Models</h3>
<ul>
<li><tt>int</tt></li>
<li><tt>std::pair</tt></li>
</ul>
<h3>See also</h3>
<p><a href=
"http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</a>
and <a href="./CopyConstructible.html">CopyConstructible</a><br></p>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
<table summary="">
<tr valign="top">
<td nowrap><i>Copyright &copy; 2000</i></td>
<td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of
Notre Dame (<a href=
"mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td>
</tr>
</table>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
</BODY>
</HTML>

View File

@ -1,534 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<title>Collection</title>
</head>
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<h1><img src="../../boost.png" alt="boost logo" width="277" align="middle"
height="86"><br>
Collection</h1>
<h3>Description</h3>
<p>A Collection is a <i>concept</i> similar to the STL <a href=
"http://www.sgi.com/tech/stl/Container.html">Container</a> concept. A
Collection provides iterators for accessing a range of elements and
provides information about the number of elements in the Collection.
However, a Collection has fewer requirements than a Container. The
motivation for the Collection concept is that there are many useful
Container-like types that do not meet the full requirements of Container,
and many algorithms that can be written with this reduced set of
requirements. To summarize the reduction in requirements:</p>
<ul>
<li>It is not required to "own" its elements: the lifetime of an element
in a Collection does not have to match the lifetime of the Collection
object, though the lifetime of the element should cover the lifetime of
the Collection object.</li>
<li>The semantics of copying a Collection object is not defined (it could
be a deep or shallow copy or not even support copying).</li>
<li>The associated reference type of a Collection does not have to be a
real C++ reference.</li>
</ul>Because of the reduced requirements, some care must be taken when
writing code that is meant to be generic for all Collection types. In
particular, a Collection object should be passed by-reference since
assumptions can not be made about the behaviour of the copy constructor.
<h3>Associated types</h3>
<table border summary="">
<tr>
<td valign="top">Value type</td>
<td valign="top"><tt>X::value_type</tt></td>
<td valign="top">The type of the object stored in a Collection. If the
Collection is <i>mutable</i> then the value type must be <a href=
"http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>. Otherwise
the value type must be <a href=
"./CopyConstructible.html">CopyConstructible</a>.</td>
</tr>
<tr>
<td valign="top">Iterator type</td>
<td valign="top"><tt>X::iterator</tt></td>
<td valign="top">The type of iterator used to iterate through a
Collection's elements. The iterator's value type is expected to be the
Collection's value type. A conversion from the iterator type to the
const iterator type must exist. The iterator type must be an <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>.</td>
</tr>
<tr>
<td valign="top">Const iterator type</td>
<td valign="top"><tt>X::const_iterator</tt></td>
<td valign="top">A type of iterator that may be used to examine, but
not to modify, a Collection's elements.</td>
</tr>
<tr>
<td valign="top">Reference type</td>
<td valign="top"><tt>X::reference</tt></td>
<td valign="top">A type that behaves like a reference to the
Collection's value type. <a href="#n1">[1]</a></td>
</tr>
<tr>
<td valign="top">Const reference type</td>
<td valign="top"><tt>X::const_reference</tt></td>
<td valign="top">A type that behaves like a const reference to the
Collection's value type.</td>
</tr>
<tr>
<td valign="top">Pointer type</td>
<td valign="top"><tt>X::pointer</tt></td>
<td valign="top">A type that behaves as a pointer to the Collection's
value type.</td>
</tr>
<tr>
<td valign="top">Distance type</td>
<td valign="top"><tt>X::difference_type</tt></td>
<td valign="top">A signed integral type used to represent the distance
between two of the Collection's iterators. This type must be the same
as the iterator's distance type.</td>
</tr>
<tr>
<td valign="top">Size type</td>
<td valign="top"><tt>X::size_type</tt></td>
<td valign="top">An unsigned integral type that can represent any
nonnegative value of the Collection's distance type.</td>
</tr>
</table>
<h3>Notation</h3>
<table summary="">
<tr>
<td valign="top"><tt>X</tt></td>
<td valign="top">A type that is a model of Collection.</td>
</tr>
<tr>
<td valign="top"><tt>a</tt>, <tt>b</tt></td>
<td valign="top">Object of type <tt>X</tt>.</td>
</tr>
<tr>
<td valign="top"><tt>T</tt></td>
<td valign="top">The value type of <tt>X</tt>.</td>
</tr>
</table>
<h3>Valid expressions</h3>
<p>The following expressions must be valid.</p>
<table border summary="">
<tr>
<th>Name</th>
<th>Expression</th>
<th>Return type</th>
</tr>
<tr>
<td valign="top">Beginning of range</td>
<td valign="top"><tt>a.begin()</tt></td>
<td valign="top"><tt>iterator</tt> if <tt>a</tt> is mutable,
<tt>const_iterator</tt> otherwise</td>
</tr>
<tr>
<td valign="top">End of range</td>
<td valign="top"><tt>a.end()</tt></td>
<td valign="top"><tt>iterator</tt> if <tt>a</tt> is mutable,
<tt>const_iterator</tt> otherwise</td>
</tr>
<tr>
<td valign="top">Size</td>
<td valign="top"><tt>a.size()</tt></td>
<td valign="top"><tt>size_type</tt></td>
</tr><!--
<TR>
<TD VAlign=top>
Maximum size
</TD>
<TD VAlign=top>
<tt>a.max_size()</tt>
</TD>
<TD VAlign=top>
<tt>size_type</tt>
</TD>
</TR>
-->
<tr>
<td valign="top">Empty Collection</td>
<td valign="top"><tt>a.empty()</tt></td>
<td valign="top">Convertible to <tt>bool</tt></td>
</tr>
<tr>
<td valign="top">Swap</td>
<td valign="top"><tt>a.swap(b)</tt></td>
<td valign="top"><tt>void</tt></td>
</tr>
</table>
<h3>Expression semantics</h3>
<table border summary="">
<tr>
<th>Name</th>
<th>Expression</th>
<th>Semantics</th>
<th>Postcondition</th>
</tr>
<tr>
<td valign="top">Beginning of range</td>
<td valign="top"><tt>a.begin()</tt></td>
<td valign="top">Returns an iterator pointing to the first element in
the Collection.</td>
<td valign="top"><tt>a.begin()</tt> is either dereferenceable or
past-the-end. It is past-the-end if and only if <tt>a.size() ==
0</tt>.</td>
</tr>
<tr>
<td valign="top">End of range</td>
<td valign="top"><tt>a.end()</tt></td>
<td valign="top">Returns an iterator pointing one past the last element
in the Collection.</td>
<td valign="top"><tt>a.end()</tt> is past-the-end.</td>
</tr>
<tr>
<td valign="top">Size</td>
<td valign="top"><tt>a.size()</tt></td>
<td valign="top">Returns the size of the Collection, that is, its
number of elements.</td>
<td valign="top"><tt>a.size() &gt;= 0</tt></td>
</tr><!--
<TR>
<TD VAlign=top>
Maximum size
</TD>
<TD VAlign=top>
<tt>a.max_size()</tt>
</TD>
<TD VAlign=top>
&nbsp;
</TD>
<TD VAlign=top>
Returns the largest size that this Collection can ever have. <A href="#8">[8]</A>
</TD>
<TD VAlign=top>
<tt>a.max_size() &gt;= 0 &amp;&amp; a.max_size() &gt;= a.size()</tt>
</TD>
</TR>
-->
<tr>
<td valign="top">Empty Collection</td>
<td valign="top"><tt>a.empty()</tt></td>
<td valign="top">Equivalent to <tt>a.size() == 0</tt>. (But possibly
faster.)</td>
<td valign="top">&nbsp;</td>
</tr>
<tr>
<td valign="top">Swap</td>
<td valign="top"><tt>a.swap(b)</tt></td>
<td valign="top">Equivalent to <tt>swap(a,b)</tt></td>
<td valign="top">&nbsp;</td>
</tr>
</table>
<h3>Complexity guarantees</h3>
<p><tt>begin()</tt> and <tt>end()</tt> are amortized constant time.</p>
<p><tt>size()</tt> is at most linear in the Collection's size.
<tt>empty()</tt> is amortized constant time.</p>
<p><tt>swap()</tt> is at most linear in the size of the two
collections.</p>
<h3>Invariants</h3>
<table border summary="">
<tr>
<td valign="top">Valid range</td>
<td valign="top">For any Collection <tt>a</tt>, <tt>[a.begin(),
a.end())</tt> is a valid range.</td>
</tr>
<tr>
<td valign="top">Range size</td>
<td valign="top"><tt>a.size()</tt> is equal to the distance from
<tt>a.begin()</tt> to <tt>a.end()</tt>.</td>
</tr>
<tr>
<td valign="top">Completeness</td>
<td valign="top">An algorithm that iterates through the range
<tt>[a.begin(), a.end())</tt> will pass through every element of
<tt>a</tt>.</td>
</tr>
</table>
<h3>Models</h3>
<ul>
<li><tt>array</tt></li>
<li><tt>array_ptr</tt></li>
<li><tt>vector&lt;bool&gt;</tt></li>
</ul>
<h3>Collection Refinements</h3>
<p>There are quite a few concepts that refine the Collection concept,
similar to the concepts that refine the Container concept. Here is a brief
overview of the refining concepts.</p>
<h4>ForwardCollection</h4>
<p>The elements are arranged in some order that does not change
spontaneously from one iteration to the next. As a result, a
ForwardCollection is <a href=
"http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>
and <a href=
"http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</a>.
In addition, the iterator type of a ForwardCollection is a
MultiPassInputIterator which is just an InputIterator with the added
requirements that the iterator can be used to make multiple passes through
a range, and that if <tt>it1 == it2</tt> and <tt>it1</tt> is
dereferenceable then <tt>++it1 == ++it2</tt>. The ForwardCollection also
has a <tt>front()</tt> method.</p>
<table border summary="">
<tr>
<th>Name</th>
<th>Expression</th>
<th>Return type</th>
<th>Semantics</th>
</tr>
<tr>
<td valign="top">Front</td>
<td valign="top"><tt>a.front()</tt></td>
<td valign="top"><tt>reference</tt> if <tt>a</tt> is mutable,<br>
<tt>const_reference</tt> otherwise.</td>
<td valign="top">Equivalent to <tt>*(a.begin())</tt>.</td>
</tr>
</table>
<h4>ReversibleCollection</h4>
<p>The container provides access to iterators that traverse in both
directions (forward and reverse). The iterator type must meet all of the
requirements of <a href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>
except that the reference type does not have to be a real C++ reference.
The ReversibleCollection adds the following requirements to those of
ForwardCollection.</p>
<table border summary="">
<tr>
<th>Name</th>
<th>Expression</th>
<th>Return type</th>
<th>Semantics</th>
</tr>
<tr>
<td valign="top">Beginning of range</td>
<td valign="top"><tt>a.rbegin()</tt></td>
<td valign="top"><tt>reverse_iterator</tt> if <tt>a</tt> is mutable,
<tt>const_reverse_iterator</tt> otherwise.</td>
<td valign="top">Equivalent to
<tt>X::reverse_iterator(a.end())</tt>.</td>
</tr>
<tr>
<td valign="top">End of range</td>
<td valign="top"><tt>a.rend()</tt></td>
<td valign="top"><tt>reverse_iterator</tt> if <tt>a</tt> is mutable,
<tt>const_reverse_iterator</tt> otherwise.</td>
<td valign="top">Equivalent to
<tt>X::reverse_iterator(a.begin())</tt>.</td>
</tr>
<tr>
<td valign="top">Back</td>
<td valign="top"><tt>a.back()</tt></td>
<td valign="top"><tt>reference</tt> if <tt>a</tt> is mutable,<br>
<tt>const_reference</tt> otherwise.</td>
<td valign="top">Equivalent to <tt>*(--a.end())</tt>.</td>
</tr>
</table>
<h4>SequentialCollection</h4>
<p>The elements are arranged in a strict linear order. No extra methods are
required.</p>
<h4>RandomAccessCollection</h4>
<p>The iterators of a RandomAccessCollection satisfy all of the
requirements of <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a>
except that the reference type does not have to be a real C++ reference. In
addition, a RandomAccessCollection provides an element access operator.</p>
<table border summary="">
<tr>
<th>Name</th>
<th>Expression</th>
<th>Return type</th>
<th>Semantics</th>
</tr>
<tr>
<td valign="top">Element Access</td>
<td valign="top"><tt>a[n]</tt></td>
<td valign="top"><tt>reference</tt> if <tt>a</tt> is mutable,
<tt>const_reference</tt> otherwise.</td>
<td valign="top">Returns the nth element of the Collection. <tt>n</tt>
must be convertible to <tt>size_type</tt>. Precondition: <tt>0 &lt;= n
&lt; a.size()</tt>.</td>
</tr>
</table>
<h3>Notes</h3>
<p><a name="n1" id="n1">[1]</a> The reference type does not have to be a
real C++ reference. The requirements of the reference type depend on the
context within which the Collection is being used. Specifically it depends
on the requirements the context places on the value type of the Collection.
The reference type of the Collection must meet the same requirements as the
value type. In addition, the reference objects must be equivalent to the
value type objects in the collection (which is trivially true if they are
the same object). Also, in a mutable Collection, an assignment to the
reference object must result in an assignment to the object in the
Collection (again, which is trivially true if they are the same object, but
non-trivial if the reference type is a proxy class).</p>
<h3>See also</h3>
<p><a href=
"http://www.sgi.com/tech/stl/Container.html">Container</a><br></p>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
<table summary="">
<tr valign="top">
<td nowrap><i>Copyright &copy; 2000</i></td>
<td><i><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy
Siek</a>, Univ.of Notre Dame and C++ Library &amp; Compiler Group/SGI
(<a href="mailto:jsiek@engr.sgi.com">jsiek@engr.sgi.com</a>)</i></td>
</tr>
</table>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>

View File

@ -1,139 +1,178 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<!--
-- Copyright (c) Jeremy Siek 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Silicon Graphics makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Copy Constructible</Title>
</HEAD>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<!--end header-->
<BR Clear>
<H1>Copy Constructible</H1>
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<h3>Description</h3>
A type is Copy Constructible if it is possible to copy objects of that
type.
<title>Copy Constructible</title>
</head>
<h3>Notation</h3>
<Table>
<TR>
<TD VAlign=top>
<tt>T</tt>
</TD>
<TD VAlign=top>
is type that is a model of Copy Constructible
</TD>
</TR>
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86"><br clear="none">
<TR>
<TD VAlign=top>
<tt>t</tt>
</TD>
<TD VAlign=top>
is an object of type <tt>T</tt>
</TD>
</tr>
<h1>Copy Constructible</h1>
<TR>
<TD VAlign=top>
<tt>u</tt>
</TD>
<TD VAlign=top>
is an object of type <tt>const T</tt>
</TD>
</tr>
<h3>Description</h3>
</table>
<h3>Definitions</h3>
<h3>Valid expressions</h3>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Return type
</TH>
<TH>
Semantics
</TH>
</TR>
<TR>
<TD VAlign=top>
Copy constructor
</TD>
<TD VAlign=top>
<tt>T(t)</tt>
</TD>
<TD VAlign=top>
<tt>T</tt>
</TD>
<TD VAlign=top>
<tt>t</tt> is equivalent to <tt>T(t)</tt>
</TD>
</TR>
<p>A type is Copy Constructible if it is possible to copy objects of that
type.</p>
<h3>Notation</h3>
<table summary="">
<tr>
<td valign="top"><tt>T</tt></td>
<td valign="top">is type that is a model of Copy Constructible</td>
</tr>
<tr>
<td valign="top"><tt>t</tt></td>
<td valign="top">is an object of type <tt>T</tt></td>
</tr>
<tr>
<td valign="top"><tt>u</tt></td>
<td valign="top">is an object of type <tt>const T</tt></td>
</tr>
</table>
<h3>Definitions</h3>
<h3>Valid expressions</h3>
<table border summary="">
<tr>
<th>Name</th>
<th>Expression</th>
<th>Return type</th>
<th>Semantics</th>
</tr>
<tr>
<td valign="top">Copy constructor</td>
<td valign="top"><tt>T(t)</tt></td>
<td valign="top"><tt>T</tt></td>
<td valign="top"><tt>t</tt> is equivalent to <tt>T(t)</tt></td>
</tr>
<tr>
<td valign="top">Copy constructor</td>
<td valign="top">
<pre>
<TR>
<TD VAlign=top>
Copy constructor
</TD>
<TD VAlign=top>
<pre>
T(u)
</pre>
</td>
</TD>
<TD VAlign=top>
<tt>T</tt>
</TD>
<TD VAlign=top>
<tt>u</tt> is equivalent to <tt>T(u)</tt>
</TD>
</TR>
<td valign="top"><tt>T</tt></td>
<td valign="top"><tt>u</tt> is equivalent to <tt>T(u)</tt></td>
</tr>
<tr>
<td valign="top">Destructor</td>
<td valign="top">
<pre>
<TR>
<TD VAlign=top>
Destructor
</TD>
<TD VAlign=top>
<pre>
t.~T()
</pre>
</td>
</TD>
<TD VAlign=top>
<tt>T</tt>
</TD>
<TD VAlign=top>
&nbsp;
</TD>
</TR>
<td valign="top"><tt>T</tt></td>
<td valign="top">&nbsp;</td>
</tr>
<tr>
<td valign="top">Address Operator</td>
<td valign="top">
<pre>
<TR>
<TD VAlign=top>
Address Operator
</TD>
<TD VAlign=top>
<pre>
&amp;t
</pre>
</td>
</TD>
<TD VAlign=top>
<tt>T*</tt>
</TD>
<TD VAlign=top>
denotes the address of <tt>t</tt>
</TD>
</TR>
<td valign="top"><tt>T*</tt></td>
<td valign="top">denotes the address of <tt>t</tt></td>
</tr>
<tr>
<td valign="top">Address Operator</td>
<td valign="top">
<pre>
<TR>
<TD VAlign=top>
Address Operator
</TD>
<TD VAlign=top>
<pre>
&amp;u
</pre>
</td>
</TD>
<TD VAlign=top>
<tt>T*</tt>
</TD>
<TD VAlign=top>
denotes the address of <tt>u</tt>
</TD>
</TR>
<td valign="top"><tt>T*</tt></td>
<td valign="top">denotes the address of <tt>u</tt></td>
</tr>
</table>
<h3>Models</h3>
</table>
<ul>
<li><tt>int</tt></li>
<li><tt>std::pair</tt></li>
</ul>
</table>
<h3>Models</h3>
<h3>Concept Checking Class</h3>
<pre>
<UL>
<LI><tt>int</tt>
<LI><tt>std::pair</tt>
</UL>
<h3>Concept Checking Class</h3>
<pre>
template &lt;class T&gt;
struct CopyConstructibleConcept
{
@ -153,33 +192,19 @@ t.~T()
};
</pre>
<h3>See also</h3>
<h3>See also</h3>
<A
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</A>
and
<A hrefa="./Assignable.html">Assignable</A>
<p><a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default
Constructible</a> and <a href="./Assignable.html">Assignable</a><br></p>
<hr>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF=http://www.lsc.nd.edu/~jsiek>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
</TD></TR></TABLE>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
<table summary="">
<tr valign="top">
<td nowrap><i>Copyright &copy; 2000</i></td>
<td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of
Notre Dame (<a href=
"mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td>
</tr>
</table>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
</BODY>
</HTML>

View File

@ -1,210 +1,212 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<HTML>
<!--
== Copyright (c) 1996-1999
== Silicon Graphics Computer Systems, Inc.
==
== Permission to use, copy, modify, distribute and sell this software
== and its documentation for any purpose is hereby granted without fee,
== provided that the above copyright notice appears in all copies and
== that both that copyright notice and this permission notice appear
== in supporting documentation. Silicon Graphics makes no
== representations about the suitability of this software for any
== purpose. It is provided "as is" without express or implied warranty.
==
== Copyright (c) 1994
== Hewlett-Packard Company
==
== Permission to use, copy, modify, distribute and sell this software
== and its documentation for any purpose is hereby granted without fee,
== provided that the above copyright notice appears in all copies and
== that both that copyright notice and this permission notice appear
== in supporting documentation. Hewlett-Packard Company makes no
== representations about the suitability of this software for any
== purpose. It is provided "as is" without express or implied warranty.
==
-- Copyright (c) Jeremy Siek 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Silicon Graphics makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<!--
-- Copyright (c) 1996-1999
-- Silicon Graphics Computer Systems, Inc.
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Silicon Graphics makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
--
-- Copyright (c) 1994
-- Hewlett-Packard Company
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Hewlett-Packard Company makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
--
-->
<Head>
<Title>LessThanComparable</Title>
</Head>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<!--end header-->
<BR Clear>
<H1>LessThanComparable</H1>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<h3>Description</h3>
A type is LessThanComparable if it is ordered: it must
be possible to compare two objects of that type using <tt>operator&lt;</tt>, and
<tt>operator&lt;</tt> must be a strict weak ordering relation.
<title>LessThanComparable</title>
</head>
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86"><br clear="none">
<h3>Refinement of</h3>
<h3>Associated types</h3>
<h3>Notation</h3>
<Table>
<TR>
<TD VAlign=top>
<tt>X</tt>
</TD>
<TD VAlign=top>
A type that is a model of LessThanComparable
</TD>
</TR>
<TR>
<TD VAlign=top>
<tt>x</tt>, <tt>y</tt>, <tt>z</tt>
</TD>
<TD VAlign=top>
Object of type <tt>X</tt>
</TD>
</tr>
</table>
<h3>Definitions</h3>
Consider the relation <tt>!(x &lt; y) &amp;&amp; !(y &lt; x)</tt>. If this relation is
transitive (that is, if <tt>!(x &lt; y) &amp;&amp; !(y &lt; x) &amp;&amp; !(y &lt; z) &amp;&amp; !(z &lt; y)</tt>
implies <tt>!(x &lt; z) &amp;&amp; !(z &lt; x)</tt>), then it satisfies the mathematical
definition of an equivalence relation. In this case, <tt>operator&lt;</tt>
is a <i>strict weak ordering</i>.
<P>
If <tt>operator&lt;</tt> is a strict weak ordering, and if each equivalence class
has only a single element, then <tt>operator&lt;</tt> is a <i>total ordering</i>.
<h3>Valid expressions</h3>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Type requirements
</TH>
<TH>
Return type
</TH>
</TR>
<TR>
<TD VAlign=top>
Less
</TD>
<TD VAlign=top>
<tt>x &lt; y</tt>
</TD>
<TD VAlign=top>
&nbsp;
</TD>
<TD VAlign=top>
Convertible to <tt>bool</tt>
</TD>
</TR>
</table>
<h1>LessThanComparable</h1>
<h3>Description</h3>
<p>A type is LessThanComparable if it is ordered: it must be possible to
compare two objects of that type using <tt>operator&lt;</tt>, and
<tt>operator&lt;</tt> must be a strict weak ordering relation.</p>
<h3>Expression semantics</h3>
<Table border>
<TR>
<TH>
Name
</TH>
<TH>
Expression
</TH>
<TH>
Precondition
</TH>
<TH>
Semantics
</TH>
<TH>
Postcondition
</TH>
</TR>
<TR>
<TD VAlign=top>
Less
</TD>
<TD VAlign=top>
<tt>x &lt; y</tt>
</TD>
<TD VAlign=top>
<tt>x</tt> and <tt>y</tt> are in the domain of <tt>&lt;</tt>
</TD>
<TD VAlign=top>
&nbsp;
</TD>
</table>
<h3>Refinement of</h3>
<h3>Associated types</h3>
<h3>Complexity guarantees</h3>
<h3>Invariants</h3>
<Table border>
<TR>
<TD VAlign=top>
Irreflexivity
</TD>
<TD VAlign=top>
<tt>x &lt; x</tt> must be false.
</TD>
</TR>
<TR>
<TD VAlign=top>
Antisymmetry
</TD>
<TD VAlign=top>
<tt>x &lt; y</tt> implies !(y &lt; x) <A href="#2">[2]</A>
</TD>
</TR>
<TR>
<TD VAlign=top>
Transitivity
</TD>
<TD VAlign=top>
<tt>x &lt; y</tt> and <tt>y &lt; z</tt> implies <tt>x &lt; z</tt> <A href="#3">[3]</A>
</TD>
</tr>
</table>
<h3>Models</h3>
<UL>
<LI>
int
</UL>
<h3>Notes</h3>
<P><A name="1">[1]</A>
Only <tt>operator&lt;</tt> is fundamental; the other inequality operators
are essentially syntactic sugar.
<P><A name="2">[2]</A>
Antisymmetry is a theorem, not an axiom: it follows from
irreflexivity and transitivity.
<P><A name="3">[3]</A>
Because of irreflexivity and transitivity, <tt>operator&lt;</tt> always
satisfies the definition of a <i>partial ordering</i>. The definition of
a <i>strict weak ordering</i> is stricter, and the definition of a
<i>total ordering</i> is stricter still.
<h3>See also</h3>
<A href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</A>, <A href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">StrictWeakOrdering</A>
<h3>Notation</h3>
<table summary="">
<tr>
<td valign="top"><tt>X</tt></td>
<td valign="top">A type that is a model of LessThanComparable</td>
</tr>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF=http://www.lsc.nd.edu/~jsiek>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
</TD></TR></TABLE>
<tr>
<td valign="top"><tt>x</tt>, <tt>y</tt>, <tt>z</tt></td>
<td valign="top">Object of type <tt>X</tt></td>
</tr>
</table>
<h3>Definitions</h3>
<p>Consider the relation <tt>!(x &lt; y) &amp;&amp; !(y &lt; x)</tt>. If
this relation is transitive (that is, if <tt>!(x &lt; y) &amp;&amp; !(y
&lt; x) &amp;&amp; !(y &lt; z) &amp;&amp; !(z &lt; y)</tt> implies <tt>!(x
&lt; z) &amp;&amp; !(z &lt; x)</tt>), then it satisfies the mathematical
definition of an equivalence relation. In this case, <tt>operator&lt;</tt>
is a <i>strict weak ordering</i>.</p>
<p>If <tt>operator&lt;</tt> is a strict weak ordering, and if each
equivalence class has only a single element, then <tt>operator&lt;</tt> is
a <i>total ordering</i>.</p>
<h3>Valid expressions</h3>
<table border summary="">
<tr>
<th>Name</th>
<th>Expression</th>
<th>Type requirements</th>
<th>Return type</th>
</tr>
<tr>
<td valign="top">Less</td>
<td valign="top"><tt>x &lt; y</tt></td>
<td valign="top">&nbsp;</td>
<td valign="top">Convertible to <tt>bool</tt></td>
</tr>
</table>
<h3>Expression semantics</h3>
<table border summary="">
<tr>
<th>Name</th>
<th>Expression</th>
<th>Precondition</th>
<th>Semantics</th>
<th>Postcondition</th>
</tr>
<tr>
<td valign="top">Less</td>
<td valign="top"><tt>x &lt; y</tt></td>
<td valign="top"><tt>x</tt> and <tt>y</tt> are in the domain of
<tt>&lt;</tt></td>
<td valign="top">&nbsp;</td>
</tr>
</table>
<h3>Complexity guarantees</h3>
<h3>Invariants</h3>
<table border summary="">
<tr>
<td valign="top">Irreflexivity</td>
<td valign="top"><tt>x &lt; x</tt> must be false.</td>
</tr>
<tr>
<td valign="top">Antisymmetry</td>
<td valign="top"><tt>x &lt; y</tt> implies !(y &lt; x) <a href=
"#n2">[2]</a></td>
</tr>
<tr>
<td valign="top">Transitivity</td>
<td valign="top"><tt>x &lt; y</tt> and <tt>y &lt; z</tt> implies <tt>x
&lt; z</tt> <a href="#n3">[3]</a></td>
</tr>
</table>
<h3>Models</h3>
<ul>
<li>int</li>
</ul>
<h3>Notes</h3>
<p><a name="n1" id="n1">[1]</a> Only <tt>operator&lt;</tt> is fundamental;
the other inequality operators are essentially syntactic sugar.</p>
<p><a name="n2" id="n2">[2]</a> Antisymmetry is a theorem, not an axiom: it
follows from irreflexivity and transitivity.</p>
<p><a name="n3" id="n3">[3]</a> Because of irreflexivity and transitivity,
<tt>operator&lt;</tt> always satisfies the definition of a <i>partial
ordering</i>. The definition of a <i>strict weak ordering</i> is stricter,
and the definition of a <i>total ordering</i> is stricter still.</p>
<h3>See also</h3>
<p><a href=
"http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</a>,
<a href=
"http://www.sgi.com/tech/stl/StrictWeakOrdering.html">StrictWeakOrdering</a><br>
</p>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
<table summary="">
<tr valign="top">
<td nowrap><i>Copyright &copy; 2000</i></td>
<td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of
Notre Dame (<a href=
"mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td>
</tr>
</table>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
</BODY>
</HTML>

View File

@ -1,95 +1,92 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<!--
-- Copyright (c) Jeremy Siek 2000
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. Silicon Graphics makes no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>MultiPassInputIterator</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<BR Clear>
<title>MultiPassInputIterator</title>
</head>
<H2>
<A NAME="concept:MultiPassInputIterator"></A>
Multi-Pass Input Iterator
</H2>
<body bgcolor="#FFFFFF" link="#0000EE" text="#000000" vlink="#551A8B" alink=
"#FF0000">
<img src="../../boost.png" alt="C++ Boost" width="277" height=
"86"><br clear="none">
This concept is a refinement of <a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>,
adding the requirements that the iterator can be used to make multiple
passes through a range, and that if <TT>it1 == it2</TT> and
<TT>it1</TT> is dereferenceable then <TT>++it1 == ++it2</TT>. The
Multi-Pass Input Iterator is very similar to the <a
href="http://www.sgi.com/tech/stl/ForwardIterator.hmtl">Forward Iterator</a>. The
only difference is that a <a
href="http://www.sgi.com/tech/stl/ForwardIterator.hmtl">Forward Iterator</a>
requires the <TT>reference</TT> type to be <TT>value_type&amp;</TT>, whereas
MultiPassInputIterator is like <a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>
in that the <TT>reference</TT> type merely has to be convertible to
<TT>value_type</TT>.
<h2><a name="concept:MultiPassInputIterator" id=
"concept:MultiPassInputIterator"></a> Multi-Pass Input Iterator</h2>
<p>This concept is a refinement of <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>, adding
the requirements that the iterator can be used to make multiple passes
through a range, and that if <tt>it1 == it2</tt> and <tt>it1</tt> is
dereferenceable then <tt>++it1 == ++it2</tt>. The Multi-Pass Input Iterator
is very similar to the <a href=
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterator</a>.
The only difference is that a <a href=
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterator</a>
requires the <tt>reference</tt> type to be <tt>value_type&amp;</tt>,
whereas MultiPassInputIterator is like <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a> in that
the <tt>reference</tt> type merely has to be convertible to
<tt>value_type</tt>.</p>
<h3>Design Notes</h3>
<h3>Design Notes</h3>
comments by Valentin Bonnard:
<p>comments by Valentin Bonnard:</p>
<p> I think that introducing Multi-Pass Input Iterator isn't the right
solution. Do you also want to define Multi-Pass Bidirectionnal Iterator
and Multi-Pass Random Access Iterator ? I don't, definitly. It only
confuses the issue. The problem lies into the existing hierarchy of
iterators, which mixes movabillity, modifiabillity and lvalue-ness,
and these are clearly independant.
<p>I think that introducing Multi-Pass Input Iterator isn't the right
solution. Do you also want to define Multi-Pass Bidirectionnal Iterator and
Multi-Pass Random Access Iterator ? I don't, definitly. It only confuses
the issue. The problem lies into the existing hierarchy of iterators, which
mixes movabillity, modifiabillity and lvalue-ness, and these are clearly
independant.</p>
<p> The terms Forward, Bidirectionnal and Random Access are about
movabillity and shouldn't be used to mean anything else. In a
completly orthogonal way, iterators can be immutable, mutable, or
neither. Lvalueness of iterators is also orthogonal with
immutabillity. With these clean concepts, your Multi-Pass Input Iterator
is just called a Forward Iterator.
<p>The terms Forward, Bidirectionnal and Random Access are about
movabillity and shouldn't be used to mean anything else. In a completly
orthogonal way, iterators can be immutable, mutable, or neither. Lvalueness
of iterators is also orthogonal with immutabillity. With these clean
concepts, your Multi-Pass Input Iterator is just called a Forward
Iterator.</p>
<p>
Other translations are:<br>
std::Forward Iterator -> ForwardIterator & Lvalue Iterator<br>
std::Bidirectionnal Iterator -> Bidirectionnal Iterator & Lvalue Iterator<br>
std::Random Access Iterator -> Random Access Iterator & Lvalue Iterator<br>
<p>Other translations are:<br>
std::Forward Iterator -&gt; ForwardIterator &amp; Lvalue Iterator<br>
std::Bidirectionnal Iterator -&gt; Bidirectionnal Iterator &amp; Lvalue
Iterator<br>
std::Random Access Iterator -&gt; Random Access Iterator &amp; Lvalue
Iterator<br></p>
<p>
Note that in practice the only operation not allowed on my
Forward Iterator which is allowed on std::Forward Iterator is
<tt>&*it</tt>. I think that <tt>&*</tt> is rarely needed in generic code.
<p>Note that in practice the only operation not allowed on my Forward
Iterator which is allowed on std::Forward Iterator is <tt>&amp;*it</tt>. I
think that <tt>&amp;*</tt> is rarely needed in generic code.</p>
<p>
reply by Jeremy Siek:
<p>reply by Jeremy Siek:</p>
<p>
The above analysis by Valentin is right on. Of course, there is
the problem with backward compatibility. The current STL implementations
are based on the old definition of Forward Iterator. The right course
of action is to get Forward Iterator, etc. changed in the C++ standard.
Once that is done we can drop Multi-Pass Input Iterator.
<p>The above analysis by Valentin is right on. Of course, there is the
problem with backward compatibility. The current STL implementations are
based on the old definition of Forward Iterator. The right course of action
is to get Forward Iterator, etc. changed in the C++ standard. Once that is
done we can drop Multi-Pass Input Iterator.<br></p>
<hr>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<a HREF="../../people/jeremy_siek.htm">Jeremy Siek</a>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
</TD></TR></TABLE>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05
December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
<table summary="">
<tr valign="top">
<td nowrap><i>Copyright &copy; 2000</i></td>
<td><i><a href="http://www.lsc.nd.edu/~jsiek">Jeremy Siek</a>, Univ.of
Notre Dame (<a href=
"mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</a>)</i></td>
</tr>
</table>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>
</BODY>
</HTML>

View File

@ -1,158 +0,0 @@
<HTML>
<Head>
<Title>OptionalPointee Concept</Title>
</HEAD>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../boost.png"
ALT="C++ Boost" width="277" height="86">
<!--end header-->
<BR Clear>
<H1>Concept: OptionalPointee</H1>
<h3>Description</h3>
A type is a model of <i>OptionalPointee</i> if it points to (or refers to) a value
that may not exist. That is, if it has a <b>pointee</b> which might be <b>valid</b>
(existent) or <b>invalid</b> (inexistent); and it is possible to test whether the
pointee is valid or not.
This model does <u>not</u> imply pointer semantics: i.e., it does not imply shallow copy nor
aliasing.
<h3>Notation</h3>
<Table>
<TR>
<TD VAlign=top> <tt>T</tt> </TD>
<TD VAlign=top> is a type that is a model of OptionalPointee</TD>
</TR>
<TR>
<TD VAlign=top> <tt>t</tt> </TD>
<TD VAlign=top> is an object of type <tt>T</tt> or possibly <tt>const T</tt></TD>
</tr>
</table>
<h3>Definitions</h3>
<h3>Valid expressions</h3>
<Table border>
<TR>
<TH> Name </TH>
<TH> Expression </TH>
<TH> Return type </TH>
<TH> Semantics </TH>
</TR>
<TR>
<TD VAlign=top>Value Access</TD>
<TD VAlign=top>&nbsp;<tt>*t</tt></TD>
<TD VAlign=top>&nbsp;<tt>T&amp;</tt></TD>
<TD VAlign=top>If the pointee is valid returns a reference to
the pointee.<br>
If the pointee is invalid the result is <i>undefined</i>.</TD>
<TD VAlign=top> </TD>
</TR>
<TR>
<TD VAlign=top>Value Access</TD>
<TD VAlign=top>&nbsp;<tt>t-><i>xyz</i></tt></TD>
<TD VAlign=top>&nbsp;<tt>T*</tt></TD>
<TD VAlign=top>If the pointee is valid returns a builtin pointer to the pointee.<br>
If the pointee is invalid the result is <i>undefined</i> (It might not even return NULL).<br>
</TD>
<TD VAlign=top> </TD>
</TR>
<TR>
<TD VAlign=top>Validity Test</TD>
<TD VAlign=top>&nbsp;<tt>t</tt><br>
&nbsp;<tt>t != 0</tt><br>
&nbsp;<tt>!!t</tt>
</TD>
<TD VAlign=top>&nbsp;bool </TD>
<TD VAlign=top>If the pointee is valid returns true.<br>
If the pointee is invalid returns false.</TD>
<TD VAlign=top></TD>
</TR>
<TR>
<TD VAlign=top>Invalidity Test</TD>
<TD VAlign=top>&nbsp;<tt>t == 0</tt><br>
&nbsp;<tt>!t</tt>
</TD>
<TD VAlign=top>&nbsp;bool </TD>
<TD VAlign=top>If the pointee is valid returns false.<br>
If the pointee is invalid returns true.</TD>
<TD VAlign=top></TD>
</TR>
</table>
<h3>Models</h3>
<UL>
<LI><tt>pointers, both builtin and smart.</tt>
<LI><tt>boost::optional&lt;&gt;</tt>
</UL>
<HR>
<h3>OptionalPointee and relational operations</h3>
<p>This concept does not define any particular semantic for relational operations, therefore,
a type which models this concept might have either shallow or deep relational semantics.<br>
For instance, pointers, which are models of OptionalPointee, have shallow relational operators:
comparisons of pointers do not involve comparisons of pointees.
This makes sense for pointers because they have shallow copy semantics.<br>
But boost::optional&lt;T&gt;, on the other hand, which is also a model of OptionalPointee, has
deep-copy and deep-relational semantics.<br>
If generic code is written for this concept, it is important not to use relational
operators directly because the semantics might be different depending on the actual type.<br>
Still, the concept itsef can be used to define <i>deep</i> relational tests that can
be used in generic code with any type which models OptionalPointee:</p>
<a name="equal"></a>
<p><u>Equivalence relation:</u></p>
<pre>template&lt;class OptionalPointee&gt;
inline
bool equal_pointees ( OptionalPointee const&amp; x, OptionalPointee const&amp; y )
{
return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ;
}
template&lt;class OptionalPointee&gt;
struct equal_pointees_t : std::binary_function&lt;OptionalPointee,OptionalPointee,bool&gt;
{
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
{ return equal_pointees(x,y) ; }
} ;
</pre>
<p>The preceding generic function and function object have the following semantics:<br>
If both <b>x</b> and <b>y</b> have valid pointees, it compares values via <code>(*x == *y)</code>.<br>
If only one has a valid pointee, returns <code>false</code>.<br>
If both have invalid pointees, returns <code>true</code>.</p>
<a name="less"></a>
<p><u>Less-than relation:</u></p>
<pre>template&lt;class OptionalPointee&gt;
inline
bool less_pointees ( OptionalPointee const&amp; x, OptionalPointee const&amp; y )
{
return !y ? false : ( !x ? true : (*x) < (*y) ) ;
}
template&lt;class OptionalPointee&gt;
struct less_pointees_t : std::binary_function&lt;OptionalPointee,OptionalPointee,bool&gt;
{
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
{ return less_pointees(x,y) ; }
} ;
</pre>
<p>The preceding generic function and function object have the following semantics:<br>
If <b>y</b> has an invalid pointee, returns <code>false</code>.<br>
Else, if <b>x</b> has an invalid pointee, returns <code>true</code>.<br>
Else, ( <b>x</b> and <b>y</b> have valid pointees), compares values via <code>(*x &lt;
*y).</code></p>
<p><br>
All these functions and function
objects are is implemented in <a href="../../boost/utility/compare_pointees.hpp">compare_pointees.hpp</a></p>
<p>Notice that OptionalPointee does not imply aliasing (and optional&lt;&gt; for instance does not alias);
so direct usage of relational operators with the implied aliasing of shallow semantics
-as with pointers- should not be used with generic code written for this concept.</p>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2003</TD><TD>
<A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>,
based on the original concept developed by Augustus Saunders.
</TD></TR></TABLE>
</BODY>
</HTML>

View File

@ -1,94 +0,0 @@
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
// Douglas Gregor (gregod@cs.rpi.edu)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// For more information, see http://www.boost.org
#include <boost/utility/addressof.hpp>
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(push, 3)
#endif
#include <iostream>
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
#pragma warning(pop)
#endif
#include <boost/detail/lightweight_test.hpp>
template<class T> void scalar_test( T * = 0 )
{
T* px = new T();
T& x = *px;
BOOST_TEST( boost::addressof(x) == px );
const T& cx = *px;
const T* pcx = boost::addressof(cx);
BOOST_TEST( pcx == px );
volatile T& vx = *px;
volatile T* pvx = boost::addressof(vx);
BOOST_TEST( pvx == px );
const volatile T& cvx = *px;
const volatile T* pcvx = boost::addressof(cvx);
BOOST_TEST( pcvx == px );
delete px;
}
template<class T> void array_test( T * = 0 )
{
T nrg[3] = {1,2,3};
T (*pnrg)[3] = &nrg;
BOOST_TEST( boost::addressof(nrg) == pnrg );
T const cnrg[3] = {1,2,3};
T const (*pcnrg)[3] = &cnrg;
BOOST_TEST( boost::addressof(cnrg) == pcnrg );
}
struct addressable
{
addressable( int = 0 )
{
}
};
struct useless_type {};
class nonaddressable {
public:
nonaddressable( int = 0 )
{
}
void dummy(); // Silence GCC warning: all member of class are private
private:
useless_type operator&() const;
};
int main()
{
scalar_test<char>();
scalar_test<int>();
scalar_test<addressable>();
scalar_test<nonaddressable>();
array_test<char>();
array_test<int>();
array_test<addressable>();
array_test<nonaddressable>();
return boost::report_errors();
}

View File

@ -1,55 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Boost: assert.hpp documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
<table border="0" width="100%">
<tr>
<td width="277"><A href="../../index.htm"> <img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86" border="0"></A>
</td>
<td align="center">
<h1>assert.hpp</h1>
</td>
</tr>
<tr>
<td colspan="2" height="64">&nbsp;</td>
</tr>
</table>
<p>
The header <STRONG>&lt;boost/assert.hpp&gt;</STRONG> defines the macro <b>BOOST_ASSERT</b>,
which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG>&lt;cassert&gt;</STRONG>.
The macro is intended to be used in Boost libraries.
</p>
<P>By default, <tt>BOOST_ASSERT(expr)</tt> is equivalent to <tt>assert(expr)</tt>.</P>
<P>When the macro <STRONG>BOOST_DISABLE_ASSERTS</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
is included, <tt>BOOST_ASSERT(expr)</tt> is defined as <tt>((void)0)</tt>. This
allows users to selectively disable <STRONG>BOOST_ASSERT</STRONG> without
affecting the definition of the standard <STRONG>assert</STRONG>.</P>
<P>When the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
is included, <tt>BOOST_ASSERT(expr)</tt> evaluates <b>expr</b> and, if the
result is false, evaluates the expression</P>
<P><tt>::boost::assertion_failed(#expr, <a href="current_function.html">BOOST_CURRENT_FUNCTION</a>,
__FILE__, __LINE__)</tt></P>
<P><STRONG>assertion_failed</STRONG> is declared in <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
as</P>
<pre>
namespace boost
{
void assertion_failed(char const * expr, char const * function, char const * file, long line);
}
</pre>
<p>but it is never defined. The user is expected to supply an appropriate
definition.</p>
<P>As is the case with <STRONG>&lt;cassert&gt;</STRONG>, <STRONG>&lt;boost/assert.hpp&gt;</STRONG>
can be included multiple times in a single translation unit. <STRONG>BOOST_ASSERT</STRONG>
will be redefined each time as specified above.</P>
<p><br>
<small>Copyright <20> 2002 by Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

View File

@ -1,109 +1,33 @@
#if defined(_MSC_VER) && !defined(__ICL)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
#pragma warning(disable: 4514) // unreferenced inline removed
#endif
//
// assert_test.cpp - a test for boost/assert.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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/detail/lightweight_test.hpp>
#define BOOST_DEBUG 1
#include <boost/assert.hpp>
void test_default()
{
int x = 1;
BOOST_ASSERT(1);
BOOST_ASSERT(x);
BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x);
}
#define BOOST_DISABLE_ASSERTS
#include <boost/assert.hpp>
void test_disabled()
{
int x = 1;
BOOST_ASSERT(1);
BOOST_ASSERT(x);
BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x);
BOOST_ASSERT(0);
BOOST_ASSERT(!x);
BOOST_ASSERT(x == 0);
void * p = 0;
BOOST_ASSERT(p);
// supress warnings
p = &x;
p = &p;
}
#undef BOOST_DISABLE_ASSERTS
#define BOOST_ENABLE_ASSERT_HANDLER
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <cstdio>
int handler_invoked = 0;
void boost::assertion_failed(char const * expr, char const * function, char const * file, long line)
bool boost_error(char const * expr, char const * func, char const * file, long line)
{
#if !defined(BOOST_NO_STDC_NAMESPACE)
using std::printf;
#endif
printf("Expression: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n", expr, function, file, line);
++handler_invoked;
std::printf("%s(%ld): Assertion '%s' failed in function '%s'\n", file, line, expr, func);
return true; // fail w/ standard assert()
}
struct X
{
static void f()
{
BOOST_ASSERT(0);
}
};
void test_handler()
{
int x = 1;
BOOST_ASSERT(1);
BOOST_ASSERT(x);
BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x);
BOOST_ASSERT(0);
BOOST_ASSERT(!x);
BOOST_ASSERT(x == 0);
void * p = 0;
BOOST_ASSERT(p);
X::f();
BOOST_ASSERT(handler_invoked == 5);
BOOST_TEST(handler_invoked == 5);
}
#undef BOOST_ENABLE_ASSERT_HANDLER
int main()
{
test_default();
test_disabled();
test_handler();
return boost::report_errors();
BOOST_ASSERT(0 == 1);
}

View File

@ -5,14 +5,15 @@
</head>
<body bgcolor="white" link="blue" text="black" vlink="purple" alink="red">
<h1><img src="../../boost.png" alt="C++ Boost" align="middle"
<h1><img src="../../c++boost.gif" alt="C++ Boost" align="middle"
width="277" height="86">Base-from-Member Idiom</h1>
<p>The class template <code>boost::base_from_member</code> provides
a workaround for a class that needs to initialize a base class with a
member. The class template is in <cite><a
href="../../boost/utility/base_from_member.hpp">boost/utility/base_from_member.hpp</a></cite>
which is included in <i><a href="../../boost/utility.hpp">boost/utility.hpp</a></i>.</p>
which is included in <i><a href="../../boost/utility.hpp">boost/utility.hpp</a></i>.
The class template is forward declared in <i><a href="../../boost/utility_fwd.hpp">boost/utility_fwd.hpp</a></i>.</p>
<p>There is test/example code in <cite><a
href="base_from_member_test.cpp">base_from_member_test.cpp</a></cite>.</p>
@ -63,12 +64,11 @@ public:
</pre></blockquote>
<p>This is undefined because C++'s initialization order mandates that
the base class is initialized before the member it uses. <a
href="http://www.moocat.org">R. Samuel Klatchko</a> developed a way
around this by using the initialization order in his favor. Base
classes are intialized in order of declaration, so moving the desired
member to another base class, that is initialized before the desired
base class, can ensure proper initialization.</p>
the base class is initialized before the member it uses. Ron Klatchko
developed a way around this by using the initialization order in his
favor. Base classes are intialized in order of declaration, so moving
the desired member to another base class, that is initialized before the
desired base class, can ensure proper initialization.</p>
<p>A custom base class can be made for this idiom:</p>
@ -108,13 +108,7 @@ public:
};
</pre></blockquote>
<p>Other projects can use similar custom base classes. The technique
is basic enough to make a template, with a sample template class in
this library. The main template parameter is the type of the enclosed
member. The template class has several (explicit) constructor member
templates, which implicitly type the constructor arguments and pass them
to the member. The template class uses implicit copy construction and
assignment, cancelling them if the enclosed member is non-copyable.</p>
<p>Other projects can use similar custom base classes. The technique is basic enough to make a template, with a sample template class in this library. The main template parameter is the type of the enclosed member. The template class has several (explicit) constructor member templates, which implicitly type the constructor arguments and pass them to the member. The template class uses implicit copy construction and assignment, cancelling them if the enclosed member is non-copyable.</p>
<p>Manually coding a base class may be better if the construction
and/or copying needs are too complex for the supplied template class,
@ -129,31 +123,21 @@ particular member type does not need to concern itself with the integer.</p>
<h2><a name="synopsis">Synopsis</a></h2>
<blockquote><pre>
#ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY
#define BOOST_BASE_FROM_MEMBER_MAX_ARITY 10
#endif
template &lt; typename MemberType, int UniqueID = 0 &gt;
class boost::base_from_member
{
protected:
MemberType member;
base_from_member();
explicit base_from_member();
template&lt; typename T1 &gt;
explicit base_from_member( T1 x1 );
template&lt; typename T1, typename T2 &gt;
base_from_member( T1 x1, T2 x2 );
//...
template&lt; typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8, typename T9,
typename T10 &gt;
base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7,
T8 x8, T9 x9, T10 x10 );
template&lt; typename T1, typename T2, typename T3 &gt;
explicit base_from_member( T1 x1, T2 x2, T3 x3 );
};
</pre></blockquote>
@ -168,20 +152,12 @@ for later base classes (or itself).</p>
<p>There is a default constructor and several constructor member
templates. These constructor templates can take as many arguments
(currently up to ten) as possible and pass them to a constructor of
(currently up to three) as possible and pass them to a constructor of
the data member. Since C++ does not allow any way to explicitly state
the template parameters of a templated constructor, make sure that
the arguments are already close as possible to the actual type used in
the data member's desired constructor.</p>
<p>The <var>BOOST_BASE_FROM_MEMBER_MAX_ARITY</var> macro constant specifies
the maximum argument length for the constructor templates. The constant
may be overridden if more (or less) argument configurations are needed. The
constant may be read for code that is expandable like the class template and
needs to maintain the same maximum size. (Example code would be a class that
uses this class template as a base class for a member with a flexible set of
constructors.)</p>
<h2><a name="usage">Usage</a></h2>
<p>With the starting example, the <code>fdoutbuf</code> sub-object needs
@ -337,9 +313,7 @@ with the exact pointer type used in <code>switcher</code>'s constructor.</p>
<dt><a href="../../people/ed_brey.htm">Ed Brey</a>
<dd>Suggested some interface changes.
<dt><a href="http://www.moocat.org">R. Samuel Klatchko</a> (<a
href="mailto:rsk@moocat.org">rsk@moocat.org</a>, <a
href="mailto:rsk@brightmail.com">rsk@brightmail.com</a>)
<dt>Ron Klatchko (<a href="mailto:ron@crl.com">ron@crl.com</a>)
<dd>Invented the idiom of how to use a class member for initializing
a base class.
@ -348,11 +322,6 @@ with the exact pointer type used in <code>switcher</code>'s constructor.</p>
<a href="http://www.informatik.uni-konstanz.de/~kuehl/c++/iostream/">IOStream
example classes</a>.
<dt>Jonathan Turkanis
<dd>Supplied an implementation of generating the constructor templates that
can be controlled and automated with macros. The implementation uses
the <a href="../preprocessor/index.html">Preprocessor library</a>.
<dt><a href="../../people/daryle_walker.html">Daryle Walker</a>
<dd>Started the library. Contributed the test file <cite><a
href="base_from_member_test.cpp">base_from_member_test.cpp</a></cite>.
@ -360,12 +329,13 @@ with the exact pointer type used in <code>switcher</code>'s constructor.</p>
<hr>
<p>Revised: 28 August 2004</p>
<p>Revised: 22 August 2001</p>
<p>Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and distribution
are subject to the Boost Software License, Version 1.0. (See accompanying
file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a copy at &lt;<a
href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>&gt;.)</p>
<p>Copyright &copy; boost.org 2001. Permission to copy, use, modify,
sell and distribute this document is granted provided this copyright
notice appears in all copies. This document is provided &quot;as
is&quot; without express or implied warranty, and with no claim as to
its suitability for any purpose.</p>
</body>
</html>

View File

@ -1,20 +1,22 @@
// Boost test program for base-from-member class templates -----------------//
// Copyright 2001, 2003 Daryle Walker. Use, modification, and distribution are
// subject to the Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
// (C) Copyright Daryle Walker 2001. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See <http://www.boost.org/libs/utility/> for the library's home page.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 14 Jun 2003 Adjusted code for Boost.Test changes (Daryle Walker)
// 29 Aug 2001 Initial Version (Daryle Walker)
#include <boost/test/minimal.hpp> // for BOOST_CHECK, main
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp> // for BOOST_TEST, main
#include <boost/config.hpp> // for BOOST_NO_MEMBER_TEMPLATES
#include <boost/cstdlib.hpp> // for boost::exit_success
#include <boost/noncopyable.hpp> // for boost::noncopyable
#include <boost/config.hpp> // for BOOST_NO_MEMBER_TEMPLATES
#include <boost/cstdlib.hpp> // for boost::exit_success
#include <boost/utility.hpp> // for boost::noncopyable
#include <boost/utility/base_from_member.hpp> // for boost::base_from_member
@ -175,11 +177,11 @@ object_registrar obj_reg;
int
test_main( int , char * [] )
{
BOOST_CHECK( obj_reg.db_.empty() );
BOOST_CHECK( obj_reg.defrauders_in_.empty() );
BOOST_CHECK( obj_reg.defrauders_out_.empty() );
BOOST_CHECK( obj_reg.overeager_.empty() );
BOOST_CHECK( obj_reg.overkilled_.empty() );
BOOST_TEST( obj_reg.db_.empty() );
BOOST_TEST( obj_reg.defrauders_in_.empty() );
BOOST_TEST( obj_reg.defrauders_out_.empty() );
BOOST_TEST( obj_reg.overeager_.empty() );
BOOST_TEST( obj_reg.overkilled_.empty() );
// Make a separate block to examine pre- and post-effects
{
@ -187,20 +189,20 @@ test_main( int , char * [] )
using std::endl;
bad_class bc;
BOOST_CHECK( obj_reg.db_.size() == 3 );
BOOST_CHECK( obj_reg.defrauders_in_.size() == 1 );
BOOST_TEST( obj_reg.db_.size() == 3 );
BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
good_class_1 gc1;
BOOST_CHECK( obj_reg.db_.size() == 6 );
BOOST_CHECK( obj_reg.defrauders_in_.size() == 1 );
BOOST_TEST( obj_reg.db_.size() == 6 );
BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
good_class_2 gc2;
BOOST_CHECK( obj_reg.db_.size() == 11 );
BOOST_CHECK( obj_reg.defrauders_in_.size() == 1 );
BOOST_TEST( obj_reg.db_.size() == 11 );
BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
BOOST_CHECK( obj_reg.defrauders_out_.empty() );
BOOST_CHECK( obj_reg.overeager_.empty() );
BOOST_CHECK( obj_reg.overkilled_.empty() );
BOOST_TEST( obj_reg.defrauders_out_.empty() );
BOOST_TEST( obj_reg.overeager_.empty() );
BOOST_TEST( obj_reg.overkilled_.empty() );
// Getting the addresses of the objects ensure
// that they're used, and not optimized away.
@ -209,11 +211,11 @@ test_main( int , char * [] )
cout << "Object 'gc2' is at " << &gc2 << '.' << endl;
}
BOOST_CHECK( obj_reg.db_.empty() );
BOOST_CHECK( obj_reg.defrauders_in_.size() == 1 );
BOOST_CHECK( obj_reg.defrauders_out_.size() == 1 );
BOOST_CHECK( obj_reg.overeager_.empty() );
BOOST_CHECK( obj_reg.overkilled_.empty() );
BOOST_TEST( obj_reg.db_.empty() );
BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
BOOST_TEST( obj_reg.defrauders_out_.size() == 1 );
BOOST_TEST( obj_reg.overeager_.empty() );
BOOST_TEST( obj_reg.overkilled_.empty() );
return boost::exit_success;
}

View File

@ -1,7 +1,8 @@
// (C) Copyright David Abrahams 2000.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright David Abrahams 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 <vector>
#include <string>
@ -13,8 +14,6 @@
#include <list>
#include <algorithm>
#include <boost/detail/binary_search.hpp>
#include <boost/detail/workaround.hpp>
#include <cstddef>
#if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
# define USE_SSTREAM
@ -28,16 +27,7 @@
namespace {
// In order to get ADL to find the comparison operators defined below, they have
struct mystring : std::string
{
typedef std::string base;
mystring(std::string const& x)
: base(x) {}
};
typedef std::vector<mystring> string_vector;
typedef std::vector<std::string> string_vector;
const std::size_t sequence_length = 1000;
@ -84,21 +74,20 @@ struct cmp
}
};
inline bool operator<(const mystring& x, const unsigned y)
inline bool operator<(const std::string& x, const unsigned y)
{
return to_int(x) < y;
}
inline bool operator<(const unsigned y, const mystring& x)
inline bool operator<(const unsigned y, const std::string& x)
{
return y < to_int(x);
}
template <class T>
void sort_by_value(T& x);
template <class T> void sort_by_value(T&);
template <class T>
void sort_by_value_(T& v, long)
template <>
void sort_by_value(std::vector<std::string>& v)
{
std::sort(v.begin(), v.end(), cmp());
}
@ -114,26 +103,28 @@ void random_sorted_sequence(T& seq)
sort_by_value(seq);
}
template <class T, class A>
void sort_by_value_(std::list<T,A>& l, int)
{
# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) && !defined(__SGI_STL_PORT)
# if defined(BOOST_MSVC) && !defined(__SGI_STL_PORT)
// VC6's standard lib doesn't have a template member function for list::sort()
std::vector<T> seq;
seq.reserve(sequence_length);
std::copy(l.begin(), l.end(), std::back_inserter(seq));
sort_by_value(seq);
std::copy(seq.begin(), seq.end(), l.begin());
# else
l.sort(cmp());
# endif
}
template <class T>
void sort_by_value(T& x)
template <>
void random_sorted_sequence(std::list<std::string>& result)
{
(sort_by_value_)(x, 1);
std::vector<std::string> seq;
seq.reserve(sequence_length);
for (std::size_t i = 0; i < sequence_length; ++i)
{
push_back_random_number_string(seq);
}
sort_by_value(seq);
result.resize(seq.size());
std::copy(seq.begin(), seq.end(), result.begin());
}
#else
template <>
inline void sort_by_value(std::list<std::string>& l)
{
l.sort(cmp());
}
# endif
// A way to select the comparisons with/without a Compare parameter for testing.
template <class Compare> struct searches
@ -242,13 +233,13 @@ void test_loop(Sequence& x, Compare cmp, unsigned long test_count)
int main()
{
string_vector x;
std::vector<std::string> x;
std::cout << "=== testing random-access iterators with <: ===\n";
test_loop(x, no_compare(), 25);
std::cout << "=== testing random-access iterators with compare: ===\n";
test_loop(x, cmp(), 25);
std::list<mystring> y;
std::list<std::string> y;
std::cout << "=== testing bidirectional iterators with <: ===\n";
test_loop(y, no_compare(), 25);
std::cout << "=== testing bidirectional iterators with compare: ===\n";

View File

@ -5,14 +5,14 @@
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">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<title>Call Traits</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
vlink="#800080">
<h1><img src="../../boost.png" width="276" height="86">Header
<h1><img src="../../c++boost.gif" width="276" height="86">Header
&lt;<a href="../../boost/detail/call_traits.hpp">boost/call_traits.hpp</a>&gt;</h1>
<p>All of the contents of &lt;boost/call_traits.hpp&gt; are
@ -592,8 +592,7 @@ would prevent template argument deduction from functioning.</p>
<p>The call_traits template will &quot;optimize&quot; 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="../type_traits/examples/fill_example.cpp">fill_example.cpp</a>),
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
@ -606,7 +605,7 @@ template &lt;bool opt&gt;
struct filler
{
template &lt;typename I, typename T&gt;
static void do_fill(I first, I last, typename boost::call_traits&lt;T&gt;::param_type val)
static void do_fill(I first, I last, typename boost::call_traits&lt;T&gt;::param_type val);
{
while(first != last)
{
@ -749,11 +748,10 @@ 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@johnmaddock.co.uk">John
<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.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
discussion list at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
<p>.</p>
@ -762,4 +760,3 @@ href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.
<p>&nbsp;</p>
</body>
</html>

View File

@ -1,10 +1,9 @@
// boost::compressed_pair test program
// boost::compressed_pair test program
// (C) Copyright John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
// (C) Copyright John Maddock 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.
// standalone test program for <boost/call_traits.hpp>
// 18 Mar 2002:
@ -12,14 +11,14 @@
// 03 Oct 2000:
// Enabled extra tests for VC6.
#include <cassert>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <typeinfo>
#include <boost/call_traits.hpp>
#include <libs/type_traits/test/test.hpp>
#include <libs/type_traits/test/check_type.hpp>
#include <boost/type_traits/type_traits_test.hpp>
// a way prevent warnings for unused variables
template<class T> inline void unused_variable(const T&) {}
@ -121,9 +120,9 @@ void call_traits_checker<T>::operator()(param_type p)
T t(p);
contained<T> c(t);
cout << "checking contained<" << typeid(T).name() << ">..." << endl;
BOOST_CHECK(t == c.value());
BOOST_CHECK(t == c.get());
BOOST_CHECK(t == c.const_get());
assert(t == c.value());
assert(t == c.get());
assert(t == c.const_get());
#ifndef __ICL
//cout << "typeof contained<" << typeid(T).name() << ">::v_ is: " << typeid(&contained<T>::v_).name() << endl;
cout << "typeof contained<" << typeid(T).name() << ">::value() is: " << typeid(&contained<T>::value).name() << endl;
@ -145,11 +144,11 @@ struct call_traits_checker<T[N]>
cout << "checking contained<" << typeid(T[N]).name() << ">..." << endl;
unsigned int i = 0;
for(i = 0; i < N; ++i)
BOOST_CHECK(t[i] == c.value()[i]);
assert(t[i] == c.value()[i]);
for(i = 0; i < N; ++i)
BOOST_CHECK(t[i] == c.get()[i]);
assert(t[i] == c.get()[i]);
for(i = 0; i < N; ++i)
BOOST_CHECK(t[i] == c.const_get()[i]);
assert(t[i] == c.const_get()[i]);
cout << "typeof contained<" << typeid(T[N]).name() << ">::v_ is: " << typeid(&contained<T[N]>::v_).name() << endl;
cout << "typeof contained<" << typeid(T[N]).name() << ">::value is: " << typeid(&contained<T[N]>::value).name() << endl;
@ -167,7 +166,7 @@ template <class W, class U>
void check_wrap(const W& w, const U& u)
{
cout << "checking " << typeid(W).name() << "..." << endl;
BOOST_CHECK(w.value() == u);
assert(w.value() == u);
}
//
@ -178,8 +177,8 @@ template <class T, class U, class V>
void check_make_pair(T c, U u, V v)
{
cout << "checking std::pair<" << typeid(c.first).name() << ", " << typeid(c.second).name() << ">..." << endl;
BOOST_CHECK(c.first == u);
BOOST_CHECK(c.second == v);
assert(c.first == u);
assert(c.second == v);
cout << endl;
}
@ -231,67 +230,73 @@ int main(int argc, char *argv[ ])
typedef int& r_type;
typedef const r_type cr_type;
BOOST_CHECK_TYPE(comparible_UDT, boost::call_traits<comparible_UDT>::value_type);
BOOST_CHECK_TYPE(comparible_UDT&, boost::call_traits<comparible_UDT>::reference);
BOOST_CHECK_TYPE(const comparible_UDT&, boost::call_traits<comparible_UDT>::const_reference);
BOOST_CHECK_TYPE(const comparible_UDT&, boost::call_traits<comparible_UDT>::param_type);
BOOST_CHECK_TYPE(int, boost::call_traits<int>::value_type);
BOOST_CHECK_TYPE(int&, boost::call_traits<int>::reference);
BOOST_CHECK_TYPE(const int&, boost::call_traits<int>::const_reference);
BOOST_CHECK_TYPE(const int, boost::call_traits<int>::param_type);
BOOST_CHECK_TYPE(int*, boost::call_traits<int*>::value_type);
BOOST_CHECK_TYPE(int*&, boost::call_traits<int*>::reference);
BOOST_CHECK_TYPE(int*const&, boost::call_traits<int*>::const_reference);
BOOST_CHECK_TYPE(int*const, boost::call_traits<int*>::param_type);
type_test(comparible_UDT, boost::call_traits<comparible_UDT>::value_type)
type_test(comparible_UDT&, boost::call_traits<comparible_UDT>::reference)
type_test(const comparible_UDT&, boost::call_traits<comparible_UDT>::const_reference)
type_test(const comparible_UDT&, boost::call_traits<comparible_UDT>::param_type)
type_test(int, boost::call_traits<int>::value_type)
type_test(int&, boost::call_traits<int>::reference)
type_test(const int&, boost::call_traits<int>::const_reference)
type_test(const int, boost::call_traits<int>::param_type)
type_test(int*, boost::call_traits<int*>::value_type)
type_test(int*&, boost::call_traits<int*>::reference)
type_test(int*const&, boost::call_traits<int*>::const_reference)
type_test(int*const, boost::call_traits<int*>::param_type)
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES)
BOOST_CHECK_TYPE(int&, boost::call_traits<int&>::value_type);
BOOST_CHECK_TYPE(int&, boost::call_traits<int&>::reference);
BOOST_CHECK_TYPE(const int&, boost::call_traits<int&>::const_reference);
BOOST_CHECK_TYPE(int&, boost::call_traits<int&>::param_type);
type_test(int&, boost::call_traits<int&>::value_type)
type_test(int&, boost::call_traits<int&>::reference)
type_test(const int&, boost::call_traits<int&>::const_reference)
type_test(int&, boost::call_traits<int&>::param_type)
#if !(defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1)))
BOOST_CHECK_TYPE(int&, boost::call_traits<cr_type>::value_type);
BOOST_CHECK_TYPE(int&, boost::call_traits<cr_type>::reference);
BOOST_CHECK_TYPE(const int&, boost::call_traits<cr_type>::const_reference);
BOOST_CHECK_TYPE(int&, boost::call_traits<cr_type>::param_type);
type_test(int&, boost::call_traits<cr_type>::value_type)
type_test(int&, boost::call_traits<cr_type>::reference)
type_test(const int&, boost::call_traits<cr_type>::const_reference)
type_test(int&, boost::call_traits<cr_type>::param_type)
#else
std::cout << "Your compiler cannot instantiate call_traits<int&const>, skipping four tests (4 errors)" << std::endl;
failures += 4;
test_count += 4;
#endif
BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::value_type);
BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::reference);
BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::const_reference);
BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::param_type);
type_test(const int&, boost::call_traits<const int&>::value_type)
type_test(const int&, boost::call_traits<const int&>::reference)
type_test(const int&, boost::call_traits<const int&>::const_reference)
type_test(const int&, boost::call_traits<const int&>::param_type)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
BOOST_CHECK_TYPE(const int*, boost::call_traits<int[3]>::value_type);
BOOST_CHECK_TYPE(int(&)[3], boost::call_traits<int[3]>::reference);
BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits<int[3]>::const_reference);
BOOST_CHECK_TYPE(const int*const, boost::call_traits<int[3]>::param_type);
BOOST_CHECK_TYPE(const int*, boost::call_traits<const int[3]>::value_type);
BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits<const int[3]>::reference);
BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits<const int[3]>::const_reference);
BOOST_CHECK_TYPE(const int*const, boost::call_traits<const int[3]>::param_type);
type_test(const int*, boost::call_traits<int[3]>::value_type)
type_test(int(&)[3], boost::call_traits<int[3]>::reference)
type_test(const int(&)[3], boost::call_traits<int[3]>::const_reference)
type_test(const int*const, boost::call_traits<int[3]>::param_type)
type_test(const int*, boost::call_traits<const int[3]>::value_type)
type_test(const int(&)[3], boost::call_traits<const int[3]>::reference)
type_test(const int(&)[3], boost::call_traits<const int[3]>::const_reference)
type_test(const int*const, boost::call_traits<const int[3]>::param_type)
// test with abstract base class:
BOOST_CHECK_TYPE(test_abc1, boost::call_traits<test_abc1>::value_type);
BOOST_CHECK_TYPE(test_abc1&, boost::call_traits<test_abc1>::reference);
BOOST_CHECK_TYPE(const test_abc1&, boost::call_traits<test_abc1>::const_reference);
BOOST_CHECK_TYPE(const test_abc1&, boost::call_traits<test_abc1>::param_type);
type_test(test_abc1, boost::call_traits<test_abc1>::value_type)
type_test(test_abc1&, boost::call_traits<test_abc1>::reference)
type_test(const test_abc1&, boost::call_traits<test_abc1>::const_reference)
type_test(const test_abc1&, boost::call_traits<test_abc1>::param_type)
#else
std::cout << "You're compiler does not support partial template specialiation, skipping 8 tests (8 errors)" << std::endl;
failures += 12;
test_count += 12;
#endif
#else
std::cout << "You're compiler does not support partial template specialiation, skipping 20 tests (20 errors)" << std::endl;
failures += 24;
test_count += 24;
#endif
// test with an incomplete type:
BOOST_CHECK_TYPE(incomplete_type, boost::call_traits<incomplete_type>::value_type);
BOOST_CHECK_TYPE(incomplete_type&, boost::call_traits<incomplete_type>::reference);
BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits<incomplete_type>::const_reference);
BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits<incomplete_type>::param_type);
type_test(incomplete_type, boost::call_traits<incomplete_type>::value_type)
type_test(incomplete_type&, boost::call_traits<incomplete_type>::reference)
type_test(const incomplete_type&, boost::call_traits<incomplete_type>::const_reference)
type_test(const incomplete_type&, boost::call_traits<incomplete_type>::param_type)
return 0;
return check_result(argc, argv);
}
//
// define call_traits tests to check that the assertions in the docs do actually work
// this is an compile-time only set of tests:
// this is an instantiate only set of tests:
//
template <typename T, bool isarray = false>
struct call_traits_test
@ -403,3 +408,23 @@ template struct call_traits_test<int[2], true>;
#endif
#endif
#ifdef BOOST_MSVC
unsigned int expected_failures = 14;
#elif defined(__SUNPRO_CC)
#if(__SUNPRO_CC <= 0x520)
unsigned int expected_failures = 18;
#elif(__SUNPRO_CC < 0x530)
unsigned int expected_failures = 17;
#else
unsigned int expected_failures = 6;
#endif
#elif defined(__BORLANDC__)
unsigned int expected_failures = 2;
#elif (defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1)))
unsigned int expected_failures = 4;
#elif defined(__HP_aCC)
unsigned int expected_failures = 24;
#else
unsigned int expected_failures = 0;
#endif

View File

@ -1,122 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Boost: checked_delete.hpp documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
<table border="0" width="100%">
<tr>
<td width="277"><A href="../../index.htm"> <img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86" border="0"></A>
</td>
<td align="center">
<h1>checked_delete.hpp</h1>
</td>
</tr>
<tr>
<td colspan="2" height="64">&nbsp;</td>
</tr>
</table>
<p>
The header <STRONG>&lt;boost/checked_delete.hpp&gt;</STRONG> defines two
function templates, <STRONG>checked_delete</STRONG> and <STRONG>checked_array_delete</STRONG>,
and two class templates, <STRONG>checked_deleter</STRONG> and <STRONG>checked_array_deleter</STRONG>.
</p>
<P>The C++ Standard allows, in 5.3.5/5, pointers to incomplete class types to be
deleted with a <EM>delete-expression</EM>. When the class has a non-trivial
destructor, or a class-specific operator delete, the behavior is undefined.
Some compilers issue a warning when an incomplete type is deleted, but
unfortunately, not all do, and programmers sometimes ignore or disable
warnings.</P>
<P>A particularly troublesome case is when a smart pointer's destructor, such as <STRONG>
boost::scoped_ptr&lt;T&gt;::~scoped_ptr</STRONG>, is instantiated with an
incomplete type. This can often lead to silent, hard to track failures.</P>
<P>The supplied function and class templates can be used to prevent these problems,
as they require a complete type, and cause a compilation error otherwise.</P>
<h3><a name="Synopsis">Synopsis</a></h3>
<pre>
namespace boost
{
template&lt;class T&gt; void checked_delete(T * p);
template&lt;class T&gt; void checked_array_delete(T * p);
template&lt;class T&gt; struct checked_deleter;
template&lt;class T&gt; struct checked_array_deleter;
}
</pre>
<h3>checked_delete</h3>
<h4><a name="checked_delete">template&lt;class T&gt; void checked_delete(T * p);</a></h4>
<blockquote>
<p>
<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete p</tt>
must be well-formed.
</p>
<p>
<b>Effects:</b> <tt>delete p;</tt>
</p>
</blockquote>
<h3>checked_array_delete</h3>
<h4><a name="checked_array_delete">template&lt;class T&gt; void checked_array_delete(T
* p);</a></h4>
<blockquote>
<p>
<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete [] p</tt>
must be well-formed.
</p>
<p>
<b>Effects:</b> <tt>delete [] p;</tt>
</p>
</blockquote>
<h3>checked_deleter</h3>
<pre>
template&lt;class T&gt; struct checked_deleter
{
typedef void result_type;
typedef T * argument_type;
void operator()(T * p) const;
};
</pre>
<h4>void checked_deleter&lt;T&gt;::operator()(T * p) const;</h4>
<blockquote>
<p>
<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete p</tt>
must be well-formed.
</p>
<p>
<b>Effects:</b> <tt>delete p;</tt>
</p>
</blockquote>
<h3>checked_array_deleter</h3>
<pre>
template&lt;class T&gt; struct checked_array_deleter
{
typedef void result_type;
typedef T * argument_type;
void operator()(T * p) const;
};
</pre>
<h4>void checked_array_deleter&lt;T&gt;::operator()(T * p) const;</h4>
<blockquote>
<p>
<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete [] p</tt>
must be well-formed.
</p>
<p>
<b>Effects:</b> <tt>delete [] p;</tt>
</p>
</blockquote>
<h3><a name="Acknowledgements">Acknowledgements</a></h3>
<p>
The function templates <STRONG>checked_delete</STRONG> and <STRONG>checked_array_delete</STRONG>
were originally part of <STRONG>&lt;boost/utility.hpp&gt;</STRONG>, and the
documentation acknowledged Beman Dawes, Dave Abrahams, Vladimir Prus, Rainer
Deyke, John Maddock, and others as contributors.
</p>
<p>
<br>
<small>Copyright <20> 2002 by Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

View File

@ -1,15 +1,17 @@
// Boost checked_delete test program ---------------------------------------//
// Copyright Beman Dawes 2001. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright Beman Dawes 2001. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org/libs/utility for documentation.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 21 May 01 Initial version (Beman Dawes)
#include <boost/checked_delete.hpp> // for checked_delete
#include <boost/utility.hpp> // for checked_delete
// This program demonstrates compiler errors when trying to delete an
// incomplete type.
@ -21,8 +23,9 @@ namespace
int main()
{
Incomplete * p = 0;
Incomplete * p;
boost::checked_delete(p); // should cause compile time error
boost::checked_array_delete(p); // should cause compile time error
Incomplete ** pa;
boost::checked_array_delete(pa); // should cause compile time error
return 0;
} // main

View File

@ -1,19 +1,30 @@
<html>
<head>
<title>Header </title>
<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">
<boostcompressed_pair.hpp>
</head>
<body bgcolor="#ffffff" text="#000000" link="#0000ff" vlink="#800080">
<h2><img src="../../boost.png" width="276" height="86">Header &lt;<a href="../../boost/detail/compressed_pair.hpp">boost/compressed_pair.hpp</a>&gt;</h2>
<p>All of the contents of &lt;boost/compressed_pair.hpp&gt; are defined inside
namespace boost.</p>
<p>The class compressed pair is very similar to std::pair, but if either of the
template arguments are empty classes, then the "empty base-class optimisation"
is applied to compress the size of the pair.</p>
<pre>template &lt;class T1, class T2&gt;
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta name="Template"
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
<title>Header </title>
<boost/compressed_pair.hpp>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
vlink="#800080">
<h2><img src="../../c++boost.gif" width="276" height="86">Header
&lt;<a href="../../boost/detail/compressed_pair.hpp">boost/compressed_pair.hpp</a>&gt;</h2>
<p>All of the contents of &lt;boost/compressed_pair.hpp&gt; are
defined inside namespace boost.</p>
<p>The class compressed pair is very similar to std::pair, but if
either of the template arguments are empty classes, then the
&quot;empty base-class optimisation&quot; is applied to compress
the size of the pair.</p>
<pre>template &lt;class T1, class T2&gt;
class compressed_pair
{
public:
@ -41,35 +52,47 @@ public:
void swap(compressed_pair&amp; y);
};</pre>
<p>The two members of the pair can be accessed using the member functions first()
and second(). Note that not all member functions can be instantiated for all
template parameter types. In particular compressed_pair can be instantiated for
reference and array types, however in these cases the range of constructors
that can be used are limited. If types T1 and T2 are the same type, then there
is only one version of the single-argument constructor, and this constructor
initialises both values in the pair to the passed value.</p>
<P>Note that if either member is a POD type, then that member is not
zero-initialized by the compressed_pair default constructor: it's up to you to
supply an initial value for these types if you want them to have a default
value.</P>
<p>Note that compressed_pair can not be instantiated if either of the template
arguments is a union type, unless there is compiler support for
boost::is_union, or if boost::is_union is specialised for the union type.</p>
<p>Finally, a word of caution for Visual C++ 6 users: if either argument is an
empty type, then assigning to that member will produce memory corruption,
unless the empty type has a "do nothing" assignment operator defined. This is
due to a bug in the way VC6 generates implicit assignment operators.</p>
<hr>
<p>Revised 08 May 2001</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@johnmaddock.co.uk">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.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
<p>&nbsp;</p>
</body>
<p>The two members of the pair can be accessed using the member
functions first() and second(). Note that not all member
functions can be instantiated for all template parameter types.
In particular compressed_pair can be instantiated for reference
and array types, however in these cases the range of constructors
that can be used are limited. If types T1 and T2 are the same
type, then there is only one version of the single-argument
constructor, and this constructor initialises both values in the
pair to the passed value.</p>
<p>Note that compressed_pair can not be instantiated if either of
the template arguments is a union type, unless there is compiler
support for boost::is_union, or if boost::is_union is specialised
for the union type.</p>
<p>Finally, a word of caution for Visual C++ 6 users: if either
argument is an empty type, then assigning to that member will
produce memory corruption, unless the empty type has a &quot;do
nothing&quot; assignment operator defined. This is due to a bug
in the way VC6 generates implicit assignment operators.</p>
<hr>
<p>Revised 08 May 2001</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
&quot;as is&quot; 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.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
<p>&nbsp;</p>
</body>
</html>

View File

@ -1,9 +1,9 @@
// boost::compressed_pair test program
// boost::compressed_pair test program
// (C) Copyright John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
// (C) Copyright John Maddock 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.
// standalone test program for <boost/compressed_pair.hpp>
// Revised 03 Oct 2000:
@ -14,23 +14,29 @@
#include <cassert>
#include <boost/compressed_pair.hpp>
#include <boost/type_traits/type_traits_test.hpp>
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
using namespace boost;
struct empty_UDT
{
~empty_UDT(){};
empty_UDT& operator=(const empty_UDT&){ return *this; }
bool operator==(const empty_UDT&)const
{ return true; }
};
struct empty_POD_UDT
{
empty_POD_UDT& operator=(const empty_POD_UDT&){ return *this; }
bool operator==(const empty_POD_UDT&)const
{ return true; }
};
namespace boost {
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
template <> struct is_empty<empty_UDT>
{ static const bool value = true; };
template <> struct is_empty<empty_POD_UDT>
{ static const bool value = true; };
template <> struct is_POD<empty_POD_UDT>
{ static const bool value = true; };
#else
template <> struct is_empty<empty_UDT>
{ enum{ value = true }; };
template <> struct is_empty<empty_POD_UDT>
{ enum{ value = true }; };
template <> struct is_POD<empty_POD_UDT>
{ enum{ value = true }; };
#endif
}
struct non_empty1
{
@ -79,47 +85,47 @@ void compressed_pair_tester<T1, T2>::test(first_param_type p1, second_param_type
// first param construct:
boost::compressed_pair<T1,T2> cp2(p1);
cp2.second() = p2;
BOOST_CHECK(cp2.first() == p1);
BOOST_CHECK(cp2.second() == p2);
BOOST_TEST(cp2.first() == p1);
BOOST_TEST(cp2.second() == p2);
// second param construct:
boost::compressed_pair<T1,T2> cp3(p2);
cp3.first() = p1;
BOOST_CHECK(cp3.second() == p2);
BOOST_CHECK(cp3.first() == p1);
BOOST_TEST(cp3.second() == p2);
BOOST_TEST(cp3.first() == p1);
// both param construct:
boost::compressed_pair<T1,T2> cp4(p1, p2);
BOOST_CHECK(cp4.first() == p1);
BOOST_CHECK(cp4.second() == p2);
BOOST_TEST(cp4.first() == p1);
BOOST_TEST(cp4.second() == p2);
boost::compressed_pair<T1,T2> cp5(p3, p4);
BOOST_CHECK(cp5.first() == p3);
BOOST_CHECK(cp5.second() == p4);
BOOST_TEST(cp5.first() == p3);
BOOST_TEST(cp5.second() == p4);
// check const members:
const boost::compressed_pair<T1,T2>& cpr1 = cp4;
BOOST_CHECK(cpr1.first() == p1);
BOOST_CHECK(cpr1.second() == p2);
BOOST_TEST(cpr1.first() == p1);
BOOST_TEST(cpr1.second() == p2);
// copy construct:
boost::compressed_pair<T1,T2> cp6(cp4);
BOOST_CHECK(cp6.first() == p1);
BOOST_CHECK(cp6.second() == p2);
BOOST_TEST(cp6.first() == p1);
BOOST_TEST(cp6.second() == p2);
// assignment:
cp1 = cp4;
BOOST_CHECK(cp1.first() == p1);
BOOST_CHECK(cp1.second() == p2);
BOOST_TEST(cp1.first() == p1);
BOOST_TEST(cp1.second() == p2);
cp1 = cp5;
BOOST_CHECK(cp1.first() == p3);
BOOST_CHECK(cp1.second() == p4);
BOOST_TEST(cp1.first() == p3);
BOOST_TEST(cp1.second() == p4);
// swap:
cp4.swap(cp5);
BOOST_CHECK(cp4.first() == p3);
BOOST_CHECK(cp4.second() == p4);
BOOST_CHECK(cp5.first() == p1);
BOOST_CHECK(cp5.second() == p2);
BOOST_TEST(cp4.first() == p3);
BOOST_TEST(cp4.second() == p4);
BOOST_TEST(cp5.first() == p1);
BOOST_TEST(cp5.second() == p2);
swap(cp4,cp5);
BOOST_CHECK(cp4.first() == p1);
BOOST_CHECK(cp4.second() == p2);
BOOST_CHECK(cp5.first() == p3);
BOOST_CHECK(cp5.second() == p4);
BOOST_TEST(cp4.first() == p1);
BOOST_TEST(cp4.second() == p2);
BOOST_TEST(cp5.first() == p3);
BOOST_TEST(cp5.second() == p4);
}
//
@ -148,20 +154,20 @@ void compressed_pair_reference_tester<T1, T2>::test(first_param_type p1, second_
#endif
// both param construct:
boost::compressed_pair<T1,T2> cp4(p1, p2);
BOOST_CHECK(cp4.first() == p1);
BOOST_CHECK(cp4.second() == p2);
BOOST_TEST(cp4.first() == p1);
BOOST_TEST(cp4.second() == p2);
boost::compressed_pair<T1,T2> cp5(p3, p4);
BOOST_CHECK(cp5.first() == p3);
BOOST_CHECK(cp5.second() == p4);
BOOST_TEST(cp5.first() == p3);
BOOST_TEST(cp5.second() == p4);
// check const members:
const boost::compressed_pair<T1,T2>& cpr1 = cp4;
BOOST_CHECK(cpr1.first() == p1);
BOOST_CHECK(cpr1.second() == p2);
BOOST_TEST(cpr1.first() == p1);
BOOST_TEST(cpr1.second() == p2);
// copy construct:
boost::compressed_pair<T1,T2> cp6(cp4);
BOOST_CHECK(cp6.first() == p1);
BOOST_CHECK(cp6.second() == p2);
BOOST_TEST(cp6.first() == p1);
BOOST_TEST(cp6.second() == p2);
// assignment:
// VC6 bug:
// When second() is an empty class, VC6 performs the
@ -174,8 +180,8 @@ void compressed_pair_reference_tester<T1, T2>::test(first_param_type p1, second_
// settings - some generate the problem others do not.
cp4.first() = p3;
cp4.second() = p4;
BOOST_CHECK(cp4.first() == p3);
BOOST_CHECK(cp4.second() == p4);
BOOST_TEST(cp4.first() == p3);
BOOST_TEST(cp4.second() == p4);
}
//
// supplimentary tests for case where first arg only is a reference type:
@ -199,8 +205,8 @@ void compressed_pair_reference1_tester<T1, T2>::test(first_param_type p1, second
// first param construct:
boost::compressed_pair<T1,T2> cp2(p1);
cp2.second() = p2;
BOOST_CHECK(cp2.first() == p1);
BOOST_CHECK(cp2.second() == p2);
BOOST_TEST(cp2.first() == p1);
BOOST_TEST(cp2.second() == p2);
#endif
}
//
@ -225,8 +231,8 @@ void compressed_pair_reference2_tester<T1, T2>::test(first_param_type p1, second
// second param construct:
boost::compressed_pair<T1,T2> cp3(p2);
cp3.first() = p1;
BOOST_CHECK(cp3.second() == p2);
BOOST_CHECK(cp3.first() == p1);
BOOST_TEST(cp3.second() == p2);
BOOST_TEST(cp3.first() == p1);
#endif
}
@ -253,14 +259,14 @@ void compressed_pair_array1_tester<T1, T2>::test(first_param_type p1, second_par
// second param construct:
boost::compressed_pair<T1,T2> cp3(p2);
cp3.first()[0] = p1[0];
BOOST_CHECK(cp3.second() == p2);
BOOST_CHECK(cp3.first()[0] == p1[0]);
BOOST_TEST(cp3.second() == p2);
BOOST_TEST(cp3.first()[0] == p1[0]);
// check const members:
const boost::compressed_pair<T1,T2>& cpr1 = cp3;
BOOST_CHECK(cpr1.first()[0] == p1[0]);
BOOST_CHECK(cpr1.second() == p2);
BOOST_TEST(cpr1.first()[0] == p1[0]);
BOOST_TEST(cpr1.second() == p2);
BOOST_CHECK(sizeof(T1) == sizeof(cp1.first()));
BOOST_TEST(sizeof(T1) == sizeof(cp1.first()));
}
template <class T1, class T2>
@ -283,14 +289,14 @@ void compressed_pair_array2_tester<T1, T2>::test(first_param_type p1, second_par
// first param construct:
boost::compressed_pair<T1,T2> cp2(p1);
cp2.second()[0] = p2[0];
BOOST_CHECK(cp2.first() == p1);
BOOST_CHECK(cp2.second()[0] == p2[0]);
BOOST_TEST(cp2.first() == p1);
BOOST_TEST(cp2.second()[0] == p2[0]);
// check const members:
const boost::compressed_pair<T1,T2>& cpr1 = cp2;
BOOST_CHECK(cpr1.first() == p1);
BOOST_CHECK(cpr1.second()[0] == p2[0]);
BOOST_TEST(cpr1.first() == p1);
BOOST_TEST(cpr1.second()[0] == p2[0]);
BOOST_CHECK(sizeof(T2) == sizeof(cp1.second()));
BOOST_TEST(sizeof(T2) == sizeof(cp1.second()));
}
template <class T1, class T2>
@ -312,18 +318,18 @@ void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_para
boost::compressed_pair<T1,T2> cp1;
cp1.first()[0] = p1[0];
cp1.second()[0] = p2[0];
BOOST_CHECK(cp1.first()[0] == p1[0]);
BOOST_CHECK(cp1.second()[0] == p2[0]);
BOOST_TEST(cp1.first()[0] == p1[0]);
BOOST_TEST(cp1.second()[0] == p2[0]);
// check const members:
const boost::compressed_pair<T1,T2>& cpr1 = cp1;
BOOST_CHECK(cpr1.first()[0] == p1[0]);
BOOST_CHECK(cpr1.second()[0] == p2[0]);
BOOST_TEST(cpr1.first()[0] == p1[0]);
BOOST_TEST(cpr1.second()[0] == p2[0]);
BOOST_CHECK(sizeof(T1) == sizeof(cp1.first()));
BOOST_CHECK(sizeof(T2) == sizeof(cp1.second()));
BOOST_TEST(sizeof(T1) == sizeof(cp1.first()));
BOOST_TEST(sizeof(T2) == sizeof(cp1.second()));
}
int test_main(int, char *[])
int test_main(int, char **)
{
// declare some variables to pass to the tester:
non_empty1 ne1(2);

325
counting_iterator.htm Normal file
View File

@ -0,0 +1,325 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Counting Iterator Adaptor Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
align="center" width="277" height="86">
<h1>Counting Iterator Adaptor</h1>
Defined in header
<a href="../../boost/counting_iterator.hpp">boost/counting_iterator.hpp</a>
<p>
How would you fill up a vector with the numbers zero
through one hundred using <a
href="http://www.sgi.com/tech/stl/copy.html"><tt>std::copy()</tt></a>? The
only iterator operation missing from builtin integer types is an
<tt>operator*()</tt> that returns the current
value of the integer. The counting iterator adaptor adds this crucial piece of
functionality to whatever type it wraps. One can use the
counting iterator adaptor not only with integer types, but with any
type that is <tt>Incrementable</tt> (see type requirements <a href="#requirements">below</a>). The
following <b>pseudo-code</b> shows the general idea of how the
counting iterator is implemented.
</p>
<pre>
// inside a hypothetical counting_iterator class...
typedef Incrementable value_type;
value_type counting_iterator::operator*() const {
return this->base; // no dereference!
}
</pre>
All of the other operators of the counting iterator behave in the same
fashion as the <tt>Incrementable</tt> base type.
<h2>Synopsis</h2>
<pre>
namespace boost {
template &lt;class Incrementable&gt;
struct <a href="#counting_iterator_traits">counting_iterator_traits</a>;
template &lt;class Incrementable&gt;
struct <a href="#counting_iterator_generator">counting_iterator_generator</a>;
template &lt;class Incrementable&gt;
typename counting_iterator_generator&lt;Incrementable&gt;::type
<a href="#make_counting_iterator">make_counting_iterator</a>(Incrementable x);
}
</pre>
<hr>
<h2><a name="counting_iterator_generator">The Counting Iterator Type
Generator</a></h2>
The class template <tt>counting_iterator_generator&lt;Incrementable&gt;</tt> is a <a href="../../more/generic_programming.html#type_generator">type generator</a> for counting iterators.
<pre>
template &lt;class Incrementable&gt;
class counting_iterator_generator
{
public:
typedef <a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt;...&gt; type;
};
</pre>
<h3>Example</h3>
In this example we use the counting iterator generator to create a
counting iterator, and count from zero to four.
<pre>
#include &lt;boost/config.hpp&gt;
#include &lt;iostream&gt;
#include &lt;boost/counting_iterator.hpp&gt;
int main(int, char*[])
{
// Example of using counting_iterator_generator
std::cout &lt;&lt; "counting from 0 to 4:" &lt;&lt; std::endl;
boost::counting_iterator_generator&lt;int&gt;::type first(0), last(4);
std::copy(first, last, std::ostream_iterator&lt;int&gt;(std::cout, " "));
std::cout &lt;&lt; std::endl;
// to be continued...
</pre>
The output from this part is:
<pre>
counting from 0 to 4:
0 1 2 3
</pre>
<h3>Template Parameters</h3>
<Table border>
<TR>
<TH>Parameter</TH><TH>Description</TH>
</TR>
<TR>
<TD><tt>Incrementable</tt></TD>
<TD>The type being wrapped by the adaptor.</TD>
</TR>
</Table>
<h3>Model of</h3>
If the <tt>Incrementable</tt> type has all of the functionality of a
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access Iterator</a> except the <tt>operator*()</tt>, then the counting
iterator will be a model of <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access Iterator</a>. If the <tt>Incrementable</tt> type has less
functionality, then the counting iterator will have correspondingly
less functionality.
<h3><a name="requirements">Type Requirements</a></h3>
The <tt>Incrementable</tt> type must be <a
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default
Constructible</a>, <a href="./CopyConstructible.html">Copy
Constructible</a>, and <a href="./Assignable.html">Assignable</a>.
Also, the <tt>Incrementable</tt> type must provide access to an
associated <tt>difference_type</tt> and <tt>iterator_category</tt>
through the <a
href="#counting_iterator_traits"><tt>counting_iterator_traits</tt></a>
class.
<p>
Furthermore, if you wish to create a counting iterator that is a <a
href="http://www.sgi.com/tech/stl/ForwardIterator.html"> Forward
Iterator</a>, then the following expressions must be valid:
<pre>
Incrementable i, j;
++i // pre-increment
i == j // operator equal
</pre>
If you wish to create a counting iterator that is a <a
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">
Bidirectional Iterator</a>, then pre-decrement is also required:
<pre>
--i
</pre>
If you wish to create a counting iterator that is a <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> Random
Access Iterator</a>, then these additional expressions are also required:
<pre>
<a href="#counting_iterator_traits">counting_iterator_traits</a>&lt;Incrementable&gt;::difference_type n;
i += n
n = i - j
i < j
</pre>
<h3>Members</h3>
The counting iterator type implements the member functions and
operators required of the <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access Iterator</a> concept. In addition it has the following
constructor:
<pre>
counting_iterator_generator::type(const Incrementable&amp; i)
</pre>
<p>
<hr>
<p>
<h2><a name="make_counting_iterator">The Counting Iterator Object Generator</a></h2>
<pre>
template &lt;class Incrementable&gt;
typename counting_iterator_generator&lt;Incrementable&gt;::type
make_counting_iterator(Incrementable base);
</pre>
An <a href="../../more/generic_programming.html#object_generator">object
generator</a> function that provides a convenient way to create counting
iterators.<p>
<h3>Example</h3>
In this example we count from negative five to positive five, this
time using the <tt>make_counting_iterator()</tt> function to save some
typing.
<pre>
// continuing from previous example...
std::cout &lt;&lt; "counting from -5 to 4:" &lt;&lt; std::endl;
std::copy(boost::make_counting_iterator(-5),
boost::make_counting_iterator(5),
std::ostream_iterator&lt;int&gt;(std::cout, " "));
std::cout &lt;&lt; std::endl;
// to be continued...
</pre>
The output from this part is:
<pre>
counting from -5 to 4:
-5 -4 -3 -2 -1 0 1 2 3 4
</pre>
In the next example we create an array of numbers, and then create a
second array of pointers, where each pointer is the address of a
number in the first array. The counting iterator makes it easy to do
this since dereferencing a counting iterator that is wrapping an
iterator over the array of numbers just returns a pointer to the
current location in the array. We then use the <a
href="./indirect_iterator.htm">indirect iterator adaptor</a> to print
out the number in the array by accessing the numbers through the array
of pointers.
<pre>
// continuing from previous example...
const int N = 7;
std::vector&lt;int&gt; numbers;
// Fill "numbers" array with [0,N)
std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N),
std::back_inserter(numbers));
std::vector&lt;std::vector&lt;int&gt;::iterator&gt; pointers;
// Use counting iterator to fill in the array of pointers.
std::copy(boost::make_counting_iterator(numbers.begin()),
boost::make_counting_iterator(numbers.end()),
std::back_inserter(pointers));
// Use indirect iterator to print out numbers by accessing
// them through the array of pointers.
std::cout &lt;&lt; "indirectly printing out the numbers from 0 to "
&lt;&lt; N &lt;&lt; std::endl;
std::copy(boost::make_indirect_iterator(pointers.begin()),
boost::make_indirect_iterator(pointers.end()),
std::ostream_iterator&lt;int&gt;(std::cout, " "));
std::cout &lt;&lt; std::endl;
</pre>
The output is:
<pre>
indirectly printing out the numbers from 0 to 7
0 1 2 3 4 5 6
</pre>
<hr>
<h2><a name="counting_iterator_traits">Counting Iterator Traits</a></h2>
The counting iterator adaptor needs to determine the appropriate
<tt>difference_type</tt> and <tt>iterator_category</tt> to use based on the
<tt>Incrementable</tt> type supplied by the user. The
<tt>counting_iterator_traits</tt> class provides these types. If the
<tt>Incrementable</tt> type is an integral type or an iterator, these types
will be correctly deduced by the <tt>counting_iterator_traits</tt> provided by
the library. Otherwise, the user must specialize
<tt>counting_iterator_traits</tt> for her type or add nested typedefs to
her type to fulfill the needs of
<a href="http://www.sgi.com/tech/stl/iterator_traits.html">
<tt>std::iterator_traits</tt></a>.
<p>The following pseudocode describes how the <tt>counting_iterator_traits</tt> are determined:
<pre>
template &lt;class Incrementable&gt;
struct counting_iterator_traits
{
if (numeric_limits&lt;Incrementable&gt::is_specialized) {
if (!numeric_limits&lt;Incrementable&gt::is_integer)
COMPILE_TIME_ERROR;
if (!numeric_limits&lt;Incrementable&gt::is_bounded
&amp;&amp; numeric_limits&lt;Incrementable&gt;::is_signed) {
typedef Incrementable difference_type;
}
else if (numeric_limits&lt;Incrementable&gt::is_integral) {
typedef <i>next-larger-signed-type-or-intmax_t</i> difference_type;
}
typedef std::random_access_iterator_tag iterator_category;
} else {
typedef std::iterator_traits&lt;Incrementable&gt;::difference_type difference_type;
typedef std::iterator_traits&lt;Incrementable&gt;::iterator_category iterator_category;
}
};
</pre>
<p>The italicized sections above are implementation details, but it is important
to know that the <tt>difference_type</tt> for integral types is selected so that
it can always represent the difference between two values if such a built-in
integer exists. On platforms with a working <tt>std::numeric_limits</tt>
implementation, the <tt>difference_type</tt> for any variable-length signed
integer type <tt>T</tt> is <tt>T</tt> itself.
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" --></p>
<p><EFBFBD> Copyright Jeremy Siek 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 &quot;as is&quot;
without express or implied warranty, and with no claim as to its suitability for
any purpose.</p>
</body>
</html>
<!-- LocalWords: html charset alt gif hpp incrementable const namespace htm
-->
<!-- LocalWords: struct typename iostream int Siek CopyConstructible pre
-->

View File

@ -0,0 +1,55 @@
// (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 <iostream>
#include <iterator>
#include <vector>
#include <boost/counting_iterator.hpp>
#include <boost/iterator_adaptors.hpp>
int main(int, char*[])
{
// Example of using counting_iterator_generator
std::cout << "counting from 0 to 4:" << std::endl;
boost::counting_iterator_generator<int>::type first(0), last(4);
std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// Example of using make_counting_iterator()
std::cout << "counting from -5 to 4:" << std::endl;
std::copy(boost::make_counting_iterator(-5),
boost::make_counting_iterator(5),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// Example of using counting iterator to create an array of pointers.
const int N = 7;
std::vector<int> numbers;
// Fill "numbers" array with [0,N)
std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N),
std::back_inserter(numbers));
std::vector<std::vector<int>::iterator> pointers;
// VC6 gets an internal compiler error on this
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
// Use counting iterator to fill in the array of pointers.
std::copy(boost::make_counting_iterator(numbers.begin()),
boost::make_counting_iterator(numbers.end()),
std::back_inserter(pointers));
// Use indirect iterator to print out numbers by accessing
// them through the array of pointers.
std::cout << "indirectly printing out the numbers from 0 to "
<< N << std::endl;
std::copy(boost::make_indirect_iterator(pointers.begin()),
boost::make_indirect_iterator(pointers.end()),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
#endif
return 0;
}

269
counting_iterator_test.cpp Normal file
View File

@ -0,0 +1,269 @@
// (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
// 16 Feb 2001 Added a missing const. Made the tests run (somewhat) with
// plain MSVC again. (David Abrahams)
// 11 Feb 2001 #if 0'd out use of counting_iterator on non-numeric types in
// MSVC without STLport, so that the other tests may proceed
// (David Abrahams)
// 04 Feb 2001 Added use of iterator_tests.hpp (David Abrahams)
// 28 Jan 2001 Removed not_an_iterator detritus (David Abrahams)
// 24 Jan 2001 Initial revision (David Abrahams)
#include <boost/config.hpp>
#ifdef BOOST_MSVC
# pragma warning(disable:4786) // identifier truncated in debug info
#endif
#include <boost/pending/iterator_tests.hpp>
#include <boost/counting_iterator.hpp>
#include <boost/detail/iterator.hpp>
#include <iostream>
#include <climits>
#include <iterator>
#include <stdlib.h>
#ifndef __BORLANDC__
# include <boost/tuple/tuple.hpp>
#endif
#include <vector>
#include <list>
#include <cassert>
#ifndef BOOST_NO_LIMITS
# include <limits>
#endif
#ifndef BOOST_NO_SLIST
# include <slist>
#endif
template <class T> struct is_numeric
{
enum { value =
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
std::numeric_limits<T>::is_specialized
#else
// Causes warnings with GCC, but how else can I detect numeric types at
// compile-time?
(boost::is_convertible<int,T>::value &&
boost::is_convertible<T,int>::value)
#endif
};
};
// Special tests for RandomAccess CountingIterators.
template <class CountingIterator>
void category_test(
CountingIterator start,
CountingIterator finish,
std::random_access_iterator_tag)
{
typedef typename
boost::detail::iterator_traits<CountingIterator>::difference_type
difference_type;
difference_type distance = boost::detail::distance(start, finish);
// Pick a random position internal to the range
difference_type offset = (unsigned)rand() % distance;
assert(offset >= 0);
CountingIterator internal = start;
std::advance(internal, offset);
// Try some binary searches on the range to show that it's ordered
assert(std::binary_search(start, finish, *internal));
// #including tuple crashed borland, so I had to give up on tie().
std::pair<CountingIterator,CountingIterator> xy(
std::equal_range(start, finish, *internal));
CountingIterator x = xy.first, y = xy.second;
assert(boost::detail::distance(x, y) == 1);
// Show that values outside the range can't be found
assert(!std::binary_search(start, boost::prior(finish), *finish));
// Do the generic random_access_iterator_test
typedef typename CountingIterator::value_type value_type;
std::vector<value_type> v;
for (value_type z = *start; z != *finish; ++z)
v.push_back(z);
if (v.size() >= 2)
{
// Note that this test requires a that the first argument is
// dereferenceable /and/ a valid iterator prior to the first argument
boost::random_access_iterator_test(start + 1, v.size() - 1, v.begin() + 1);
}
}
// Special tests for bidirectional CountingIterators
template <class CountingIterator>
void category_test(CountingIterator start, CountingIterator finish, std::bidirectional_iterator_tag)
{
if (finish != start
&& finish != boost::next(start)
&& finish != boost::next(boost::next(start)))
{
// Note that this test requires a that the first argument is
// dereferenceable /and/ a valid iterator prior to the first argument
boost::bidirectional_iterator_test(boost::next(start), boost::next(*start), boost::next(boost::next(*start)));
}
}
template <class CountingIterator>
void category_test(CountingIterator start, CountingIterator finish, std::forward_iterator_tag)
{
if (finish != start && finish != boost::next(start))
boost::forward_iterator_test(start, *start, boost::next(*start));
}
template <class CountingIterator>
void test_aux(CountingIterator start, CountingIterator finish)
{
typedef typename CountingIterator::iterator_category category;
typedef typename CountingIterator::value_type value_type;
// If it's a RandomAccessIterator we can do a few delicate tests
category_test(start, finish, category());
// Okay, brute force...
for (CountingIterator p = start; p != finish && boost::next(p) != finish; ++p)
{
assert(boost::next(*p) == *boost::next(p));
}
// prove that a reference can be formed to these values
typedef typename CountingIterator::value_type value;
const value* q = &*start;
(void)q; // suppress unused variable warning
}
template <class Incrementable>
void test(Incrementable start, Incrementable finish)
{
test_aux(boost::make_counting_iterator(start), boost::make_counting_iterator(finish));
}
template <class Integer>
void test_integer(Integer* = 0) // default arg works around MSVC bug
{
Integer start = 0;
Integer finish = 120;
test(start, finish);
}
template <class Container>
void test_container(Container* = 0) // default arg works around MSVC bug
{
Container c(1 + (unsigned)rand() % 1673);
const typename Container::iterator start = c.begin();
// back off by 1 to leave room for dereferenceable value at the end
typename Container::iterator finish = start;
std::advance(finish, c.size() - 1);
test(start, finish);
typedef typename Container::const_iterator const_iterator;
test(const_iterator(start), const_iterator(finish));
}
class my_int1 {
public:
my_int1() { }
my_int1(int x) : m_int(x) { }
my_int1& operator++() { ++m_int; return *this; }
bool operator==(const my_int1& x) const { return m_int == x.m_int; }
private:
int m_int;
};
namespace boost {
template <>
struct counting_iterator_traits<my_int1> {
typedef std::ptrdiff_t difference_type;
typedef std::forward_iterator_tag iterator_category;
};
}
class my_int2 {
public:
typedef void value_type;
typedef void pointer;
typedef void reference;
typedef std::ptrdiff_t difference_type;
typedef std::bidirectional_iterator_tag iterator_category;
my_int2() { }
my_int2(int x) : m_int(x) { }
my_int2& operator++() { ++m_int; return *this; }
my_int2& operator--() { --m_int; return *this; }
bool operator==(const my_int2& x) const { return m_int == x.m_int; }
private:
int m_int;
};
class my_int3 {
public:
typedef void value_type;
typedef void pointer;
typedef void reference;
typedef std::ptrdiff_t difference_type;
typedef std::random_access_iterator_tag iterator_category;
my_int3() { }
my_int3(int x) : m_int(x) { }
my_int3& operator++() { ++m_int; return *this; }
my_int3& operator+=(std::ptrdiff_t n) { m_int += n; return *this; }
std::ptrdiff_t operator-(const my_int3& x) const { return m_int - x.m_int; }
my_int3& operator--() { --m_int; return *this; }
bool operator==(const my_int3& x) const { return m_int == x.m_int; }
bool operator!=(const my_int3& x) const { return m_int != x.m_int; }
bool operator<(const my_int3& x) const { return m_int < x.m_int; }
private:
int m_int;
};
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
// wrapping an iterator or non-built-in integer type causes an INTERNAL
// COMPILER ERROR in MSVC without STLport. I'm clueless as to why.
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
// Test user-defined type.
test_integer<my_int1>();
test_integer<my_int2>();
test_integer<my_int3>();
// 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];
test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1));
#endif
std::cout << "test successful " << std::endl;
return 0;
}

View File

@ -1,36 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Boost: current_function.hpp documentation</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
</head>
<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%">
<table border="0" width="100%">
<tr>
<td width="277"><A href="../../index.htm"> <img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86" border="0"></A>
</td>
<td align="center">
<h1>current_function.hpp</h1>
</td>
</tr>
<tr>
<td colspan="2" height="64">&nbsp;</td>
</tr>
</table>
<p>
The header <STRONG>&lt;boost/current_function.hpp&gt;</STRONG> defines a single
macro, <STRONG>BOOST_CURRENT_FUNCTION</STRONG>,<STRONG> </STRONG>similar to the
C99 predefined identifier <STRONG>__func__</STRONG>.
</p>
<P><STRONG>BOOST_CURRENT_FUNCTION</STRONG> expands to a string literal containing
the (fully qualified, if possible) name of the enclosing function. If there is
no enclosing function, the behavior is undefined.</P>
<p>Some compilers do not provide a way to obtain the name of the current enclosing
function. On such compilers, the string literal has an unspecified value.</p>
<p>
<br>
<small>Copyright <20> 2002 by Peter Dimov. Distributed under the Boost Software License, Version
1.0. See accompanying file <A href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</A> or
copy at <A href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</A>.</small></p>
</body>
</html>

View File

@ -1,6 +1,4 @@
#include <boost/config.hpp>
#if defined(BOOST_MSVC)
#if defined(_MSC_VER) && !defined(__ICL)
#pragma warning(disable: 4786) // identifier truncated in debug info
#pragma warning(disable: 4710) // function not inlined
#pragma warning(disable: 4711) // function selected for automatic inline expansion
@ -12,22 +10,18 @@
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// 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/current_function.hpp>
#include <boost/config.hpp>
#include <cstdio>
void message(char const * file, long line, char const * func, char const * msg)
{
#if !defined(BOOST_NO_STDC_NAMESPACE)
using std::printf;
#endif
printf("%s(%ld): %s in function '%s'\n", file, line, msg, func);
std::printf("%s(%ld): %s in function '%s'\n", file, line, msg, func);
}
#define MESSAGE(msg) message(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, msg)
@ -35,6 +29,4 @@ void message(char const * file, long line, char const * func, char const * msg)
int main()
{
MESSAGE("assertion failed");
return 0;
}

View File

@ -1,388 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<HTML>
<HEAD><TITLE>enable_if</TITLE>
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="Microsoft FrontPage 5.0">
</HEAD>
<BODY >
<!--HEVEA command line is: hevea -nosymb -noiso -pedantic -v enable_if_docs_for_boost.tex -->
<!--HTMLHEAD-->
<!--ENDHTML-->
<!--PREFIX <ARG ></ARG>-->
<!--CUT DEF section 1 -->
<BR>
<BR>
<h1>
<img border="0" src="../../boost.png" align="center" width="277" height="86">enable_if</h1>
<BR>
<BR>
Copyright 2003 Jaakko J&auml;rvi, Jeremiah Willcock, Andrew Lumsdaine.<BR>
<BR>
<!--TOC section Introduction-->
<H2><A NAME="htoc1">1</A>&nbsp;&nbsp;Introduction</H2><!--SEC END -->
<A NAME="introduction"></A>
The <TT>enable_if</TT> family of templates is a set of tools to allow a function template or a class template specialization
to include or exclude itself from a set of matching functions or specializations
based on properties of its template arguments.
For example, one can define function templates that
are only enabled for, and thus only match, an arbitrary set of types
defined by a traits class. The <TT>enable_if</TT> templates can also be
applied to enable class template specializations. Applications of
<TT>enable_if</TT> are discussed in length
in&nbsp;[<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>] and&nbsp;[<A HREF="#jarvi:03:c++typeclasses"><CITE>2</CITE></A>].<BR>
<BR>
<!--TOC subsection Synopsis-->
<H3><A NAME="htoc2">1.1</A>&nbsp;&nbsp;Synopsis</H3><!--SEC END -->
<A NAME="sec:synopsis"></A>
<PRE>namespace boost {
template &lt;class Cond, class T = void&gt; struct enable_if;
template &lt;class Cond, class T = void&gt; struct disable_if;
template &lt;class Cond, class T&gt; struct lazy_enable_if;
template &lt;class Cond, class T&gt; struct lazy_disable_if;
template &lt;bool B, class T = void&gt; struct enable_if_c;
template &lt;bool B, class T = void&gt; struct disable_if_c;
template &lt;bool B, class T&gt; struct lazy_enable_if_c;
template &lt;bool B, class T&gt; struct lazy_disable_if_c;
}
</PRE>
<!--TOC subsection Background-->
<H3><A NAME="htoc3">1.2</A>&nbsp;&nbsp;Background</H3><!--SEC END -->
<A NAME="sec:background"></A>
Sensible operation of template function overloading in C++ relies
on the <EM>SFINAE</EM> (substitution-failure-is-not-an-error)
principle&nbsp;[<A HREF="#vandevoorde2002:templates"><CITE>3</CITE></A>]: if an invalid argument
or return type is formed during the instantiation of a function
template, the instantiation is removed from the overload resolution
set instead of causing a compilation error. The following example,
taken from&nbsp;[<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>],
demonstrates why this is important:
<PRE>int negate(int i) { return -i; }
template &lt;class F&gt;
typename F::result_type negate(const F&amp; f) { return -f(); }
</PRE>
Suppose the compiler encounters the call <TT>negate(1)</TT>. The first
definition is obviously a better match, but the compiler must
nevertheless consider (and instantiate the prototypes) of both
definitions to find this out. Instantiating the latter definition with
<TT>F</TT> as <TT>int</TT> would result in:
<PRE>int::result_type negate(const int&amp;);
</PRE>
where the return type is invalid. If this was an error, adding an unrelated function template
(that was never called) could break otherwise valid code.
Due to the SFINAE principle the above example is not, however, erroneous.
The latter definition of <TT>negate</TT> is simply removed from the overload resolution set.<BR>
<BR>
The <TT>enable_if</TT> templates are tools for controlled creation of the SFINAE
conditions.<BR>
<BR>
<!--TOC section The <TT>enable_if</TT> templates-->
<H2><A NAME="htoc4">2</A>&nbsp;&nbsp;The <TT>enable_if</TT> templates</H2><!--SEC END -->
<A NAME="enable_if"></A>
The names of the <TT>enable_if</TT> templates have three parts: an optional <TT>lazy_</TT> tag,
either <TT>enable_if</TT> or <TT>disable_if</TT>, and an optional <TT>_c</TT> tag.
All eight combinations of these parts are supported.
The meaning of the <TT>lazy_</TT> tag is described in Section&nbsp;<A HREF="#sec:enable_if_lazy">3.3</A>.
The second part of the name indicates whether a true condition argument should
enable or disable the current overload.
The third part of the name indicates whether the condition argument is a <TT>bool</TT> value
(<TT>_c</TT> suffix), or a type containing a static <TT>bool</TT> constant named <TT>value</TT> (no suffix).
The latter version interoperates with Boost.MPL. <BR>
<BR>
The definitions of <TT>enable_if_c</TT> and <TT>enable_if</TT> are as follows (we use <TT>enable_if</TT> templates
unqualified but they are in the <TT>boost</TT> namespace).
<PRE>template &lt;bool B, class T = void&gt;
struct enable_if_c {
typedef T type;
};
template &lt;class T&gt;
struct enable_if_c&lt;false, T&gt; {};
template &lt;class Cond, class T = void&gt;
struct enable_if : public enable_if_c&lt;Cond::value, T&gt; {};
</PRE>
An instantiation of the <TT>enable_if_c</TT> template with the parameter
<TT>B</TT> as <TT>true</TT> contains a member type <TT>type</TT>, defined
to be <TT>T</TT>. If <TT>B</TT> is
<TT>false</TT>, no such member is defined. Thus
<TT>enable_if_c&lt;B, T&gt;::type</TT> is either a valid or an invalid type
expression, depending on the value of <TT>B</TT>.
When valid, <TT>enable_if_c&lt;B, T&gt;::type</TT> equals <TT>T</TT>.
The <TT>enable_if_c</TT> template can thus be used for controlling when functions are considered for
overload resolution and when they are not.
For example, the following function is defined for all arithmetic types (according to the
classification of the <A HREF="../type_traits/index.html">Boost type_traits library</A>):
<PRE>template &lt;class T&gt;
typename enable_if_c&lt;boost::is_arithmetic&lt;T&gt;::value, T&gt;::type
foo(T t) { return t; }
</PRE>
The <TT>disable_if_c</TT> template is provided as well, and has the
same functionality as <TT>enable_if_c</TT> except for the negated condition. The following
function is enabled for all non-arithmetic types.
<PRE>template &lt;class T&gt;
typename disable_if_c&lt;boost::is_arithmetic&lt;T&gt;::value, T&gt;::type
bar(T t) { return t; }
</PRE>
For easier syntax in some cases and interoperation with Boost.MPL we provide versions of
the <TT>enable_if</TT> templates taking any type with a <TT>bool</TT> member constant named
<TT>value</TT> as the condition argument.
The MPL <TT>bool_</TT>, <TT>and_</TT>, <TT>or_</TT>, and <TT>not_</TT> templates are likely to be
useful for creating such types. Also, the traits classes in the Boost.Type_traits library
follow this convention.
For example, the above example function <TT>foo</TT> can be alternatively written as:
<PRE>template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t) { return t; }
</PRE>
<!--TOC section Using <TT>enable_if</TT>-->
<H2><A NAME="htoc5">3</A>&nbsp;&nbsp;Using <TT>enable_if</TT></H2><!--SEC END -->
<A NAME="sec:using_enable_if"></A>
The <TT>enable_if</TT> templates are defined in
<TT>boost/utility/enable_if.hpp</TT>, which is included by <TT>boost/utility.hpp</TT>.<BR>
<BR>
The <TT>enable_if</TT> template can be used either as the return type, or as an
extra argument. For example, the <TT>foo</TT> function in the previous section could also be written
as:
<PRE>template &lt;class T&gt;
T foo(T t, typename enable_if&lt;boost::is_arithmetic&lt;T&gt; &gt;::type* dummy = 0);
</PRE>Hence, an extra parameter of type <TT>void*</TT> is added, but it is given
a default value to keep the parameter hidden from client code.
Note that the second template argument was not given to <TT>enable_if</TT>, as the default
<TT>void</TT> gives the desired behavior.<BR>
<BR>
Whether to write the enabler as an argument or within the return type is
largely a matter of taste, but for certain functions, only one
alternative is possible:
<UL><LI>
Operators have a fixed number of arguments, thus <TT>enable_if</TT> must be used in the return type.
<LI>Constructors and destructors do not have a return type; an extra argument is the only option.
<LI>There does not seem to be a way to specify an enabler for a conversion operator. Converting constructors,
however, can have enablers as extra default arguments.
</UL>
<!--TOC subsection Enabling template class specializations-->
<H3><A NAME="htoc6">3.1</A>&nbsp;&nbsp;Enabling template class specializations</H3><!--SEC END -->
<A NAME="sec:enable_if_classes"></A>
Class template specializations can be enabled or disabled with <TT>enable_if</TT>.
One extra template parameter needs to be added for the enabler expressions.
This parameter has the default value <TT>void</TT>.
For example:
<PRE>template &lt;class T, class Enable = void&gt;
class A { ... };
template &lt;class T&gt;
class A&lt;T, typename enable_if&lt;is_integral&lt;T&gt; &gt;::type&gt; { ... };
template &lt;class T&gt;
class A&lt;T, typename enable_if&lt;is_float&lt;T&gt; &gt;::type&gt; { ... };
</PRE>Instantiating <TT>A</TT> with any integral type matches the first specialization,
whereas any floating point type matches the second one. All other types
match the primary template.
The condition can be any compile-time boolean expression that depends on the
template arguments of the class.
Note that again, the second argument to <TT>enable_if</TT> is not needed; the default (<TT>void</TT>)
is the correct value.<BR>
<BR>
<!--TOC subsection Overlapping enabler conditions-->
<H3><A NAME="htoc7">3.2</A>&nbsp;&nbsp;Overlapping enabler conditions</H3><!--SEC END -->
<A NAME="sec:overlapping_conditions"></A>
Once the compiler has examined the enabling conditions and included the
function into the overload resolution set, normal C++ overload resolution
rules are used to select the best matching function.
In particular, there is no ordering between enabling conditions.
Function templates with enabling conditions that are not mutually exclusive can
lead to ambiguities. For example:
<PRE>template &lt;class T&gt;
typename enable_if&lt;boost::is_integral&lt;T&gt;, void&gt;::type
foo(T t) {}
template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, void&gt;::type
foo(T t) {}
</PRE>
All integral types are also arithmetic. Therefore, say, for the call <TT>foo(1)</TT>,
both conditions are true and both functions are thus in the overload resolution set.
They are both equally good matches and thus ambiguous.
Of course, more than one enabling condition can be simultaneously true as long as
other arguments disambiguate the functions.<BR>
<BR>
The above discussion applies to using <TT>enable_if</TT> in class template
partial specializations as well.<BR>
<BR>
<!--TOC subsection Lazy <TT>enable_if</TT>-->
<H3><A NAME="htoc8">3.3</A>&nbsp;&nbsp;Lazy <TT>enable_if</TT></H3><!--SEC END -->
<A NAME="sec:enable_if_lazy"></A>
In some cases it is necessary to avoid instantiating part of a
function signature unless an enabling condition is true. For example:
<PRE>template &lt;class T, class U&gt; class mult_traits;
template &lt;class T, class U&gt;
typename enable_if&lt;is_multipliable&lt;T, U&gt;, typename mult_traits&lt;T, U&gt;::type&gt;::type
operator*(const T&amp; t, const U&amp; u) { ... }
</PRE>Assume the class template <TT>mult_traits</TT> is a traits class defining
the resulting type of a multiplication operator. The <TT>is_multipliable</TT> traits
class specifies for which types to enable the operator. Whenever
<TT>is_multipliable&lt;A, B&gt;::value</TT> is <TT>true</TT> for some types <TT>A</TT> and <TT>B</TT>,
then <TT>mult_traits&lt;A, B&gt;::type</TT> is defined.<BR>
<BR>
Now, trying to invoke (some other overload) of <TT>operator*</TT> with, say, operand types <TT>C</TT> and <TT>D</TT>
for which <TT>is_multipliable&lt;C, D&gt;::value</TT> is <TT>false</TT>
and <TT>mult_traits&lt;C, D&gt;::type</TT> is not defined is an error on some compilers.
The SFINAE principle is not applied because
the invalid type occurs as an argument to another template. The <TT>lazy_enable_if</TT>
and <TT>lazy_disable_if</TT> templates (and their <TT>_c</TT> versions) can be used in such
situations:
<PRE>template&lt;class T, class U&gt;
typename lazy_enable_if&lt;is_multipliable&lt;T, U&gt;, mult_traits&lt;T, U&gt; &gt;::type
operator*(const T&amp; t, const U&amp; u) { ... }
</PRE>The second argument of <TT>lazy_enable_if</TT> must be a class type
that defines a nested type named <TT>type</TT> whenever the first
parameter (the condition) is true.<BR>
<BR>
<!--TOC paragraph Note-->
<H5>Note</H5><!--SEC END -->
Referring to one member type or static constant in a traits class
causes all of the members (type and static constant) of that
specialization to be instantiated. Therefore, if your traits classes
can sometimes contain invalid types, you should use two distinct
templates for describing the conditions and the type mappings. In the
above example, <TT>is_multipliable&lt;T, U&gt;::value</TT> defines when
<TT>mult_traits&lt;T, U&gt;::type</TT> is valid.<BR>
<BR>
<!--TOC subsection Compiler workarounds-->
<H3><A NAME="htoc9">3.4</A>&nbsp;&nbsp;Compiler workarounds</H3><!--SEC END -->
<A NAME="sec:workarounds"></A>
Some compilers flag functions as ambiguous if the only distinguishing factor is a different
condition in an enabler (even though the functions could never be ambiguous). For example,
some compilers (e.g. GCC 3.2) diagnose the following two functions as ambiguous:
<PRE>template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t);
template &lt;class T&gt;
typename disable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t);
</PRE>Two workarounds can be applied:
<UL><LI>
Use an extra dummy parameter which disambiguates the functions. Use a default value for
it to hide the parameter from the caller. For example:
<PRE>template &lt;int&gt; struct dummy { dummy(int) {} };
template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t, dummy&lt;0&gt; = 0);
template &lt;class T&gt;
typename disable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t, dummy&lt;1&gt; = 0);
</PRE><BR>
<BR>
<LI>Define the functions in different namespaces and bring them into a common
namespace with <TT>using</TT> declarations:
<PRE>namespace A {
template &lt;class T&gt;
typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t);
}
namespace B {
template &lt;class T&gt;
typename disable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
foo(T t);
}
using A::foo;
using B::foo;
</PRE>
Note that the second workaround above cannot be used for member
templates. On the other hand, operators do not accept extra arguments,
which makes the first workaround unusable. As the net effect,
neither of the workarounds are of assistance for templated operators that
need to be defined as member functions (assignment and
subscript operators).
</UL>
<!--TOC section Acknowledgements-->
<H2><A NAME="htoc10">4</A>&nbsp;&nbsp;Acknowledgements</H2><!--SEC END -->
We are grateful to Howard Hinnant, Jason Shirk, Paul Mensonides, and Richard
Smith whose findings have influenced the library.<BR>
<BR>
<!--TOC section References-->
<H2>References</H2><!--SEC END -->
<DL COMPACT=compact><DT><A NAME="jarvi:03:cuj_arbitrary_overloading"><FONT COLOR=purple>[1]</FONT></A><DD>
Jaakko J&auml;rvi, Jeremiah Willcock, Howard Hinnant, and Andrew Lumsdaine.
Function overloading based on arbitrary properties of types.
<EM>C/C++ Users Journal</EM>, 21(6):25--32, June 2003.<BR>
<BR>
<DT><A NAME="jarvi:03:c++typeclasses"><FONT COLOR=purple>[2]</FONT></A><DD>
Jaakko J&auml;rvi, Jeremiah Willcock, and Andrew Lumsdaine.
Concept-controlled polymorphism.
In Frank Pfennig and Yannis Smaragdakis, editors, <EM>Generative
Programming and Component Engineering</EM>, volume 2830 of <EM>LNCS</EM>, pages
228--244. Springer Verlag, September 2003.<BR>
<BR>
<DT><A NAME="vandevoorde2002:templates"><FONT COLOR=purple>[3]</FONT></A><DD>
David Vandevoorde and Nicolai&nbsp;M. Josuttis.
<EM>C++ Templates: The Complete Guide</EM>.
Addison-Wesley, 2002.</DL>
<hr></hr>
<B>Contributed by:</B> <BR>
Jaakko J&auml;rvi, Jeremiah Willcock and Andrew Lumsdaine<BR>
<EM>{jajarvi|jewillco|lums}@osl.iu.edu</EM><BR>
Indiana University<BR>
Open Systems Lab
<!--HTMLFOOT-->
<!--ENDHTML-->
<!--FOOTER-->
<HR SIZE=2>
<BLOCKQUOTE><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
</EM><A HREF="http://pauillac.inria.fr/~maranget/hevea/index.html"><EM>H<FONT SIZE=2><sup>E</sup></FONT>V<FONT SIZE=2><sup>E</sup></FONT>A</EM></A><EM>.
</EM></BLOCKQUOTE>
</BODY>
</HTML>

View File

@ -1,23 +0,0 @@
# Copyright David Abrahams 2003.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
# For more information, see http://www.boost.org/
project
: requirements <library>/boost/test//boost_test_exec_monitor
;
test-suite utility/enable_if
:
[ run constructors.cpp ]
[ run dummy_arg_disambiguation.cpp ]
[ run lazy.cpp ]
[ run lazy_test.cpp ]
[ run member_templates.cpp ]
[ run namespace_disambiguation.cpp ]
[ run no_disambiguation.cpp ]
[ run partial_specializations.cpp ]
;

View File

@ -1,62 +0,0 @@
// Boost enable_if library
// Copyright 2003 <20> The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#include <boost/test/minimal.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits.hpp>
using boost::enable_if;
using boost::disable_if;
using boost::is_arithmetic;
struct container {
bool my_value;
template <class T>
container(const T&, const typename enable_if<is_arithmetic<T>, T>::type * = 0):
my_value(true) {}
template <class T>
container(const T&, const typename disable_if<is_arithmetic<T>, T>::type * = 0):
my_value(false) {}
};
// example from Howard Hinnant (tests enable_if template members of a templated class)
template <class charT>
struct xstring
{
template <class It>
xstring(It begin, It end, typename
disable_if<is_arithmetic<It> >::type* = 0)
: data(end-begin) {}
int data;
};
int test_main(int, char*[])
{
BOOST_CHECK(container(1).my_value);
BOOST_CHECK(container(1.0).my_value);
BOOST_CHECK(!container("1").my_value);
BOOST_CHECK(!container(static_cast<void*>(0)).my_value);
char sa[] = "123456";
BOOST_CHECK(xstring<char>(sa, sa+6).data == 6);
return 0;
}

View File

@ -1,46 +0,0 @@
// Boost enable_if library
// Copyright 2003 <20> The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#include <boost/test/minimal.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
using boost::enable_if;
using boost::disable_if;
using boost::is_arithmetic;
template <int N> struct dummy {
dummy(int) {};
};
template<class T>
typename enable_if<is_arithmetic<T>, bool>::type
arithmetic_object(T t, dummy<0> = 0) { return true; }
template<class T>
typename disable_if<is_arithmetic<T>, bool>::type
arithmetic_object(T t, dummy<1> = 0) { return false; }
int test_main(int, char*[])
{
BOOST_CHECK(arithmetic_object(1));
BOOST_CHECK(arithmetic_object(1.0));
BOOST_CHECK(!arithmetic_object("1"));
BOOST_CHECK(!arithmetic_object(static_cast<void*>(0)));
return 0;
}

View File

@ -1,82 +0,0 @@
// Boost enable_if library
// Copyright 2003 <20> The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#include <boost/test/minimal.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
using boost::enable_if_c;
using boost::lazy_enable_if_c;
// This class provides a reduced example of a traits class for
// computing the result of multiplying two types. The member typedef
// 'type' in this traits class defines the return type of this
// operator. The return type member is invalid unless both arguments
// for mult_traits are values that mult_traits expects (ints in this
// case). This kind of situation may arise if a traits class only
// makes sense for some set of types, not all C++ types.
template <class T> struct is_int {
BOOST_STATIC_CONSTANT(bool, value = (boost::is_same<T, int>::value));
};
template <class T, class U>
struct mult_traits {
typedef typename T::does_not_exist type;
};
template <>
struct mult_traits<int, int> {
typedef int type;
};
// Next, a forwarding function mult() is defined. It is enabled only
// when both arguments are of type int. The first version, using
// non-lazy enable_if_c does not work.
#if 0
template <class T, class U>
typename enable_if_c<
is_int<T>::value && is_int<U>::value,
typename mult_traits<T, U>::type
>::type
mult(const T& x, const U& y) {return x * y;}
#endif
// A correct version uses lazy_enable_if_c.
// This template removes compiler errors from invalid code used as an
// argument to enable_if_c.
#if 1
template <class T, class U>
typename lazy_enable_if_c<
is_int<T>::value & is_int<U>::value,
mult_traits<T, U>
>::type
mult(const T& x, const U& y) {return x * y;}
#endif
double mult(int i, double d) { return (double)i * d; }
int test_main(int, char*[])
{
BOOST_CHECK(mult(1, 2) == 2);
BOOST_CHECK(mult(1, 3.0) == 3.0);
return 0;
}

View File

@ -1,100 +0,0 @@
// Boost enable_if library
// Copyright 2003 <20> The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
// Testing all variations of lazy_enable_if.
#include <boost/test/minimal.hpp>
#include <boost/mpl/not.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
using boost::lazy_enable_if;
using boost::lazy_disable_if;
using boost::lazy_enable_if_c;
using boost::lazy_disable_if_c;
template <class T>
struct is_int_or_double {
BOOST_STATIC_CONSTANT(bool,
value = (boost::is_same<T, int>::value ||
boost::is_same<T, double>::value));
};
template <class T>
struct some_traits {
typedef typename T::does_not_exist type;
};
template <>
struct some_traits<int> {
typedef bool type;
};
template <>
struct some_traits<double> {
typedef bool type;
};
template <class T>
struct make_bool {
typedef bool type;
};
template <>
struct make_bool<int> {};
template <>
struct make_bool<double> {};
namespace A {
template<class T>
typename lazy_enable_if<is_int_or_double<T>, some_traits<T> >::type
foo(T t) { return true; }
template<class T>
typename lazy_enable_if_c<is_int_or_double<T>::value, some_traits<T> >::type
foo2(T t) { return true; }
}
namespace B {
template<class T>
typename lazy_disable_if<is_int_or_double<T>, make_bool<T> >::type
foo(T t) { return false; }
template<class T>
typename lazy_disable_if_c<is_int_or_double<T>::value, make_bool<T> >::type
foo2(T t) { return false; }
}
int test_main(int, char*[])
{
using namespace A;
using namespace B;
BOOST_CHECK(foo(1));
BOOST_CHECK(foo(1.0));
BOOST_CHECK(!foo("1"));
BOOST_CHECK(!foo(static_cast<void*>(0)));
BOOST_CHECK(foo2(1));
BOOST_CHECK(foo2(1.0));
BOOST_CHECK(!foo2("1"));
BOOST_CHECK(!foo2(static_cast<void*>(0)));
return 0;
}

View File

@ -1,43 +0,0 @@
// Boost enable_if library
// Copyright 2003 <20> The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#include <boost/test/minimal.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
using boost::enable_if;
using boost::disable_if;
using boost::is_arithmetic;
struct container {
template <class T>
typename enable_if<is_arithmetic<T>, bool>::type
arithmetic_object(const T&, const int* /* disambiguate */ = 0) {return true;}
template <class T>
typename disable_if<is_arithmetic<T>, bool>::type
arithmetic_object(const T&) {return false;}
};
int test_main(int, char*[])
{
BOOST_CHECK(container().arithmetic_object(1));
BOOST_CHECK(container().arithmetic_object(1.0));
BOOST_CHECK(!container().arithmetic_object("1"));
BOOST_CHECK(!container().arithmetic_object(static_cast<void*>(0)));
return 0;
}

View File

@ -1,47 +0,0 @@
// Boost enable_if library
// Copyright 2003 <20> The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#include <boost/test/minimal.hpp>
#include <boost/mpl/not.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
using boost::enable_if;
using boost::mpl::not_;
using boost::is_arithmetic;
namespace A {
template<class T>
typename enable_if<is_arithmetic<T>, bool>::type
arithmetic_object(T t) { return true; }
}
namespace B {
template<class T>
typename enable_if<not_<is_arithmetic<T> >, bool>::type
arithmetic_object(T t) { return false; }
}
int test_main(int, char*[])
{
using namespace A;
using namespace B;
BOOST_CHECK(arithmetic_object(1));
BOOST_CHECK(arithmetic_object(1.0));
BOOST_CHECK(!arithmetic_object("1"));
BOOST_CHECK(!arithmetic_object(static_cast<void*>(0)));
return 0;
}

View File

@ -1,43 +0,0 @@
// Boost enable_if library
// Copyright 2003 <20> The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#include <boost/test/minimal.hpp>
#include <boost/mpl/not.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
using boost::mpl::not_;
using boost::enable_if;
using boost::is_arithmetic;
template<class T>
typename enable_if<is_arithmetic<T>, bool>::type
arithmetic_object(T t) { return true; }
template<class T>
typename enable_if<not_<is_arithmetic<T> >, bool>::type
arithmetic_object(T t) { return false; }
int test_main(int, char*[])
{
BOOST_CHECK(arithmetic_object(1));
BOOST_CHECK(arithmetic_object(1.0));
BOOST_CHECK(!arithmetic_object("1"));
BOOST_CHECK(!arithmetic_object(static_cast<void*>(0)));
return 0;
}

View File

@ -1,67 +0,0 @@
// Boost enable_if library
// Copyright 2003 <20> The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#include <boost/test/minimal.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
using boost::enable_if_c;
using boost::disable_if_c;
using boost::enable_if;
using boost::disable_if;
using boost::is_arithmetic;
template <class T, class Enable = void>
struct tester;
template <class T>
struct tester<T, typename enable_if_c<is_arithmetic<T>::value>::type> {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class T>
struct tester<T, typename disable_if_c<is_arithmetic<T>::value>::type> {
BOOST_STATIC_CONSTANT(bool, value = false);
};
template <class T, class Enable = void>
struct tester2;
template <class T>
struct tester2<T, typename enable_if<is_arithmetic<T> >::type> {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <class T>
struct tester2<T, typename disable_if<is_arithmetic<T> >::type> {
BOOST_STATIC_CONSTANT(bool, value = false);
};
int test_main(int, char*[])
{
BOOST_CHECK(tester<int>::value);
BOOST_CHECK(tester<double>::value);
BOOST_CHECK(!tester<char*>::value);
BOOST_CHECK(!tester<void*>::value);
BOOST_CHECK(tester2<int>::value);
BOOST_CHECK(tester2<double>::value);
BOOST_CHECK(!tester2<char*>::value);
BOOST_CHECK(!tester2<void*>::value);
return 0;
}

273
filter_iterator.htm Normal file
View File

@ -0,0 +1,273 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Filter Iterator Adaptor Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
align="center" width="277" height="86">
<h1>Filter Iterator Adaptor</h1>
Defined in header
<a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
<p>
The filter iterator adaptor creates a view of an iterator range in
which some elements of the range are skipped over. A <a
href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>
function object controls which elements are skipped. When the
predicate is applied to an element, if it returns <tt>true</tt> then
the element is retained and if it returns <tt>false</tt> then the
element is skipped over.
<h2>Synopsis</h2>
<pre>
namespace boost {
template &lt;class Predicate, class BaseIterator, ...&gt;
class filter_iterator_generator;
template &lt;class Predicate, class BaseIterator&gt;
typename filter_iterator_generator&lt;Predicate, BaseIterator&gt;::type
make_filter_iterator(BaseIterator first, BaseIterator last, const Predicate& p = Predicate());
}
</pre>
<hr>
<h2><a name="filter_iterator_generator">The Filter Iterator Type
Generator</a></h2>
The class <tt>filter_iterator_generator</tt> is a helper class whose
purpose is to construct a filter iterator type. The template
parameters for this class are the <tt>Predicate</tt> function object
type and the <tt>BaseIterator</tt> type that is being wrapped. In
most cases the associated types for the wrapped iterator can be
deduced from <tt>std::iterator_traits</tt>, but in some situations the
user may want to override these types, so there are also template
parameters for each of the iterator's associated types.
<pre>
template &lt;class Predicate, class BaseIterator,
class Value, class Reference, class Pointer, class Category, class Distance>
class filter_iterator_generator
{
public:
typedef <tt><a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt...&gt;</tt> type; // the resulting filter iterator type
}
</pre>
<h3>Example</h3>
The following example uses filter iterator to print out all the
positive integers in an array.
<pre>
struct is_positive_number {
bool operator()(int x) { return 0 &lt; x; }
};
int main() {
int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
const int N = sizeof(numbers)/sizeof(int);
typedef boost::filter_iterator_generator&lt;is_positive_number, int*, int&gt;::type FilterIter;
is_positive_number predicate;
FilterIter::policies_type policies(predicate, numbers + N);
FilterIter filter_iter_first(numbers, policies);
FilterIter filter_iter_last(numbers + N, policies);
std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator&lt;int&gt;(std::cout, " "));
std::cout &lt;&lt; std::endl;
return 0;
}
</pre>
The output is:
<pre>
4 5 8
</pre>
<h3>Template Parameters</h3>
<Table border>
<TR>
<TH>Parameter</TH><TH>Description</TH>
</TR>
<TR>
<TD><a href="http://www.sgi.com/tech/stl/Predicate.html"><tt>Predicate</tt></a></TD>
<TD>The function object that determines which elements are retained and which elements are skipped.
</TR>
<TR>
<TD><tt>BaseIterator</tt></TD>
<TD>The iterator type being wrapped. This type must at least be a model
of the <a href="http://www.sgi.com/tech/stl/InputIterator">InputIterator</a> concept.</TD>
</TR>
<TR>
<TD><tt>Value</tt></TD>
<TD>The <tt>value_type</tt> of the resulting iterator,
unless const. If const, a conforming compiler strips constness for the
<tt>value_type</tt>. Typically the default for this parameter is the
appropriate type<a href="#1">[1]</a>.<br> <b>Default:</b>
<tt>std::iterator_traits&lt;BaseIterator&gt;::value_type</TD>
</TR>
<TR>
<TD><tt>Reference</tt></TD>
<TD>The <tt>reference</tt> type of the resulting iterator, and in
particular, the result type of <tt>operator*()</tt>. Typically the default for
this parameter is the appropriate type.<br> <b>Default:</b> If
<tt>Value</tt> is supplied, <tt>Value&amp;</tt> is used. Otherwise
<tt>std::iterator_traits&lt;BaseIterator&gt;::reference</tt> is
used.</TD>
</TR>
<TR>
<TD><tt>Pointer</tt></TD>
<TD>The <tt>pointer</tt> type of the resulting iterator, and in
particular, the result type of <tt>operator->()</tt>.
Typically the default for
this parameter is the appropriate type.<br>
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
otherwise <tt>std::iterator_traits&lt;BaseIterator&gt;::pointer</tt>.</TD>
</TR>
<TR>
<TD><tt>Category</tt></TD>
<TD>The <tt>iterator_category</tt> type for the resulting iterator.
Typically the
default for this parameter is the appropriate type. If you override
this parameter, do not use <tt>bidirectional_iterator_tag</tt>
because filter iterators can not go in reverse.<br>
<b>Default:</b> <tt>std::iterator_traits&lt;BaseIterator&gt;::iterator_category</tt></TD>
</TR>
<TR>
<TD><tt>Distance</tt></TD>
<TD>The <tt>difference_type</tt> for the resulting iterator. Typically the default for
this parameter is the appropriate type.<br>
<b>Default:</b> <tt>std::iterator_traits&lt;BaseIterator&gt;::difference_type</TD>
</TR>
</table>
<h3>Model of</h3>
The filter iterator adaptor (the type
<tt>filter_iterator_generator<...>::type</tt>) may be a model of <a
href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> or <a
href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>
depending on the adapted iterator type.
<h3>Members</h3>
The filter iterator type implements all of the member functions and
operators required of the <a
href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>
concept. In addition it has the following constructor:
<pre>filter_iterator_generator::type(const BaseIterator& it, const Policies& p = Policies())</pre>
<p>
The policies type has only one public function, which is its constructor:
<pre>filter_iterator_generator::policies_type(const Predicate& p, const BaseIterator& end)</pre>
<p>
<hr>
<p>
<h2><a name="make_filter_iterator">The Make Filter Iterator Function</a></h2>
<pre>
template &lt;class Predicate, class BaseIterator&gt;
typename filter_generator&lt;Predicate, BaseIterator&gt;::type
make_filter_iterator(BaseIterator first, BaseIterator last, const Predicate& p = Predicate())
</pre>
This function provides a convenient way to create filter iterators.
<h3>Example</h3>
In this example we print out all numbers in the array that are
greater than negative two.
<pre>
int main()
{
int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
const int N = sizeof(numbers)/sizeof(int);
std::copy(boost::make_filter_iterator(numbers, numbers + N,
std::bind2nd(std::greater<int>(), -2)),
boost::make_filter_iterator(numbers + N, numbers + N,
std::bind2nd(std::greater<int>(), -2)),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
</pre>
The output is:
<pre>
0 -1 4 5 8
</pre>
<p>
In the next example we print the positive numbers using the
<tt>make_filter_iterator()</tt> function.
<pre>
struct is_positive_number {
bool operator()(int x) { return 0 &lt; x; }
};
int main()
{
int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
const int N = sizeof(numbers)/sizeof(int);
std::copy(boost::make_filter_iterator&lt;is_positive_number&gt;(numbers, numbers + N),
boost::make_filter_iterator&lt;is_positive_number&gt;(numbers + N, numbers + N),
std::ostream_iterator&lt;int&gt;(std::cout, " "));
std::cout &lt;&lt; std::endl;
return 0;
}
</pre>
The output is:
<pre>
4 5 8
</pre>
<h3>Notes</h3>
<a name="1">[1]</a> If the compiler does not support partial
specialization and the wrapped iterator type is a builtin pointer then
the <tt>Value</tt> type must be explicitly specified (don't use the
default).
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->09 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14894" --></p>
<p><EFBFBD> Copyright Jeremy Siek 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 &quot;as is&quot;
without express or implied warranty, and with no claim as to its suitability for
any purpose.</p>
</body>
</html>

View File

@ -0,0 +1,61 @@
// Example of using the filter iterator adaptor from
// boost/iterator_adaptors.hpp.
// (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.
#include <boost/config.hpp>
#include <algorithm>
#include <functional>
#include <iostream>
#include <boost/iterator_adaptors.hpp>
struct is_positive_number {
bool operator()(int x) { return 0 < x; }
};
int main()
{
int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 };
const int N = sizeof(numbers_)/sizeof(int);
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// Assume there won't be proper iterator traits for pointers. This
// is just a wrapper for int* which has the right traits.
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies, int> base_iterator;
#else
typedef int* base_iterator;
#endif
base_iterator numbers(numbers_);
// Example using make_filter_iterator()
std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// Example using filter_iterator_generator
typedef boost::filter_iterator_generator<is_positive_number, base_iterator, int>::type
FilterIter;
is_positive_number predicate;
FilterIter::policies_type policies(predicate, numbers + N);
FilterIter filter_iter_first(numbers, policies);
FilterIter filter_iter_last(numbers + N, policies);
std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
// Another example using make_filter_iterator()
std::copy(boost::make_filter_iterator(numbers, numbers + N,
std::bind2nd(std::greater<int>(), -2)),
boost::make_filter_iterator(numbers + N, numbers + N,
std::bind2nd(std::greater<int>(), -2)),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}

41
fun_out_iter_example.cpp Normal file
View File

@ -0,0 +1,41 @@
// (C) Copyright Jeremy Siek 2001. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// Revision History:
// 27 Feb 2001 Jeremy Siek
// Initial checkin.
#include <iostream>
#include <string>
#include <vector>
#include <boost/function_output_iterator.hpp>
struct string_appender {
string_appender(std::string& s) : m_str(s) { }
void operator()(const std::string& x) const {
m_str += x;
}
std::string& m_str;
};
int main(int, char*[])
{
std::vector<std::string> x;
x.push_back("hello");
x.push_back(" ");
x.push_back("world");
x.push_back("!");
std::string s = "";
std::copy(x.begin(), x.end(),
boost::make_function_output_iterator(string_appender(s)));
std::cout << s << std::endl;
return 0;
}

View File

@ -0,0 +1,169 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<meta name="generator" content="HTML Tidy, see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Function Output Iterator Adaptor Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"center" width="277" height="86">
<h1>Function Output Iterator Adaptor</h1>
Defined in header <a href=
"../../boost/function_output_iterator.hpp">boost/function_output_iterator.hpp</a>
<p>The function output iterator adaptor makes it easier to create
custom output iterators. The adaptor takes a <a
href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary
Function</a> and creates a model of <a
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
Iterator</a>. Each item assigned to the output iterator is passed
as an argument to the unary function. The motivation for this
iterator is that creating a C++ Standard conforming output
iterator is non-trivial, particularly because the proper
implementation usually requires a proxy object. On the other hand,
creating a function (or function object) is much simpler.
<h2>Synopsis</h2>
<blockquote>
<pre>
namespace boost {
template &lt;class UnaryFunction&gt;
class function_output_iterator;
template &lt;class UnaryFunction&gt;
function_output_iterator&lt;UnaryFunction&gt;
make_function_output_iterator(const UnaryFunction&amp; f = UnaryFunction())
}
</pre>
</blockquote>
<h3>Example</h3>
In this example we create an output iterator that appends
each item onto the end of a string, using the <tt>string_appender</tt>
function.
<blockquote>
<pre>
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;vector&gt;
#include &lt;boost/function_output_iterator.hpp&gt;
struct string_appender {
string_appender(std::string&amp; s) : m_str(s) { }
void operator()(const std::string&amp; x) const {
m_str += x;
}
std::string&amp; m_str;
};
int main(int, char*[])
{
std::vector&lt;std::string&gt; x;
x.push_back("hello");
x.push_back(" ");
x.push_back("world");
x.push_back("!");
std::string s = "";
std::copy(x.begin(), x.end(),
boost::make_function_output_iterator(string_appender(s)));
std::cout &lt;&lt; s &lt;&lt; std::endl;
return 0;
}
</pre>
</blockquote>
<hr>
<h2><a name="function_output_iterator">The Function Output Iterator Class</a></h2>
<blockquote>
<pre>
template &lt;class UnaryFunction&gt;
class function_output_iterator;
</pre>
</blockquote>
The <tt>function_output_iterator</tt> class creates an <a
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
Iterator</a> out of a
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary
Function</a>. Each item assigned to the output iterator is passed
as an argument to the unary function.
<h3>Template Parameters</h3>
<table border>
<tr>
<th>Parameter
<th>Description
<tr>
<td><tt>UnaryFunction</tt>
<td>The function type being wrapped. The return type of the
function is not used, so it can be <tt>void</tt>. The
function must be a model of <a
href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary
Function</a>.</td>
</table>
<h3>Concept Model</h3>
The function output iterator class is a model of <a
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
Iterator</a>.
<h2>Members</h3>
The function output iterator implements the member functions
and operators required of the <a
href="http://www.sgi.com/tech/stl/OutputIterator.html">Output
Iterator</a> concept. In addition it has the following constructor:
<pre>
explicit function_output_iterator(const UnaryFunction& f = UnaryFunction())
</pre>
<br>
<br>
<hr>
<h2><a name="make_function_output_iterator">The Function Output Iterator Object
Generator</a></h2>
The <tt>make_function_output_iterator()</tt> function provides a
more convenient way to create function output iterator objects. The
function saves the user the trouble of explicitly writing out the
iterator types. If the default argument is used, the function
type must be provided as an explicit template argument.
<blockquote>
<pre>
template &lt;class UnaryFunction&gt;
function_output_iterator&lt;UnaryFunction&gt;
make_function_output_iterator(const UnaryFunction&amp; f = UnaryFunction())
</pre>
</blockquote>
<hr>
<p>&copy; Copyright Jeremy Siek 2001. 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.
</body>
</html>

View File

@ -1,37 +1,33 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<title>Generator Iterator Adaptor Documentation</title>
<title>Generator Iterator Adaptor Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<img src="../../boost.png" alt="boost.png (6897 bytes)" align="middle"
width="277" height="86">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">
<h1>Generator Iterator Adaptor</h1>
<h1>Generator Iterator Adaptor</h1>
Defined in header <a href="../../boost/generator_iterator.hpp">boost/generator_iterator.hpp</a>
<p>
The generator iterator adaptor makes it easier to create custom input
iterators from 0-ary functions and function objects. The adaptor
takes a
<a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>
and creates a model of
<a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>.
Each increment retrieves an item from the generator and makes it
available to be retrieved by dereferencing. The motivation for this
iterator is that some concepts can be more naturally expressed as a
generator, while most STL algorithms expect an iterator. An example
is the <a href="../random/index.html">Random Number</a> library.
<p>Defined in header <a href=
"../../boost/generator_iterator.hpp">boost/generator_iterator.hpp</a></p>
<h2>Synopsis</h2>
<p>The generator iterator adaptor makes it easier to create custom input
iterators from 0-ary functions and function objects. The adaptor takes a
<a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a> and
creates a model of <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>. Each
increment retrieves an item from the generator and makes it available to be
retrieved by dereferencing. The motivation for this iterator is that some
concepts can be more naturally expressed as a generator, while most STL
algorithms expect an iterator. An example is the <a href=
"../random/index.html">Random Number</a> library.</p>
<h2>Synopsis</h2>
<blockquote>
<pre>
<blockquote>
<pre>
namespace boost {
template &lt;class Generator&gt;
class generator_iterator_policies;
@ -44,85 +40,87 @@ namespace boost {
make_generator_iterator(Generator &amp; gen);
}
</pre>
</blockquote>
<hr>
</blockquote>
<h2>The Generator Iterator Generator Class</h2>
<hr>
<p>The class generator_iterator_generator is a helper class whose purpose
is to construct a generator iterator type. The template parameter for this
class is the Generator function object type that is being wrapped. The
generator iterator adaptor only holds a reference (or pointer) to the
function object, therefore the function object must outlive the generator
iterator adaptor constructed from it.</p>
<pre>
template &lt;class Generator&gt;
<h2>The Generator Iterator Generator Class</h2>
The class generator_iterator_generator is a helper class whose purpose
is to construct a generator iterator type. The template parameter for
this class is the Generator function object type that is being
wrapped. The generator iterator adaptor only holds a reference (or
pointer) to the function object, therefore the function object must
outlive the generator iterator adaptor constructed from it.
<pre>
template &lt;class Generator>
class generator_iterator_generator
{
public:
typedef <i>unspecified</i> type; // the resulting generator iterator type
typedef <a href="iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt...&gt; type; // the resulting generator iterator type
}
</pre>
<h3>Template Parameters</h3>
<table border summary="">
<tr>
<th>Parameter</th>
<h3>Template Parameters</h3>
<th>Description</th>
</tr>
<table border>
<tr>
<th>Parameter</th>
<th>Description</th>
</tr>
<tr>
<td><tt><a href=
"http://www.sgi.com/tech/stl/Generator.html">Generator</a></tt></td>
<tr>
<td><tt><a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a></tt>
<td>The generator (0-ary function object) type being
wrapped. The return type of the function must be defined as
<tt>Generator::result_type</tt>. The function object must be a model
of
<a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>.
</td>
</table>
<td>The generator (0-ary function object) type being wrapped. The
return type of the function must be defined as
<tt>Generator::result_type</tt>. The function object must be a model of
<a href=
"http://www.sgi.com/tech/stl/Generator.html">Generator</a>.</td>
</tr>
</table>
<h3>Concept Model</h3>
The generator iterator class is a model of
<a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>.
<h3>Concept Model</h3>
<h3>Members</h3>
The generator iterator implements the member functions
and operators required of the
<a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>
concept.
<p>The generator iterator class is a model of <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>.</p>
<br>
<h3>Members</h3>
<hr>
<h2><a name="make_generator_iterator">The Generator Iterator Object Generator</a></h2>
<p>The generator iterator implements the member functions and operators
required of the <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>
concept.<br></p>
<hr>
The <tt>make_generator_iterator()</tt> function provides a
convenient way to create generator iterator objects. The function
saves the user the trouble of explicitly writing out the iterator
types.
<h2><a name="make_generator_iterator" id="make_generator_iterator">The
Generator Iterator Object Generator</a></h2>
<p>The <tt>make_generator_iterator()</tt> function provides a convenient
way to create generator iterator objects. The function saves the user the
trouble of explicitly writing out the iterator types.</p>
<blockquote>
<pre>
<blockquote>
<pre>
template &lt;class Generator&gt;
typename generator_iterator_generator&lt;Generator&gt;::type
make_generator_iterator(Generator &amp; gen);
make_function_output_iterator(Generator &amp; gen);
</pre>
</blockquote>
<hr>
</blockquote>
<h3>Example</h3>
<hr>
<p>The following program shows how <code>generator_iterator</code>
transforms a generator into an input iterator.</p>
<blockquote>
<pre>
#include &lt;iostream&gt;
#include &lt;boost/generator_iterator.hpp&gt;
<h3>Example</h3>
The following program shows how <code>generator_iterator</code>
transforms a generator into an input iterator.
<blockquote>
<pre>
#include &lt;iostream>
#include &lt;boost/generator_iterator.hpp>
class my_generator
{
@ -142,22 +140,11 @@ int main()
std::cout &lt;&lt; *it &lt;&lt; std::endl;
}
</pre>
</blockquote>
<hr>
</blockquote>
<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
"http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01 Transitional"
height="31" width="88"></a></p>
<hr>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
Written by Jens Maurer.
<p><i>Copyright &copy; 2001 <a href=
"../../people/jens_maurer.htm">Jens Maurer</a></i></p>
<p><i>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or
copy at <a href=
"http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>)</i></p>
</body>
</html>

366
half_open_range_test.cpp Normal file
View File

@ -0,0 +1,366 @@
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears in
// all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org for most recent version including documentation.
//
// Revision History
// 11 Feb 2001 Compile with Borland, re-enable failing tests (David Abrahams)
// 29 Jan 2001 Initial revision (David Abrahams)
#include <boost/half_open_range.hpp>
#include <boost/utility.hpp>
#include <iterator>
#include <stdlib.h>
#include <vector>
#include <list>
#include <cassert>
#include <stdexcept>
#ifndef BOOST_NO_LIMITS
# include <limits>
#endif
#ifndef BOOST_NO_SLIST
# include <slist>
#endif
inline unsigned unsigned_random(unsigned max)
{
return (max > 0) ? (unsigned)rand() % max : 0;
}
// Special tests for ranges supporting random access
template <class T>
void category_test_1(
const boost::half_open_range<T>& r, std::random_access_iterator_tag)
{
typedef boost::half_open_range<T> range;
typedef typename range::size_type size_type;
size_type size = r.size();
// pick a random offset
size_type offset = unsigned_random(size);
typename range::value_type x = *(r.begin() + offset);
// test contains(value_type)
assert(r.contains(r.start()) == !r.empty());
assert(!r.contains(r.finish()));
assert(r.contains(x) == (offset != size));
range::const_iterator p = r.find(x);
assert((p == r.end()) == (x == r.finish()));
assert(r.find(r.finish()) == r.end());
if (offset != size)
{
assert(x == r[offset]);
assert(x == r.at(offset));
}
bool caught_out_of_range = false;
try {
bool never_initialized = x == r.at(size);
(void)never_initialized;
}
catch(std::out_of_range&)
{
caught_out_of_range = true;
}
catch(...)
{
}
assert(caught_out_of_range);
}
// Those tests must be skipped for other ranges
template <class T>
void category_test_1(
const boost::half_open_range<T>&, std::forward_iterator_tag)
{
}
unsigned indices[][2] = { {0,0},{0,1},{0,2},{0,3},
{1,1},{1,2},{1,3},
{2,2},{2,3},
{3,3}};
template <class Range>
void category_test_2(
const std::vector<Range>& ranges, unsigned i, unsigned j, std::random_access_iterator_tag)
{
typedef Range range;
const range& ri = ranges[i];
const range& rj = ranges[j];
if (indices[i][0] <= indices[j][0] && indices[i][1] >= indices[j][1])
assert(ri.contains(rj));
if (ri.contains(rj))
assert((ri & rj) == rj);
assert(boost::intersects(ri, rj) == !(ri & rj).empty());
range t1(ri);
t1 &= rj;
assert(t1 == range(indices[i][0] > indices[j][0] ? ri.start() : rj.start(),
indices[i][1] < indices[j][1] ? ri.finish() : rj.finish()));
assert(t1 == (ri & rj));
range t2(ri);
t2 |= rj;
if (ri.empty())
assert(t2 == rj);
else if (rj.empty())
assert(t2 == ri);
else
assert(t2 == range(indices[i][0] < indices[j][0] ? ri.start() : rj.start(),
indices[i][1] > indices[j][1] ? ri.finish() : rj.finish()));
assert(t2 == (ri | rj));
if (i == j)
assert(ri == rj);
if (ri.empty() || rj.empty())
assert((ri == rj) == (ri.empty() && rj.empty()));
else
assert((ri == rj) == (ri.start() == rj.start() && ri.finish() == rj.finish()));
assert((ri == rj) == !(ri != rj));
bool same = ri == rj;
bool one_empty = ri.empty() != rj.empty();
std::less<range> less;
std::less_equal<range> less_equal;
std::greater<range> greater;
std::greater_equal<range> greater_equal;
if (same)
{
assert(greater_equal(ri,rj));
assert(less_equal(ri,rj));
assert(!greater(ri,rj));
assert(!less(ri,rj));
}
else if (one_empty)
{
const range& empty = ri.empty() ? ri : rj;
const range& non_empty = rj.empty() ? ri : rj;
assert(less(empty,non_empty));
assert(less_equal(empty,non_empty));
assert(!greater(empty,non_empty));
assert(!greater_equal(empty,non_empty));
assert(!less(non_empty,empty));
assert(!less_equal(non_empty,empty));
assert(greater(non_empty,empty));
assert(greater_equal(non_empty,empty));
}
else {
if (indices[i][0] < indices[j][0] ||
indices[i][0] == indices[j][0] && indices[i][1] < indices[j][1])
{
assert(!greater_equal(ri,rj));
assert(less(ri,rj));
}
if (indices[i][0] < indices[j][0] ||
indices[i][0] == indices[j][0] && indices[i][1] <= indices[j][1])
{
assert(!greater(ri,rj));
assert(less_equal(ri,rj));
}
if (indices[i][0] > indices[j][0] ||
indices[i][0] == indices[j][0] && indices[i][1] > indices[j][1])
{
assert(!less_equal(ri,rj));
assert(greater(ri,rj));
}
if (indices[i][0] > indices[j][0] ||
indices[i][0] == indices[j][0] && indices[i][1] >= indices[j][1])
{
assert(!less(ri,rj));
assert(greater_equal(ri,rj));
}
}
}
template <class Range>
void category_test_2(
const std::vector<Range>&, unsigned, unsigned, std::forward_iterator_tag)
{
}
template <class T>
void category_test_2(
const std::vector<boost::half_open_range<T> >&, unsigned, unsigned, std::bidirectional_iterator_tag)
{
}
template <class Range>
void test_back(Range& x, std::bidirectional_iterator_tag)
{
assert(x.back() == boost::prior(x.finish()));
}
template <class Range>
void test_back(Range& x, std::forward_iterator_tag)
{
}
template <class T>
boost::half_open_range<T> range_identity(const boost::half_open_range<T>& x)
{
return x;
}
template <class T>
void test(T x0, T x1, T x2, T x3)
{
std::vector<boost::half_open_range<T> > ranges;
typedef boost::half_open_range<T> range;
T bounds[4] = { x0, x1, x2, x3 };
const std::size_t num_ranges = sizeof(indices)/sizeof(*indices);
// test construction
for (std::size_t n = 0; n < num_ranges;++n)
{
T start = bounds[indices[n][0]];
T finish = bounds[indices[n][1]];
boost::half_open_range<T> r(start, finish);
ranges.push_back(r);
}
// test implicit conversion from std::pair<T,T>
range converted = std::pair<T,T>(x0,x0);
(void)converted;
// test assignment, equality and inequality
range r00 = range(x0, x0);
assert(r00 == range(x0,x0));
assert(r00 == range(x1,x1)); // empty ranges are all equal
if (x3 != x0)
assert(r00 != range(x0, x3));
r00 = range(x0, x3);
assert(r00 == range(x0, x3));
if (x3 != x0)
assert(r00 != range(x0, x0));
typedef typename range::iterator iterator;
typedef typename iterator::iterator_category category;
for (unsigned i = 0; i < num_ranges; ++i)
{
const range& r = ranges[i];
// test begin(), end(), basic iteration.
unsigned count = 0;
for (range::const_iterator p = r.begin(), finish = r.end();
p != finish;
++p, ++count)
{
assert(count < 2100);
}
// test size(), empty(), front(), back()
assert((unsigned)r.size() == count);
if (indices[i][0] == indices[i][1])
assert(r.empty());
if (r.empty())
assert(r.size() == 0);
if (!r.empty())
{
assert(r.front() == r.start());
test_back(r, category());
}
// test swap
range r1(r);
range r2(x0,x3);
const bool same = r1 == r2;
r1.swap(r2);
assert(r1 == range(x0,x3));
assert(r2 == r);
if (!same) {
assert(r1 != r);
assert(r2 != range(x0,x3));
}
// do individual tests for random-access iterators
category_test_1(r, category());
}
for (unsigned j = 0; j < num_ranges; ++j) {
for (unsigned k = 0; k < num_ranges; ++k) {
category_test_2(ranges, j, k, category());
}
}
}
template <class Integer>
void test_integer(Integer* = 0) // default arg works around MSVC bug
{
Integer a = 0;
Integer b = a + unsigned_random(128 - a);
Integer c = b + unsigned_random(128 - b);
Integer d = c + unsigned_random(128 - c);
test(a, b, c, d);
}
template <class Container>
void test_container(Container* = 0) // default arg works around MSVC bug
{
Container c(unsigned_random(1673));
const typename Container::size_type offset1 = unsigned_random(c.size());
const typename Container::size_type offset2 = unsigned_random(c.size() - offset1);
typename Container::iterator internal1 = c.begin();
std::advance(internal1, offset1);
typename Container::iterator internal2 = internal1;
std::advance(internal2, offset2);
test(c.begin(), internal1, internal2, c.end());
typedef typename Container::const_iterator const_iterator;
test(const_iterator(c.begin()),
const_iterator(internal1),
const_iterator(internal2),
const_iterator(c.end()));
}
int main()
{
// Test the built-in integer types.
test_integer<char>();
test_integer<unsigned char>();
test_integer<signed char>();
test_integer<wchar_t>();
test_integer<short>();
test_integer<unsigned short>();
test_integer<int>();
test_integer<unsigned int>();
test_integer<long>();
test_integer<unsigned long>();
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
test_integer<long long>();
test_integer<unsigned long long>();
#endif
// Some tests on container iterators, to prove we handle a few different categories
test_container<std::vector<int> >();
test_container<std::list<int> >();
#ifndef BOOST_NO_SLIST
test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
#endif
// Also prove that we can handle raw pointers.
int array[2000];
const std::size_t a = 0;
const std::size_t b = a + unsigned_random(2000 - a);
const std::size_t c = b + unsigned_random(2000 - b);
test(array, array+b, array+c, array+2000);
return 0;
}

View File

@ -1,296 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 5.0::19981217::extensions to HTML 4.0//EN" "hmpro5.dtd">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252">
<TITLE>In_place_factory Documentation</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080">
<H2 align="left"><IMG SRC="../../boost.png" WIDTH="276" HEIGHT="86"></H2>
<blockquote>
<blockquote>
<blockquote>
<blockquote>
<blockquote>
<blockquote>
<H2 align="left">Header &lt;<A
HREF="../../boost/utility/in_place_factory.hpp">boost/utility/in_place_factory.hpp</A>&gt; </H2>
<H2 align="left">Header &lt;<A
HREF="../../boost/utility/typed_in_place_factory.hpp">boost/utility/typed_in_place_factory.hpp</A>&gt; </H2>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
</blockquote>
<p>&nbsp;</p>
<H2>Contents</H2>
<DL CLASS="page-index">
<DT><A HREF="#mot">Motivation</A></DT>
<DT><A HREF="#framework">Framework</A></DT>
<DT><A HREF="#specification">Specification</A></DT>
<DT><A HREF="#container-usage">Container-side Usage</A></DT>
<DT><A HREF="#user-usage">User-side Usage</A></DT>
</DL>
<HR>
<H2><A NAME="mot"></A>Motivation</H2>
<p>Suppose we have a class</p>
<pre>struct X
{
X ( int, std:::string ) ;
} ;</pre>
<p>And a container for it which supports an empty state (that is, which can contain zero objects):</p>
<pre>struct C
{
C() : contained_(0) {}
~C() { delete contained_ ; }
X* contained_ ;
} ;</pre>
<p>A container designed to support an empty state typically doesn't require the contained type to be DefaultConstructible,
but it typically requires it to be CopyConstructible as a mechanism to
initialize the object to store:</p>
<pre>struct C
{
C() : contained_(0) {}
C ( X const& v ) : contained_ ( new X(v) ) {}
~C() { delete contained_ ; }
X* contained_ ;
} ;</pre>
<p>There is a subtle problem with this: since the mechanism used to initialize the stored object is copy construction,
there must exist a previously constructed source object to copy from. This
object is likely to be temporary and serve no purpose besides being the source</p>
<pre>void foo()
{
// Temporary object created.
C c( X(123,"hello") ) ;
}
</pre>
<p>A solution to this problem is to support direct construction of the contained
object right in the container's storage.<br>
In this scheme, the user supplies the arguments for the X constructor
directly to the container:</p>
<pre>struct C
{
C() : contained_(0) {}
C ( X const& v ) : contained_ ( new X(v) ) {}
C ( int a0, std::string a1 ) : contained_ ( new X(a0,a1) ) {}
~C() { delete contained_ ; }
X* contained_ ;
} ;</pre>
<pre>void foo()
{
// Wrapped object constructed in-place
// No temporary created.
C c(123,"hello") ;
}
</pre>
<p>Clearly, this solution doesn't scale well since the container must duplicate all the constructor overloads from the contained type
(at least all those which are to be supported directly in the container).</p>
<H2><A NAME="framework"></A>Framework</H2>
<p>
This library proposes a framework to allow some containers to directly contruct contained objects in-place without requiring
the entire set of constructor overloads ftom the contained type. It also allows the container to remove the CopyConstuctible
requirement from the contained type since objects can be directly constructed in-place without need of a copy.<br>
The only requirement on the container is that it must provide proper storage (that is, correctly aligned and sized).
Naturally, the container will typically support uninitialized storage to avoid the in-place construction to override
a fully-constructed object (as this would defeat the purpose of in-place construction)
</p>
<p>For this purpose, the framework provides two families of classes collectively called: InPlaceFactories and TypedInPlaceFactories.<br>
Essentially, these classes hold a sequence of actual parameters and a method to contruct an object in place using these parameters.
Each member of the family differs only in the number (and type) of the parameter list. The first family
takes the type of the object to construct directly in method provided for that
purpose, whereas the second family incorporates that type in the factory class
itself..</p>
<p>From the container POV, using the framework amounts to calling the factory's method to contruct the object in place.
From the user POV, it amounts to creating the right factory object to hold the parameters and pass it to the container.<br>
The following simplified example shows the basic idea. A complete example follows the formal specification of the framework:</p>
<pre>struct C
{
template&lt;class InPlaceFactory&gt;
C ( InPlaceFactory const& aFactoty )
:
contained_ ( uninitialized_storage() )
{
aFactory.template apply&lt;X&gt;(contained_);
}
~C()
{
contained_ -> X::~X();
delete[] contained_ ;
}
char* uninitialized_storage() { return new char[sizeof(X)] ; }
char* contained_ ;
} ;
void foo()
{
C c( in_place(123,"hello") ) ;
}
</pre>
<HR>
<H2><A NAME="specification">Specification</A></H2>
<p>The following is the first member of the family of 'in_place_factory' classes, along with its corresponding helper template function.
The rest of the family varies only in the number and type of template (and constructor) parameters.</p>
<PRE>namespace boost {
struct in_place_factory_base {} ;
template&lt;class A0&gt;
class in_place_factory : public in_place_factory_base
{
public:</PRE>
<PRE> in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
template&lt; class T &gt;
void apply ( void* address ) const
{
new (address) T(m_a0);
}
private:</PRE>
<PRE> A0 const& m_a0 ;
} ;
template&lt;class A0&gt;
in_place_factory&lt;A0&gt; in_place ( A0 const& a0 )
{
return in_place_factory&lt;A0&gt;(a0);
}
</PRE>
<p>Similarly, the following is the first member of the family of 'typed_in_place_factory' classes, along with its corresponding
helper template function. The rest of the family varies only in the number and type of template (and constructor) parameters.</p>
<PRE>namespace boost {
struct typed_in_place_factory_base {} ;
template&lt;class T, class A0&gt;
class typed_in_place_factory : public typed_in_place_factory_base
{
public:</PRE>
<PRE> typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
void apply ( void* address ) const
{
new (address) T(m_a0);
}
private:</PRE>
<PRE> A0 const& m_a0 ;
} ;
template&lt;class T, class A0&gt;
typed_in_place_factory&lt;A0&gt; in_place ( A0 const& a0 )
{
return typed_in_place_factory&lt;T,A0&gt;(a0);
}</PRE>
<PRE>}
</PRE>
<p>As you can see, the 'in_place_factory' and 'typed_in_place_factory' template classes varies only in the way they specify
the target type: in the first family, the type is given as a template argument to the apply member function while in the
second it is given directly as part of the factory class.<br>
When the container holds a unique non-polymorphic type (such as the case of Boost.Optional), it knows the exact dynamic-type
of the contained object and can pass it to the apply() method of a (non-typed) factory.
In this case, end users can use an 'in_place_factory' instance which can be constructed without the type of the object to construct.<br>
However, if the container holds heterogeneous or polymorphic objects (such as the case of Boost.Variant), the dynamic-type
of the object to be constructed must be known by the factory itslef. In this case, end users must use a 'typed_in_place_factory'
instead.</p>
<HR>
<h2><A NAME="container-usage">Container-side Usage</a></h2>
<p>As shown in the introductory simplified example, the container class must
contain methods that accept an instance of
these factories and pass the object's storage to the factory's apply method.<br>
However, the type of the factory class cannot be completly specified in the container class because that would
defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list
for the constructor of its contained object.<br>
The correct function overload must be based on the only distinctive and common
characteristic of all the classes in each family, the base class.<br>
Depending on the container class, you can use 'enable_if' to generate the right overload, or use the following
dispatch technique (used in the Boost.Optional class):
</p>
<pre>struct C
{
C() : contained_(0) {}
C ( X const& v ) : contained_ ( new X(v) ) {}
template&lt;class Expr&gt
C ( Expr const& expr )
:
contained_ ( uninitialized_storage() )
{
construct(expr,&expr)
}
~C() { delete contained_ ; }
template&lt;class InPlaceFactory&gt;
void construct ( InPlaceFactory const& aFactory, boost::in_place_factory_base* )
{
aFactory.template apply&lt;X&gt;(contained_);
}
template&lt;class TypedInPlaceFactory&gt;
void construct ( TypedInPlaceFactory const& aFactory, boost::typed_in_place_factory_base* )
{
aFactory.apply(contained_);
}
X* uninitialized_storage() { return static_cast&lt;X*&gt;(new char[sizeof(X)]) ; }
X* contained_ ;
} ;
</pre>
<hr>
<h2><A NAME="user-usage">User-side Usage</a></h2>
<p>End users pass to the container an instance of a factory object holding the actual parameters needed to construct the
contained object directly within the container. For this, the helper template function 'in_place' is used.<br>
The call 'in_place(a0,a1,a2,...,an)' constructs a (non-typed) 'in_place_factory' instance with the given argument list.<br>
The call 'in_place&lt;T&gt;(a0,a1,a2,...,an)' constructs a 'typed_in_place_factory' instance with the given argument list for the
type 'T'.</p>
<pre>void foo()
{
C a( in_place(123,"hello") ) ; // in_place_factory passed
C b( in_place&lt;X&gt;(456,"world") ) ; // typed_in_place_factory passed
}
</pre>
<P>Revised September 17, 2004</P>
<p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2004</p>
<p> Use, modification, and distribution are subject to the Boost Software
License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
www.boost.org/LICENSE_1_0.txt</a>)</p>
<P>Developed by <A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>,
the latest version of this file can be found at <A
HREF="http://www.boost.org">www.boost.org</A>, and the boost
<A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P>
</BODY>
</HTML>

View File

@ -1,37 +1,52 @@
#ifndef BOOST_ASSERT_HPP_INCLUDED
#define BOOST_ASSERT_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/assert.hpp - BOOST_ASSERT(expr)
// boost/assert.hpp
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// Note: There are no include guards. This is intentional.
//
// See http://www.boost.org/libs/utility/assert.html for documentation.
// 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.
//
#undef BOOST_ASSERT
//
// When BOOST_DEBUG is not defined, it defaults to 0 (off)
// for compatibility with programs that do not expect asserts
// in the smart pointer class templates.
//
// This default may be changed after an initial transition period.
//
#if defined(BOOST_DISABLE_ASSERTS)
#ifndef BOOST_DEBUG
#define BOOST_DEBUG 0
#endif
# define BOOST_ASSERT(expr) ((void)0)
#if BOOST_DEBUG
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
#include <assert.h>
#ifndef BOOST_ASSERT
#include <boost/current_function.hpp>
namespace boost
{
bool boost_error(char const * expr, char const * func, char const * file, long line);
void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
# define BOOST_ASSERT(expr) ((expr) || !boost_error(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__) || (assert(expr), true))
} // namespace boost
#endif // #ifndef BOOST_ASSERT
#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#else // #if BOOST_DEBUG
#else
# include <assert.h> // .h to support old libraries w/o <cassert> - effect is the same
# define BOOST_ASSERT(expr) assert(expr)
#endif
#undef BOOST_ASSERT
#define BOOST_ASSERT(expr) ((void)0)
#endif // #if BOOST_DEBUG
#endif // #ifndef BOOST_ASSERT_HPP_INCLUDED

View File

@ -1,10 +1,9 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// See http://www.boost.org/libs/utility for most recent version including documentation.
// (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// See http://www.boost.org for most recent version including documentation.
// See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp
// for full copyright notices.

View File

@ -1,24 +1,19 @@
#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
#define BOOST_CHECKED_DELETE_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/checked_delete.hpp
//
// Copyright (c) 2002, 2003 Peter Dimov
// Copyright (c) 2003 Daniel Frey
// Copyright (c) 2003 Howard Hinnant
// Copyright (c) 1999, 2000, 2001, 2002 boost.org
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/utility/checked_delete.html for documentation.
// 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.
//
namespace boost
@ -26,18 +21,15 @@ namespace boost
// verify that types are complete for increased safety
template<class T> inline void checked_delete(T * x)
template< typename T > inline void checked_delete(T * x)
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
typedef char type_must_be_complete[sizeof(T)];
delete x;
}
template<class T> inline void checked_array_delete(T * x)
template< typename T > inline void checked_array_delete(T * x)
{
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
typedef char type_must_be_complete[sizeof(T)];
delete [] x;
}
@ -46,10 +38,9 @@ template<class T> struct checked_deleter
typedef void result_type;
typedef T * argument_type;
void operator()(T * x) const
void operator()(T * x)
{
// boost:: disables ADL
boost::checked_delete(x);
checked_delete(x);
}
};
@ -58,9 +49,9 @@ template<class T> struct checked_array_deleter
typedef void result_type;
typedef T * argument_type;
void operator()(T * x) const
void operator()(T * x)
{
boost::checked_array_delete(x);
checked_array_delete(x);
}
};

View File

@ -1,10 +1,9 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// See http://www.boost.org/libs/utility for most recent version including documentation.
// (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// See http://www.boost.org for most recent version including documentation.
// See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp
// for full copyright notices.

View File

@ -1,10 +1,8 @@
#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED
// MS compatible compilers support #pragma once
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#if _MSC_VER >= 1020
#pragma once
#endif
//
@ -12,11 +10,10 @@
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// http://www.boost.org/libs/utility/current_function.html
// 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.
//
namespace boost
@ -28,11 +25,7 @@ namespace detail
inline void current_function_helper()
{
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600))
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
#elif defined(__DMC__) && (__DMC__ >= 0x810)
#if defined(__GNUC__)
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
@ -40,11 +33,7 @@ inline void current_function_helper()
# define BOOST_CURRENT_FUNCTION __FUNCSIG__
#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
# define BOOST_CURRENT_FUNCTION __FUNCTION__
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
#elif defined(__BORLANDC__)
# define BOOST_CURRENT_FUNCTION __FUNC__

View File

@ -1,9 +1,10 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// See http://www.boost.org/libs/utility for most recent version including documentation.
// 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.
// call_traits: defines typedefs for function usage
// (see libs/utility/call_traits.htm)
@ -21,11 +22,13 @@
#ifndef BOOST_CONFIG_HPP
#include <boost/config.hpp>
#endif
#include <cstddef>
#include <boost/type_traits/is_arithmetic.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/detail/workaround.hpp>
#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP
#include <boost/type_traits/arithmetic_traits.hpp>
#endif
#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP
#include <boost/type_traits/composite_traits.hpp>
#endif
namespace boost{
@ -58,7 +61,7 @@ struct ct_imp<T, isp, true>
template <typename T, bool b1>
struct ct_imp<T, true, b1>
{
typedef const T param_type;
typedef T const param_type;
};
}
@ -76,7 +79,7 @@ public:
// however compiler bugs prevent this - instead pass three bool's to
// ct_imp<T,bool,bool,bool> and add an extra partial specialisation
// of ct_imp to handle the logic. (JM)
typedef typename boost::detail::ct_imp<
typedef typename detail::ct_imp<
T,
::boost::is_pointer<T>::value,
::boost::is_arithmetic<T>::value
@ -92,7 +95,7 @@ struct call_traits<T&>
typedef T& param_type; // hh removed const
};
#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x581 ) )
#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x551)
// these are illegal specialisations; cv-qualifies applied to
// references have no effect according to [8.3.2p1],
// C++ Builder requires them though as it treats cv-qualified
@ -121,17 +124,8 @@ struct call_traits<T&const volatile>
typedef const T& const_reference;
typedef T& param_type; // hh removed const
};
template <typename T>
struct call_traits< T * >
{
typedef T * value_type;
typedef T * & reference;
typedef T * const & const_reference;
typedef T * const param_type; // hh removed const
};
#endif
#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)
#ifndef __SUNPRO_CC
template <typename T, std::size_t N>
struct call_traits<T [N]>
{

View File

@ -1,16 +1,14 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// See http://www.boost.org/libs/utility for most recent version including documentation.
// 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.
// compressed_pair: pair that "compresses" empty members
// (see libs/utility/compressed_pair.htm)
//
// JM changes 25 Jan 2004:
// For the case where T1 == T2 and both are empty, then first() and second()
// should return different objects.
// JM changes 25 Jan 2000:
// Removed default arguments from compressed_pair_switch to get
// C++ Builder 4 to accept them
@ -21,16 +19,16 @@
#define BOOST_DETAIL_COMPRESSED_PAIR_HPP
#include <algorithm>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/is_empty.hpp>
#include <boost/type_traits/is_same.hpp>
#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
#include <boost/type_traits/object_traits.hpp>
#endif
#ifndef BOOST_SAME_TRAITS_HPP
#include <boost/type_traits/same_traits.hpp>
#endif
#ifndef BOOST_CALL_TRAITS_HPP
#include <boost/call_traits.hpp>
#endif
#ifdef BOOST_MSVC
# pragma warning(push)
# pragma warning(disable:4512)
#endif
namespace boost
{
@ -136,7 +134,7 @@ namespace details
template <class T1, class T2>
class compressed_pair_imp<T1, T2, 1>
: protected ::boost::remove_cv<T1>::type
: private T1
{
public:
typedef T1 first_type;
@ -178,7 +176,7 @@ namespace details
template <class T1, class T2>
class compressed_pair_imp<T1, T2, 2>
: protected ::boost::remove_cv<T2>::type
: private T2
{
public:
typedef T1 first_type;
@ -221,8 +219,8 @@ namespace details
template <class T1, class T2>
class compressed_pair_imp<T1, T2, 3>
: protected ::boost::remove_cv<T1>::type,
protected ::boost::remove_cv<T2>::type
: private T1,
private T2
{
public:
typedef T1 first_type;
@ -257,14 +255,11 @@ namespace details
// JM
// 4 T1 == T2, T1 and T2 both empty
// Originally this did not store an instance of T2 at all
// but that led to problems beause it meant &x.first() == &x.second()
// which is not true for any other kind of pair, so now we store an instance
// of T2 just in case the user is relying on first() and second() returning
// different objects (albeit both empty).
// Note does not actually store an instance of T2 at all -
// but reuses T1 base class for both first() and second().
template <class T1, class T2>
class compressed_pair_imp<T1, T2, 4>
: protected ::boost::remove_cv<T1>::type
: private T1
{
public:
typedef T1 first_type;
@ -278,21 +273,20 @@ namespace details
compressed_pair_imp() {}
compressed_pair_imp(first_param_type x, second_param_type y)
: first_type(x), m_second(y) {}
compressed_pair_imp(first_param_type x, second_param_type)
: first_type(x) {}
compressed_pair_imp(first_param_type x)
: first_type(x), m_second(x) {}
: first_type(x) {}
first_reference first() {return *this;}
first_const_reference first() const {return *this;}
second_reference second() {return m_second;}
second_const_reference second() const {return m_second;}
second_reference second() {return *this;}
second_const_reference second() const {return *this;}
void swap(::boost::compressed_pair<T1,T2>&) {}
private:
T2 m_second;
};
// 5 T1 == T2 and are not empty: //JM
@ -435,9 +429,7 @@ swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
} // boost
#ifdef BOOST_MSVC
# pragma warning(pop)
#endif
#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP

View File

@ -1,9 +1,10 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// See http://www.boost.org/libs/utility for most recent version including documentation.
// 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.
//
// Crippled version for crippled compilers:
// see libs/utility/call_traits.htm
@ -97,21 +98,21 @@ struct call_traits_chooser<false, false, true>
template <bool size_is_small>
struct call_traits_sizeof_chooser2
{
template <class T>
struct small_rebind
{
typedef simple_call_traits<T> small_type;
};
template <class T>
struct small_rebind
{
typedef simple_call_traits<T> small_type;
};
};
template<>
struct call_traits_sizeof_chooser2<false>
{
template <class T>
struct small_rebind
{
typedef standard_call_traits<T> small_type;
};
template <class T>
struct small_rebind
{
typedef standard_call_traits<T> small_type;
};
};
template <>
@ -120,10 +121,10 @@ struct call_traits_chooser<false, true, false>
template <class T>
struct rebind
{
enum { sizeof_choice = (sizeof(T) <= sizeof(void*)) };
typedef call_traits_sizeof_chooser2<(sizeof(T) <= sizeof(void*))> chooser;
typedef typename chooser::template small_rebind<T> bound_type;
typedef typename bound_type::small_type type;
enum { sizeof_choice = (sizeof(T) <= sizeof(void*)) };
typedef call_traits_sizeof_chooser2<(sizeof(T) <= sizeof(void*))> chooser;
typedef typename chooser::template small_rebind<T> bound_type;
typedef typename bound_type::small_type type;
};
};
@ -137,8 +138,8 @@ private:
::boost::is_arithmetic<T>::value,
::boost::is_reference<T>::value
> chooser;
typedef typename chooser::template rebind<T> bound_type;
typedef typename bound_type::type call_traits_type;
typedef typename chooser::template rebind<T> bound_type;
typedef typename bound_type::type call_traits_type;
public:
typedef typename call_traits_type::value_type value_type;
typedef typename call_traits_type::reference reference;

View File

@ -1,9 +1,10 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
// Use, modification and distribution are subject to the Boost Software License,
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt).
//
// See http://www.boost.org/libs/utility for most recent version including documentation.
// Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// See http://www.boost.org for most recent version including documentation.
// see libs/utility/compressed_pair.hpp
//
/* Release notes:
@ -167,7 +168,7 @@ public:
compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
: T2(x.second()), _first(x.first()) {}
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
#ifdef BOOST_MSVC
// Total weirdness. If the assignment to _first is moved after
// the call to the inherited operator=, then this breaks graph/test/graph.cpp
// by way of iterator_adaptor.
@ -292,24 +293,22 @@ public:
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_4() : T1() {}
compressed_pair_4(first_param_type x, second_param_type y) : T1(x), m_second(y) {}
compressed_pair_4(first_param_type x, second_param_type) : T1(x) {}
// only one single argument constructor since T1 == T2
explicit compressed_pair_4(first_param_type x) : T1(x), m_second(x) {}
explicit compressed_pair_4(first_param_type x) : T1(x) {}
compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
: T1(x.first()), m_second(x.second()) {}
: T1(x.first()){}
first_reference first() { return *this; }
first_const_reference first() const { return *this; }
second_reference second() { return m_second; }
second_const_reference second() const { return m_second; }
second_reference second() { return *this; }
second_const_reference second() const { return *this; }
void swap(compressed_pair_4& y)
{
// no need to swap empty base classes:
}
private:
T2 m_second;
};
// T1 == T2, not empty

View File

@ -1,75 +1,68 @@
// (C) Copyright Jens Maurer 2001.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright Jens Maurer 2001. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
//
// Revision History:
// 15 Nov 2001 Jens Maurer
// created.
// See http://www.boost.org/libs/utility/iterator_adaptors.htm for documentation.
#ifndef BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
#define BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator_adaptors.hpp>
#include <boost/ref.hpp>
namespace boost {
template<class Generator>
class generator_iterator
: public iterator_facade<
generator_iterator<Generator>
, typename Generator::result_type
, single_pass_traversal_tag
, typename Generator::result_type const&
>
class generator_iterator_policies
{
typedef iterator_facade<
generator_iterator<Generator>
, typename Generator::result_type
, single_pass_traversal_tag
, typename Generator::result_type const&
> super_t;
public:
generator_iterator() {}
generator_iterator(Generator* g) : m_g(g), m_value((*m_g)()) {}
public:
generator_iterator_policies() { }
void increment()
{
m_value = (*m_g)();
template<class Base>
void initialize(Base& base) {
m_value = (*base)();
}
// The Iter template argument is necessary for compatibility with a MWCW
// bug workaround
template <class IteratorAdaptor>
void increment(IteratorAdaptor& iter) {
m_value = (*iter.base())();
}
template <class IteratorAdaptor>
const typename Generator::result_type&
dereference() const
{
return m_value;
}
dereference(const IteratorAdaptor&) const
{ return m_value; }
bool equal(generator_iterator const& y) const
{
return this->m_g == y.m_g && this->m_value == y.m_value;
}
template <class IteratorAdaptor1, class IteratorAdaptor2>
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
{ return x.base() == y.base() &&
x.policies().m_value == y.policies().m_value; }
private:
Generator* m_g;
typename Generator::result_type m_value;
private:
typename Generator::result_type m_value;
};
template<class Generator>
struct generator_iterator_generator
{
typedef generator_iterator<Generator> type;
typedef iterator_adaptor<Generator*, generator_iterator_policies<Generator>,
typename Generator::result_type, const typename Generator::result_type&,
const typename Generator::result_type*, std::input_iterator_tag,
long> type;
};
template <class Generator>
inline generator_iterator<Generator>
inline typename generator_iterator_generator<Generator>::type
make_generator_iterator(Generator & gen)
{
typedef generator_iterator<Generator> result_t;
typedef typename generator_iterator_generator<Generator>::type result_t;
return result_t(&gen);
}

View File

@ -1,51 +0,0 @@
// Boost next_prior.hpp header file ---------------------------------------//
// (C) Copyright Dave Abrahams and Daniel Walker 1999-2003. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/utility for documentation.
// Revision History
// 13 Dec 2003 Added next(x, n) and prior(x, n) (Daniel Walker)
#ifndef BOOST_NEXT_PRIOR_HPP_INCLUDED
#define BOOST_NEXT_PRIOR_HPP_INCLUDED
#include <iterator>
namespace boost {
// Helper functions for classes like bidirectional iterators not supporting
// operator+ and operator-
//
// Usage:
// const std::list<T>::iterator p = get_some_iterator();
// const std::list<T>::iterator prev = boost::prior(p);
// const std::list<T>::iterator next = boost::next(prev, 2);
// Contributed by Dave Abrahams
template <class T>
inline T next(T x) { return ++x; }
template <class T, class Distance>
inline T next(T x, Distance n)
{
std::advance(x, n);
return x;
}
template <class T>
inline T prior(T x) { return --x; }
template <class T, class Distance>
inline T prior(T x, Distance n)
{
std::advance(x, -n);
return x;
}
} // namespace boost
#endif // BOOST_NEXT_PRIOR_HPP_INCLUDED

View File

@ -1,36 +0,0 @@
// Boost noncopyable.hpp header file --------------------------------------//
// (C) Copyright Beman Dawes 1999-2003. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/utility for documentation.
#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
#define BOOST_NONCOPYABLE_HPP_INCLUDED
namespace boost {
// Private copy constructor and copy assignment ensure classes derived from
// class noncopyable cannot be copied.
// Contributed by Dave Abrahams
namespace noncopyable_ // protection from unintended ADL
{
class noncopyable
{
protected:
noncopyable() {}
~noncopyable() {}
private: // emphasize the following members are private
noncopyable( const noncopyable& );
const noncopyable& operator=( const noncopyable& );
};
}
typedef noncopyable_::noncopyable noncopyable;
} // namespace boost
#endif // BOOST_NONCOPYABLE_HPP_INCLUDED

View File

@ -1,18 +1,14 @@
// Boost operators.hpp header file ----------------------------------------//
// (C) Copyright David Abrahams, Jeremy Siek, Daryle Walker 1999-2001.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-2001.
// Permission to copy, use, modify, sell and distribute this software is
// granted provided this copyright notice appears in all copies. This
// software is provided "as is" without express or implied warranty, and
// with no claim as to its suitability for any purpose.
// See http://www.boost.org/libs/utility/operators.htm for documentation.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 24 May 07 Changed empty_base to depend on T, see
// http://svn.boost.org/trac/boost/ticket/979
// 21 Oct 02 Modified implementation of operators to allow compilers with a
// correct named return value optimization (NRVO) to produce optimal
// code. (Daniel Frey)
// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
// 27 Aug 01 'left' form for non commutative operators added;
@ -79,10 +75,9 @@
#include <boost/config.hpp>
#include <boost/iterator.hpp>
#include <boost/detail/workaround.hpp>
#if defined(__sgi) && !defined(__GNUC__)
# pragma set woff 1234
#pragma set woff 1234
#endif
#if defined(BOOST_MSVC)
@ -92,14 +87,14 @@
namespace boost {
namespace detail {
template <typename T> class empty_base {
// Helmut Zeisel, empty base class optimization bug with GCC 3.0.0
#if defined(__GNUC__) && __GNUC__==3 && __GNUC_MINOR__==0 && __GNU_PATCHLEVEL__==0
class empty_base {
bool dummy;
#endif
};
#else
class empty_base {};
#endif
} // namespace detail
} // namespace boost
@ -121,7 +116,7 @@ namespace boost
// 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<T> >
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); }
@ -132,7 +127,7 @@ struct less_than_comparable2 : B
friend bool operator>=(const U& x, const T& y) { return !(y > x); }
};
template <class T, class B = ::boost::detail::empty_base<T> >
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; }
@ -140,7 +135,7 @@ struct less_than_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<T> >
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; }
@ -148,142 +143,157 @@ struct equality_comparable2 : B
friend bool operator!=(const T& y, const U& x) { return !(y == x); }
};
template <class T, class B = ::boost::detail::empty_base<T> >
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); }
};
// A macro which produces "name_2left" from "name".
#define BOOST_OPERATOR2_LEFT(name) name##2##_##left
// NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
// This is the optimal implementation for ISO/ANSI C++,
// but it requires the compiler to implement the NRVO.
// If the compiler has no NRVO, this is the best symmetric
// implementation available.
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
friend T operator OP( const U& lhs, const T& rhs ) \
{ T nrv( rhs ); nrv OP##= lhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
template <class T, class U, class B = ::boost::detail::empty_base>
struct multipliable2 : B
{
friend T operator*(T x, const U& y) { return x *= y; }
friend T operator*(const U& y, T x) { return x *= y; }
};
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct BOOST_OPERATOR2_LEFT(NAME) : B \
{ \
friend T operator OP( const U& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
template <class T, class B = ::boost::detail::empty_base>
struct multipliable1 : B
{
friend T operator*(T x, const T& y) { return x *= y; }
};
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
// For compilers without NRVO the following code is optimal, but not
// symmetric! Note that the implementation of
// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
// optimization opportunities to the compiler :)
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
template <class T, class U, class B = ::boost::detail::empty_base>
struct addable2 : B
{
friend T operator+(T x, const U& y) { return x += y; }
friend T operator+(const U& y, T x) { return x += y; }
};
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
}; \
\
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct BOOST_OPERATOR2_LEFT(NAME) : B \
{ \
friend T operator OP( const U& lhs, const T& rhs ) \
{ return T( lhs ) OP##= rhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
template <class T, class B = ::boost::detail::empty_base>
struct addable1 : B
{
friend T operator+(T x, const T& y) { return x += y; }
};
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
template <class T, class U, class B = ::boost::detail::empty_base>
struct subtractable2 : B
{
friend T operator-(T x, const U& y) { return x -= y; }
};
BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
template <class T, class U, class B = ::boost::detail::empty_base>
struct subtractable2_left : B
{
friend T operator-(const U& x, const T& y)
{ T result(x); return result -= y; }
};
#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
#undef BOOST_OPERATOR2_LEFT
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 U, class B = ::boost::detail::empty_base>
struct dividable2_left : B
{
friend T operator/(const U& x, const T& y)
{ T result(x); return result /= 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 U, class B = ::boost::detail::empty_base>
struct modable2_left : B
{
friend T operator%(const U& x, const T& y)
{ T result(x); return result %= 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<T> >
template <class T, class B = ::boost::detail::empty_base>
struct incrementable : B
{
friend T operator++(T& x, int)
{
incrementable_type nrv(x);
incrementable_type tmp(x);
++x;
return nrv;
return tmp;
}
private: // The use of this typedef works around a Borland bug
typedef T incrementable_type;
};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct decrementable : B
{
friend T operator--(T& x, int)
{
decrementable_type nrv(x);
decrementable_type tmp(x);
--x;
return nrv;
return tmp;
}
private: // The use of this typedef works around a Borland bug
typedef T decrementable_type;
@ -291,7 +301,7 @@ private: // The use of this typedef works around a Borland bug
// Iterator operator classes (contributed by Jeremy Siek) ------------------//
template <class T, class P, class B = ::boost::detail::empty_base<T> >
template <class T, class P, class B = ::boost::detail::empty_base>
struct dereferenceable : B
{
P operator->() const
@ -300,7 +310,7 @@ struct dereferenceable : B
}
};
template <class T, class I, class R, class B = ::boost::detail::empty_base<T> >
template <class T, class I, class R, class B = ::boost::detail::empty_base>
struct indexable : B
{
R operator[](I n) const
@ -310,48 +320,32 @@ struct indexable : B
};
// More operator classes (contributed by Daryle Walker) --------------------//
// (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
template <class T, class U, class B = ::boost::detail::empty_base>
struct left_shiftable2 : B
{
friend T operator<<(T x, const U& y) { return x <<= y; }
};
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base<T> > \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
template <class T, class B = ::boost::detail::empty_base>
struct left_shiftable1 : B
{
friend T operator<<(T x, const T& y) { return x <<= y; }
};
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
template <class T, class U, class B = ::boost::detail::empty_base>
struct right_shiftable2 : B
{
friend T operator>>(T x, const U& y) { return x >>= y; }
};
BOOST_BINARY_OPERATOR( left_shiftable, << )
BOOST_BINARY_OPERATOR( right_shiftable, >> )
template <class T, class B = ::boost::detail::empty_base>
struct right_shiftable1 : B
{
friend T operator>>(T x, const T& y) { return x >>= y; }
};
#undef BOOST_BINARY_OPERATOR
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct equivalent2 : B
{
friend bool operator==(const T& x, const U& y)
@ -360,7 +354,7 @@ struct equivalent2 : B
}
};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct equivalent1 : B
{
friend bool operator==(const T&x, const T&y)
@ -369,7 +363,7 @@ struct equivalent1 : B
}
};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct partially_ordered2 : B
{
friend bool operator<=(const T& x, const U& y)
@ -386,7 +380,7 @@ struct partially_ordered2 : B
{ return (y < x) || (y == x); }
};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct partially_ordered1 : B
{
friend bool operator>(const T& x, const T& y)
@ -399,161 +393,161 @@ struct partially_ordered1 : B
// Combined operator classes (contributed by Daryle Walker) ----------------//
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct totally_ordered2
: less_than_comparable2<T, U
, equality_comparable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct totally_ordered1
: less_than_comparable1<T
, equality_comparable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct additive2
: addable2<T, U
, subtractable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct additive1
: addable1<T
, subtractable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct multiplicative2
: multipliable2<T, U
, dividable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct multiplicative1
: multipliable1<T
, dividable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct integer_multiplicative2
: multiplicative2<T, U
, modable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct integer_multiplicative1
: multiplicative1<T
, modable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct arithmetic2
: additive2<T, U
, multiplicative2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct arithmetic1
: additive1<T
, multiplicative1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct integer_arithmetic2
: additive2<T, U
, integer_multiplicative2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct integer_arithmetic1
: additive1<T
, integer_multiplicative1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct bitwise2
: xorable2<T, U
, andable2<T, U
, orable2<T, U, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct bitwise1
: xorable1<T
, andable1<T
, orable1<T, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct unit_steppable
: incrementable<T
, decrementable<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct shiftable2
: left_shiftable2<T, U
, right_shiftable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct shiftable1
: left_shiftable1<T
, right_shiftable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct ring_operators2
: additive2<T, U
, subtractable2_left<T, U
, multipliable2<T, U, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct ring_operators1
: additive1<T
, multipliable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct ordered_ring_operators2
: ring_operators2<T, U
, totally_ordered2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct ordered_ring_operators1
: ring_operators1<T
, totally_ordered1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct field_operators2
: ring_operators2<T, U
, dividable2<T, U
, dividable2_left<T, U, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct field_operators1
: ring_operators1<T
, dividable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct ordered_field_operators2
: field_operators2<T, U
, totally_ordered2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct ordered_field_operators1
: field_operators1<T
, totally_ordered1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct euclidian_ring_operators2
: ring_operators2<T, U
, dividable2<T, U
@ -562,43 +556,43 @@ struct euclidian_ring_operators2
, modable2_left<T, U, B
> > > > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct euclidian_ring_operators1
: ring_operators1<T
, dividable1<T
, modable1<T, B
> > > {};
template <class T, class U, class B = ::boost::detail::empty_base<T> >
template <class T, class U, class B = ::boost::detail::empty_base>
struct ordered_euclidian_ring_operators2
: totally_ordered2<T, U
, euclidian_ring_operators2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct ordered_euclidian_ring_operators1
: totally_ordered1<T
, euclidian_ring_operators1<T, B
> > {};
template <class T, class P, class B = ::boost::detail::empty_base<T> >
template <class T, class P, class B = ::boost::detail::empty_base>
struct input_iteratable
: equality_comparable1<T
, incrementable<T
, dereferenceable<T, P, B
> > > {};
template <class T, class B = ::boost::detail::empty_base<T> >
template <class T, class B = ::boost::detail::empty_base>
struct output_iteratable
: incrementable<T, B
> {};
template <class T, class P, class B = ::boost::detail::empty_base<T> >
template <class T, class P, class B = ::boost::detail::empty_base>
struct forward_iteratable
: input_iteratable<T, P, B
> {};
template <class T, class P, class B = ::boost::detail::empty_base<T> >
template <class T, class P, class B = ::boost::detail::empty_base>
struct bidirectional_iteratable
: forward_iteratable<T, P
, decrementable<T, B
@ -608,7 +602,7 @@ struct bidirectional_iteratable
// which is an indirect base class of bidirectional_iterable,
// random_access_iteratable must not be derived from totally_ordered1
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base<T> >
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base>
struct random_access_iteratable
: bidirectional_iteratable<T, P
, less_than_comparable1<T
@ -652,20 +646,20 @@ struct random_access_iteratable
// Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
// from working, we are forced to use inheritance for that compiler.
# define BOOST_IMPORT_TEMPLATE4(template_name) \
template <class T, class U, class V, class W, class B = ::boost::detail::empty_base<T> > \
# define BOOST_IMPORT_TEMPLATE4(template_name) \
template <class T, class U, class V, class W, class B = ::boost::detail::empty_base> \
struct template_name : ::template_name<T, U, V, W, B> {};
# define BOOST_IMPORT_TEMPLATE3(template_name) \
template <class T, class U, class V, class B = ::boost::detail::empty_base<T> > \
# define BOOST_IMPORT_TEMPLATE3(template_name) \
template <class T, class U, class V, class B = ::boost::detail::empty_base> \
struct template_name : ::template_name<T, U, V, B> {};
# define BOOST_IMPORT_TEMPLATE2(template_name) \
template <class T, class U, class B = ::boost::detail::empty_base<T> > \
# 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<T> > \
# define BOOST_IMPORT_TEMPLATE1(template_name) \
template <class T, class B = ::boost::detail::empty_base> \
struct template_name : ::template_name<T, B> {};
# endif // BOOST_NO_USING_TEMPLATE
@ -676,7 +670,7 @@ struct random_access_iteratable
// 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
// necessary.
// neccessary.
//
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
@ -701,7 +695,7 @@ template<class T> struct is_chained_base {
} // namespace boost
// Import a 4-type-argument operator template into boost (if necessary) and
// Import a 4-type-argument operator template into boost (if neccessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
BOOST_IMPORT_TEMPLATE4(template_name4) \
@ -710,7 +704,7 @@ template<class T> struct is_chained_base {
typedef ::boost::detail::true_t value; \
};
// Import a 3-type-argument operator template into boost (if necessary) and
// Import a 3-type-argument operator template into boost (if neccessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
BOOST_IMPORT_TEMPLATE3(template_name3) \
@ -719,7 +713,7 @@ template<class T> struct is_chained_base {
typedef ::boost::detail::true_t value; \
};
// Import a 2-type-argument operator template into boost (if necessary) and
// 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) \
@ -728,7 +722,7 @@ template<class T> struct is_chained_base {
typedef ::boost::detail::true_t value; \
};
// Import a 1-type-argument operator template into boost (if necessary) and
// 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) \
@ -754,7 +748,7 @@ template<class T> struct is_chained_base {
# define BOOST_OPERATOR_TEMPLATE(template_name) \
template <class T \
,class U = T \
,class B = ::boost::detail::empty_base<T> \
,class B = ::boost::detail::empty_base \
,class O = typename is_chained_base<U>::value \
> \
struct template_name : template_name##2<T, U, B> {}; \
@ -790,7 +784,7 @@ BOOST_OPERATOR_TEMPLATE1(template_name##1)
// 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<T> > \
template <class T, class B = ::boost::detail::empty_base> \
struct template_name : template_name##1<T, B> {};
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION

View File

@ -1,27 +1,23 @@
#ifndef BOOST_REF_HPP_INCLUDED
#define BOOST_REF_HPP_INCLUDED
# define BOOST_REF_HPP_INCLUDED
// MS compatible compilers support #pragma once
# if _MSC_VER+0 >= 1020
# pragma once
# endif
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
# pragma once
#endif
#include <boost/config.hpp>
#include <boost/utility/addressof.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/detail/workaround.hpp>
# include <boost/config.hpp>
//
// ref.hpp - ref/cref, useful helper functions
//
// Copyright (C) 1999, 2000 Jaakko J<>rvi (jaakko.jarvi@cs.utu.fi)
// Copyright (C) 2001, 2002 Peter Dimov
// Copyright (C) 2001 Peter Dimov
// Copyright (C) 2002 David Abrahams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org/libs/bind/ref.html for documentation.
//
@ -34,28 +30,18 @@ template<class T> class reference_wrapper
public:
typedef T type;
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, < 1300 )
explicit reference_wrapper(T& t): t_(&t) {}
#else
explicit reference_wrapper(T& t): t_(boost::addressof(t)) {}
#endif
operator T& () const { return *t_; }
T& get() const { return *t_; }
T* get_pointer() const { return t_; }
private:
T* t_;
};
# if defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT(0x581) )
# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x551)
# define BOOST_REF_CONST
# else
# define BOOST_REF_CONST const
@ -74,11 +60,18 @@ template<class T> inline reference_wrapper<T const> BOOST_REF_CONST cref(T const
# undef BOOST_REF_CONST
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<typename T>
class is_reference_wrapper
: public mpl::false_
{
public:
BOOST_STATIC_CONSTANT(bool, value = false);
};
template<typename T>
class is_reference_wrapper<reference_wrapper<T> >
{
public:
BOOST_STATIC_CONSTANT(bool, value = true);
};
template<typename T>
@ -88,30 +81,12 @@ class unwrap_reference
typedef T type;
};
# define AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(X) \
template<typename T> \
class is_reference_wrapper< X > \
: public mpl::true_ \
{ \
}; \
\
template<typename T> \
class unwrap_reference< X > \
{ \
public: \
typedef T type; \
}; \
/**/
AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper<T>)
#if !defined(BOOST_NO_CV_SPECIALIZATIONS)
AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper<T> const)
AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper<T> volatile)
AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF(reference_wrapper<T> const volatile)
#endif
# undef AUX_REFERENCE_WRAPPER_METAFUNCTIONS_DEF
template<typename T>
class unwrap_reference<reference_wrapper<T> >
{
public:
typedef T type;
};
# else // no partial specialization
} // namespace boost
@ -158,10 +133,8 @@ class is_reference_wrapper
public:
BOOST_STATIC_CONSTANT(
bool, value = (
sizeof(detail::is_reference_wrapper_test(type<T>()))
sizeof(detail::is_reference_wrapper_test(type<T>()))
== sizeof(detail::yes_reference_wrapper_t)));
typedef ::boost::mpl::bool_<value> type;
};
template <typename T>

View File

@ -1,19 +1,62 @@
// Boost utility.hpp header file -------------------------------------------//
// boost utility.hpp header file -------------------------------------------//
// Copyright 1999-2003 Aleksey Gurtovoy. Use, modification, and distribution are
// subject to the Boost Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)
// (C) Copyright boost.org 1999. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See <http://www.boost.org/libs/utility/> for the library's home page.
// See http://www.boost.org for most recent version including documentation.
// Classes appear in alphabetical order
#ifndef BOOST_UTILITY_HPP
#define BOOST_UTILITY_HPP
#include <boost/utility/addressof.hpp>
#include <boost/utility/base_from_member.hpp>
#include <boost/utility/enable_if.hpp>
// certain headers are part of the <utility.hpp> interface
#include <boost/checked_delete.hpp>
#include <boost/next_prior.hpp>
#include <boost/noncopyable.hpp>
#include <boost/utility/base_from_member.hpp>
namespace boost
{
// next() and prior() template functions -----------------------------------//
// Helper functions for classes like bidirectional iterators not supporting
// operator+ and operator-.
//
// Usage:
// const std::list<T>::iterator p = get_some_iterator();
// const std::list<T>::iterator prev = boost::prior(p);
// Contributed by Dave Abrahams
template <class T>
inline T next(T x) { return ++x; }
template <class T>
inline T prior(T x) { return --x; }
// class noncopyable -------------------------------------------------------//
// Private copy constructor and copy assignment ensure classes derived from
// class noncopyable cannot be copied.
// Contributed by Dave Abrahams
class noncopyable
{
protected:
noncopyable(){}
~noncopyable(){}
private: // emphasize the following members are private
noncopyable( const noncopyable& );
const noncopyable& operator=( const noncopyable& );
}; // noncopyable
} // namespace boost
#endif // BOOST_UTILITY_HPP

View File

@ -1,58 +0,0 @@
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
// Douglas Gregor (gregod@cs.rpi.edu)
// Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// For more information, see http://www.boost.org
#ifndef BOOST_UTILITY_ADDRESSOF_HPP
# define BOOST_UTILITY_ADDRESSOF_HPP
# include <boost/config.hpp>
# include <boost/detail/workaround.hpp>
namespace boost {
// Do not make addressof() inline. Breaks MSVC 7. (Peter Dimov)
// VC7 strips const from nested classes unless we add indirection here
# if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
template<class T> struct _addp
{
typedef T * type;
};
template <typename T> typename _addp<T>::type
# else
template <typename T> T*
# endif
addressof(T& v)
{
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
// Borland doesn't like casting an array reference to a char reference
// but these overloads work around the problem.
# if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
template<typename T,std::size_t N>
T (*addressof(T (&t)[N]))[N]
{
return reinterpret_cast<T(*)[N]>(&t);
}
template<typename T,std::size_t N>
const T (*addressof(const T (&t)[N]))[N]
{
return reinterpret_cast<const T(*)[N]>(&t);
}
# endif
}
#endif // BOOST_UTILITY_ADDRESSOF_HPP

View File

@ -1,53 +1,17 @@
// boost utility/base_from_member.hpp header file --------------------------//
// Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and
// distribution are subject to the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or a copy at
// <http://www.boost.org/LICENSE_1_0.txt>.)
// (C) Copyright Daryle Walker 2001. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See <http://www.boost.org/libs/utility/> for the library's home page.
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_UTILITY_BASE_FROM_MEMBER_HPP
#define BOOST_UTILITY_BASE_FROM_MEMBER_HPP
#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
// Base-from-member arity configuration macro ------------------------------//
// The following macro determines how many arguments will be in the largest
// constructor template of base_from_member. Constructor templates will be
// generated from one argument to this maximum. Code from other files can read
// this number if they need to always match the exact maximum base_from_member
// uses. The maximum constructor length can be changed by overriding the
// #defined constant. Make sure to apply the override, if any, for all source
// files during project compiling for consistency.
// Contributed by Jonathan Turkanis
#ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY
#define BOOST_BASE_FROM_MEMBER_MAX_ARITY 10
#endif
// An iteration of a constructor template for base_from_member -------------//
// A macro that should expand to:
// template < typename T1, ..., typename Tn >
// base_from_member( T1 x1, ..., Tn xn )
// : member( x1, ..., xn )
// {}
// This macro should only persist within this file.
#define BOOST_PRIVATE_CTR_DEF( z, n, data ) \
template < BOOST_PP_ENUM_PARAMS(n, typename T) > \
explicit base_from_member( BOOST_PP_ENUM_BINARY_PARAMS(n, T, x) ) \
: member( BOOST_PP_ENUM_PARAMS(n, x) ) \
{} \
/**/
#include <boost/utility_fwd.hpp> // required for parameter defaults
namespace boost
@ -62,26 +26,34 @@ namespace boost
// Contributed by Daryle Walker
template < typename MemberType, int UniqueID = 0 >
template < typename MemberType, int UniqueID >
class base_from_member
{
protected:
MemberType member;
base_from_member()
explicit base_from_member()
: member()
{}
BOOST_PP_REPEAT_FROM_TO( 1, BOOST_PP_INC(BOOST_BASE_FROM_MEMBER_MAX_ARITY),
BOOST_PRIVATE_CTR_DEF, _ )
template< typename T1 >
explicit base_from_member( T1 x1 )
: member( x1 )
{}
template< typename T1, typename T2 >
base_from_member( T1 x1, T2 x2 )
: member( x1, x2 )
{}
template< typename T1, typename T2, typename T3 >
base_from_member( T1 x1, T2 x2, T3 x3 )
: member( x1, x2, x3 )
{}
}; // boost::base_from_member
} // namespace boost
// Undo any private macros
#undef BOOST_PRIVATE_CTR_DEF
#endif // BOOST_UTILITY_BASE_FROM_MEMBER_HPP

View File

@ -1,68 +0,0 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
//
#ifndef BOOST_UTILITY_COMPARE_POINTEES_25AGO2003_HPP
#define BOOST_UTILITY_COMPARE_POINTEES_25AGO2003_HPP
#include<functional>
namespace boost {
// template<class OP> bool equal_pointees(OP const& x, OP const& y);
// template<class OP> struct equal_pointees_t;
//
// Being OP a model of OptionalPointee (either a pointer or an optional):
//
// If both x and y have valid pointees, returns the result of (*x == *y)
// If only one has a valid pointee, returns false.
// If none have valid pointees, returns true.
// No-throw
template<class OptionalPointee>
inline
bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y )
{
return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ;
}
template<class OptionalPointee>
struct equal_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
{
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
{ return equal_pointees(x,y) ; }
} ;
// template<class OP> bool less_pointees(OP const& x, OP const& y);
// template<class OP> struct less_pointees_t;
//
// Being OP a model of OptionalPointee (either a pointer or an optional):
//
// If y has not a valid pointee, returns false.
// ElseIf x has not a valid pointee, returns true.
// ElseIf both x and y have valid pointees, returns the result of (*x < *y)
// No-throw
template<class OptionalPointee>
inline
bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y )
{
return !y ? false : ( !x ? true : (*x) < (*y) ) ;
}
template<class OptionalPointee>
struct less_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
{
bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
{ return less_pointees(x,y) ; }
} ;
} // namespace boost
#endif

View File

@ -1,36 +0,0 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
// Copyright (C) 2007, Tobias Schwinger.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
//
#ifndef BOOST_UTILITY_DETAIL_INPLACE_FACTORY_PREFIX_04APR2007_HPP
#define BOOST_UTILITY_DETAIL_INPLACE_FACTORY_PREFIX_04APR2007_HPP
#include <new>
#include <cstddef>
#include <boost/config.hpp>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/punctuation/paren.hpp>
#include <boost/preprocessor/iteration/iterate.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
#include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
#define BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT(z,n,_) BOOST_PP_CAT(m_a,n) BOOST_PP_LPAREN() BOOST_PP_CAT(a,n) BOOST_PP_RPAREN()
#define BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL(z,n,_) BOOST_PP_CAT(A,n) const& BOOST_PP_CAT(m_a,n);
#define BOOST_MAX_INPLACE_FACTORY_ARITY 10
#undef BOOST_UTILITY_DETAIL_INPLACE_FACTORY_SUFFIX_04APR2007_HPP
#endif

View File

@ -1,23 +0,0 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
// Copyright (C) 2007, Tobias Schwinger.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
//
#ifndef BOOST_UTILITY_DETAIL_INPLACE_FACTORY_SUFFIX_04APR2007_HPP
#define BOOST_UTILITY_DETAIL_INPLACE_FACTORY_SUFFIX_04APR2007_HPP
#undef BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT
#undef BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL
#undef BOOST_MAX_INPLACE_FACTORY_ARITY
#undef BOOST_UTILITY_DETAIL_INPLACE_FACTORY_PREFIX_04APR2007_HPP
#endif

View File

@ -1,89 +0,0 @@
// Boost result_of library
// Copyright Douglas Gregor 2004. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// For more information, see http://www.boost.org/libs/utility
#if !defined(BOOST_PP_IS_ITERATING)
# error Boost result_of - do not include this file!
#endif
// CWPro8 requires an argument in a function type specialization
#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3002)) && BOOST_PP_ITERATION() == 0
# define BOOST_RESULT_OF_ARGS void
#else
# define BOOST_RESULT_OF_ARGS BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)
#endif
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template<typename F BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of<F(BOOST_RESULT_OF_ARGS)>
: boost::detail::result_of_impl<F, F(BOOST_RESULT_OF_ARGS), (boost::detail::has_result_type<F>::value)> {};
#endif
#undef BOOST_RESULT_OF_ARGS
#if BOOST_PP_ITERATION() >= 1
namespace detail {
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of_impl<R (*)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
{
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of_impl<R (&)(BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),T)), FArgs, false>
{
typedef R type;
};
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T)),
FArgs, false>
{
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
const,
FArgs, false>
{
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
volatile,
FArgs, false>
{
typedef R type;
};
template<typename R, typename FArgs BOOST_PP_COMMA_IF(BOOST_PP_ITERATION())
BOOST_PP_ENUM_PARAMS(BOOST_PP_ITERATION(),typename T)>
struct result_of_impl<R (T0::*)
(BOOST_PP_ENUM_SHIFTED_PARAMS(BOOST_PP_ITERATION(),T))
const volatile,
FArgs, false>
{
typedef R type;
};
#endif
}
#endif

View File

@ -1,119 +0,0 @@
// Boost enable_if library
// Copyright 2003 <20> The Trustees of Indiana University.
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu)
// Jeremiah Willcock (jewillco at osl.iu.edu)
// Andrew Lumsdaine (lums at osl.iu.edu)
#ifndef BOOST_UTILITY_ENABLE_IF_HPP
#define BOOST_UTILITY_ENABLE_IF_HPP
#include "boost/config.hpp"
// Even the definition of enable_if causes problems on some compilers,
// so it's macroed out for all compilers that do not support SFINAE
#ifndef BOOST_NO_SFINAE
namespace boost
{
template <bool B, class T = void>
struct enable_if_c {
typedef T type;
};
template <class T>
struct enable_if_c<false, T> {};
template <class Cond, class T = void>
struct enable_if : public enable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_enable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_enable_if_c<false, T> {};
template <class Cond, class T>
struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
template <bool B, class T = void>
struct disable_if_c {
typedef T type;
};
template <class T>
struct disable_if_c<true, T> {};
template <class Cond, class T = void>
struct disable_if : public disable_if_c<Cond::value, T> {};
template <bool B, class T>
struct lazy_disable_if_c {
typedef typename T::type type;
};
template <class T>
struct lazy_disable_if_c<true, T> {};
template <class Cond, class T>
struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
} // namespace boost
#else
namespace boost {
namespace detail { typedef void enable_if_default_T; }
template <typename T>
struct enable_if_does_not_work_on_this_compiler;
template <bool B, class T = detail::enable_if_default_T>
struct enable_if_c : enable_if_does_not_work_on_this_compiler<T>
{ };
template <bool B, class T = detail::enable_if_default_T>
struct disable_if_c : enable_if_does_not_work_on_this_compiler<T>
{ };
template <bool B, class T = detail::enable_if_default_T>
struct lazy_enable_if_c : enable_if_does_not_work_on_this_compiler<T>
{ };
template <bool B, class T = detail::enable_if_default_T>
struct lazy_disable_if_c : enable_if_does_not_work_on_this_compiler<T>
{ };
template <class Cond, class T = detail::enable_if_default_T>
struct enable_if : enable_if_does_not_work_on_this_compiler<T>
{ };
template <class Cond, class T = detail::enable_if_default_T>
struct disable_if : enable_if_does_not_work_on_this_compiler<T>
{ };
template <class Cond, class T = detail::enable_if_default_T>
struct lazy_enable_if : enable_if_does_not_work_on_this_compiler<T>
{ };
template <class Cond, class T = detail::enable_if_default_T>
struct lazy_disable_if : enable_if_does_not_work_on_this_compiler<T>
{ };
} // namespace boost
#endif // BOOST_NO_SFINAE
#endif

View File

@ -1,88 +0,0 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
// Copyright (C) 2007, Tobias Schwinger.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
//
#ifndef BOOST_UTILITY_INPLACE_FACTORY_04APR2007_HPP
#ifndef BOOST_PP_IS_ITERATING
#include <boost/utility/detail/in_place_factory_prefix.hpp>
namespace boost {
class in_place_factory_base {} ;
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_MAX_INPLACE_FACTORY_ARITY)
#define BOOST_PP_FILENAME_1 <boost/utility/in_place_factory.hpp>
#include BOOST_PP_ITERATE()
} // namespace boost
#include <boost/utility/detail/in_place_factory_suffix.hpp>
#define BOOST_UTILITY_INPLACE_FACTORY_04APR2007_HPP
#else
#define N BOOST_PP_ITERATION()
#if N
template< BOOST_PP_ENUM_PARAMS(N, class A) >
#endif
class BOOST_PP_CAT(in_place_factory,N)
:
public in_place_factory_base
{
public:
explicit BOOST_PP_CAT(in_place_factory,N)
( BOOST_PP_ENUM_BINARY_PARAMS(N,A,const& a) )
#if N > 0
: BOOST_PP_ENUM(N, BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT, _)
#endif
{}
template<class T>
void* apply(void* address
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) const
{
return new(address) T( BOOST_PP_ENUM_PARAMS(N, m_a) );
}
template<class T>
void* apply(void* address, std::size_t n
BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(T)) const
{
for(char* next = address = this->BOOST_NESTED_TEMPLATE apply<T>(address);
!! --n;)
this->BOOST_NESTED_TEMPLATE apply<T>(next = next+sizeof(T));
return address;
}
BOOST_PP_REPEAT(N, BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL, _)
};
#if N > 0
template< BOOST_PP_ENUM_PARAMS(N, class A) >
inline BOOST_PP_CAT(in_place_factory,N)< BOOST_PP_ENUM_PARAMS(N, A) >
in_place( BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& a) )
{
return BOOST_PP_CAT(in_place_factory,N)< BOOST_PP_ENUM_PARAMS(N, A) >
( BOOST_PP_ENUM_PARAMS(N, a) );
}
#else
inline in_place_factory0 in_place()
{
return in_place_factory0();
}
#endif
#undef N
#endif
#endif

View File

@ -1,88 +0,0 @@
// Boost result_of library
// Copyright Douglas Gregor 2004. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// For more information, see http://www.boost.org/libs/utility
#ifndef BOOST_RESULT_OF_HPP
#define BOOST_RESULT_OF_HPP
#include <boost/config.hpp>
#include <boost/type_traits/ice.hpp>
#include <boost/type.hpp>
#include <boost/preprocessor.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/bool.hpp>
#ifndef BOOST_RESULT_OF_NUM_ARGS
# define BOOST_RESULT_OF_NUM_ARGS 10
#endif
namespace boost {
template<typename F> struct result_of;
#if !defined(BOOST_NO_SFINAE) && !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace detail {
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
template<typename F, typename FArgs, bool HasResultType> struct result_of_impl;
template<typename F>
struct result_of_void_impl
{
typedef void type;
};
template<typename R>
struct result_of_void_impl<R (*)(void)>
{
typedef R type;
};
template<typename R>
struct result_of_void_impl<R (&)(void)>
{
typedef R type;
};
template<typename F, typename FArgs>
struct result_of_impl<F, FArgs, true>
{
typedef typename F::result_type type;
};
template<typename FArgs>
struct is_function_with_no_args : mpl::false_ {};
template<typename F>
struct is_function_with_no_args<F(void)> : mpl::true_ {};
template<typename F, typename FArgs>
struct result_of_nested_result : F::template result<FArgs>
{};
template<typename F, typename FArgs>
struct result_of_impl<F, FArgs, false>
: mpl::if_<is_function_with_no_args<FArgs>,
result_of_void_impl<F>,
result_of_nested_result<F, FArgs> >::type
{};
} // end namespace detail
#define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_RESULT_OF_NUM_ARGS,<boost/utility/detail/result_of_iterate.hpp>))
#include BOOST_PP_ITERATE()
#else
# define BOOST_NO_RESULT_OF 1
#endif
}
#endif // BOOST_RESULT_OF_HPP

View File

@ -1,77 +0,0 @@
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
// Copyright (C) 2007, Tobias Schwinger.
//
// Use, modification, and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/lib/optional for documentation.
//
// You are welcome to contact the author at:
// fernando_cacciola@hotmail.com
//
#ifndef BOOST_UTILITY_TYPED_INPLACE_FACTORY_04APR2007_HPP
#ifndef BOOST_PP_IS_ITERATING
#include <boost/utility/detail/in_place_factory_prefix.hpp>
namespace boost {
class typed_in_place_factory_base {} ;
#define BOOST_PP_ITERATION_LIMITS (0, BOOST_MAX_INPLACE_FACTORY_ARITY)
#define BOOST_PP_FILENAME_1 <boost/utility/typed_in_place_factory.hpp>
#include BOOST_PP_ITERATE()
} // namespace boost
#include <boost/utility/detail/in_place_factory_suffix.hpp>
#define BOOST_UTILITY_TYPED_INPLACE_FACTORY_04APR2007_HPP
#else
#define N BOOST_PP_ITERATION()
template< class T BOOST_PP_ENUM_TRAILING_PARAMS(N,class A) >
class BOOST_PP_CAT(typed_in_place_factory,N)
:
public typed_in_place_factory_base
{
public:
typedef T value_type;
explicit BOOST_PP_CAT(typed_in_place_factory,N)
( BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& a) )
#if N > 0
: BOOST_PP_ENUM(N, BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_INIT, _)
#endif
{}
void* apply (void* address) const
{
return new(address) T( BOOST_PP_ENUM_PARAMS(N, m_a) );
}
void* apply (void* address, std::size_t n) const
{
for(char* next = address = this->apply(address); !! --n;)
this->apply(next = next+sizeof(T));
return address;
}
BOOST_PP_REPEAT(N, BOOST_DEFINE_INPLACE_FACTORY_CLASS_MEMBER_DECL, _)
};
template< class T BOOST_PP_ENUM_TRAILING_PARAMS(N, class A) >
inline BOOST_PP_CAT(typed_in_place_factory,N)<
T BOOST_PP_ENUM_TRAILING_PARAMS(N, A) >
in_place( BOOST_PP_ENUM_BINARY_PARAMS(N, A, const& a) )
{
return BOOST_PP_CAT(typed_in_place_factory,N)<
T BOOST_PP_ENUM_TRAILING_PARAMS(N, A) >( BOOST_PP_ENUM_PARAMS(N, a) );
}
#undef N
#endif
#endif

View File

@ -1,81 +0,0 @@
// (C) 2002, Fernando Luis Cacciola Carballal.
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// 21 Ago 2002 (Created) Fernando Cacciola
//
#ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
#define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
#include <boost/detail/select_type.hpp>
#include <boost/type_traits/cv_traits.hpp>
#include <boost/detail/workaround.hpp>
namespace boost {
namespace vinit_detail {
template<class T>
class const_T_base
{
protected :
const_T_base() : x() {}
T x ;
} ;
template<class T>
struct non_const_T_base
{
protected :
non_const_T_base() : x() {}
mutable T x ;
} ;
template<class T>
struct select_base
{
typedef
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
typename
#endif
::boost::detail::if_true< ::boost::is_const<T>::value >
::template then< const_T_base<T>, non_const_T_base<T> >::type type ;
} ;
} // namespace vinit_detail
template<class T>
class value_initialized : private vinit_detail::select_base<T>::type
{
public :
value_initialized() {}
operator T&() const { return this->x ; }
T& data() const { return this->x ; }
} ;
template<class T>
T const& get ( value_initialized<T> const& x )
{
return x.data() ;
}
template<class T>
T& get ( value_initialized<T>& x )
{
return x.data() ;
}
} // namespace boost
#endif

View File

@ -0,0 +1,34 @@
// Boost utility_fwd.hpp header file ---------------------------------------//
// (C) Copyright boost.org 2001. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org for most recent version including documentation.
#ifndef BOOST_UTILITY_FWD_HPP
#define BOOST_UTILITY_FWD_HPP
namespace boost
{
// From <boost/utility/base_from_member.hpp> -------------------------------//
template < typename MemberType, int UniqueID = 0 >
class base_from_member;
// From <boost/utility.hpp> ------------------------------------------------//
class noncopyable;
// Also has a few function templates
} // namespace boost
#endif // BOOST_UTILITY_FWD_HPP

View File

@ -1,40 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Boost Utility Library</title>
</head>
<body bgcolor="#FFFFFF">
<h1><IMG SRC="../../boost.png" WIDTH="276" HEIGHT="86" align="center">Boost
Utility Library</h1>
<p>The Boost Utility Library isn't really a single library at all. It is just a
collection for components too small to be called libraries in their own right.</p>
<p>But that doesn't mean there isn't useful stuff here. Take a look:</p>
<blockquote>
<p>
<a href="assert.html">assert</a><br>
<a href="base_from_member.html">base_from_member</a><br>
<a href="call_traits.htm">call_traits</a><br>
<a href="checked_delete.html">checked_delete</a><br>
<a href="compressed_pair.htm">compressed_pair</a><br>
<a href="current_function.html">current_function</a><br>
<a href="enable_if.html">enable_if</a><br>
<a href="iterator_adaptors.htm">iterator_adaptors</a><br>
<a href="operators.htm">operators</a><br>
<a href="throw_exception.html">throw_exception</a><br>
<a href="utility.htm">utility</a><br>
<a href="value_init.htm">value_init</a></p>
</blockquote>
<hr>
<p><EFBFBD> Copyright Beman Dawes, 2001</p>
<p>Distributed under the Boost Software License, Version 1.0. (See
accompanying file <a href="../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at
<a href="http://www.boost.org/LICENSE_1_0.txt">
www.boost.org/LICENSE_1_0.txt</a>)</p>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->07 November, 2006<!--webbot bot="Timestamp" endspan i-checksum="39368" --></p>
</body>
</html>

444
indirect_iterator.htm Normal file
View File

@ -0,0 +1,444 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<meta name="generator" content="HTML Tidy, see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Indirect Iterator Adaptor Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"center" width="277" height="86">
<h1>Indirect Iterator Adaptor</h1>
Defined in header <a href=
"../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
<p>The indirect iterator adaptor augments an iterator by applying an
<b>extra</b> dereference inside of <tt>operator*()</tt>. For example, this
iterator makes it possible to view a container of pointers or
smart-pointers (e.g. <tt>std::list&lt;boost::shared_ptr&lt;foo&gt;
&gt;</tt>) as if it were a container of the pointed-to type. The following
<b>pseudo-code</b> shows the basic idea of the indirect iterator:
<blockquote>
<pre>
// inside a hypothetical indirect_iterator class...
typedef std::iterator_traits&lt;BaseIterator&gt;::value_type Pointer;
typedef std::iterator_traits&lt;Pointer&gt;::reference reference;
reference indirect_iterator::operator*() const {
return **this-&gt;base_iterator;
}
</pre>
</blockquote>
<h2>Synopsis</h2>
<blockquote>
<pre>
namespace boost {
template &lt;class BaseIterator,
class Value, class Reference, class Category, class Pointer&gt;
struct indirect_iterator_generator;
template &lt;class BaseIterator,
class Value, class Reference, class ConstReference,
class Category, class Pointer, class ConstPointer&gt;
struct indirect_iterator_pair_generator;
template &lt;class BaseIterator&gt;
typename indirect_iterator_generator&lt;BaseIterator&gt;::type
make_indirect_iterator(BaseIterator base)
}
</pre>
</blockquote>
<hr>
<h2><a name="indirect_iterator_generator">The Indirect Iterator Type
Generator</a></h2>
The <tt>indirect_iterator_generator</tt> template is a <a href=
"../../more/generic_programming.html#type_generator">generator</a> of
indirect iterator types. The main template parameter for this class is the
<tt>BaseIterator</tt> type that is being wrapped. In most cases the type of
the elements being pointed to can be deduced using
<tt>std::iterator_traits</tt>, but in some situations the user may want to
override this type, so there are also template parameters that allow a user
to control the <tt>value_type</tt>, <tt>pointer</tt>, and
<tt>reference</tt> types of the resulting iterators.
<blockquote>
<pre>
template &lt;class BaseIterator,
class Value, class Reference, class Pointer&gt;
class indirect_iterator_generator
{
public:
typedef <tt><a href=
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt;...&gt;</tt> type; // the resulting indirect iterator type
};
</pre>
</blockquote>
<h3>Example</h3>
This example uses the <tt>indirect_iterator_generator</tt> to create
indirect iterators which dereference the pointers stored in the
<tt>pointers_to_chars</tt> array to access the <tt>char</tt>s in the
<tt>characters</tt> array.
<blockquote>
<pre>
#include &lt;boost/config.hpp&gt;
#include &lt;vector&gt;
#include &lt;iostream&gt;
#include &lt;iterator&gt;
#include &lt;boost/iterator_adaptors.hpp&gt;
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 &lt; N; ++i)
pointers_to_chars[i] = &amp;characters[i];
boost::indirect_iterator_generator&lt;char**, char&gt;::type
indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
std::copy(indirect_first, indirect_last, std::ostream_iterator&lt;char&gt;(std::cout, ","));
std::cout &lt;&lt; std::endl;
// to be continued...
</pre>
</blockquote>
<h3>Template Parameters</h3>
<table border>
<tr>
<th>Parameter
<th>Description
<tr>
<td><tt>BaseIterator</tt>
<td>The iterator type being wrapped. The <tt>value_type</tt>
of the base iterator should itself be dereferenceable.
The return type of the <tt>operator*</tt> for the
<tt>value_type</tt> should match the <tt>Reference</tt> type.
<tr>
<td><tt>Value</tt>
<td>The <tt>value_type</tt> of the resulting iterator, unless const. If
Value is <tt>const X</tt>, a conforming compiler makes the
<tt>value_type</tt> <tt><i>non-</i>const X</tt><a href=
"iterator_adaptors.htm#1">[1]</a>. Note that if the default
is used for <tt>Value</tt>, then there must be a valid specialization
of <tt>iterator_traits</tt> for the value type of the base iterator.
<br>
<b>Default:</b> <tt>std::iterator_traits&lt;<br>
<20> std::iterator_traits&lt;BaseIterator&gt;::value_type
&gt;::value_type</tt><a href="#2">[2]</a>
<tr>
<td><tt>Reference</tt>
<td>The <tt>reference</tt> type of the resulting iterator, and in
particular, the result type of <tt>operator*()</tt>.<br>
<b>Default:</b> <tt>Value&amp;</tt>
<tr>
<td><tt>Pointer</tt>
<td>The <tt>pointer</tt> type of the resulting iterator, and in
particular, the result type of <tt>operator-&gt;()</tt>.<br>
<b>Default:</b> <tt>Value*</tt>
<tr>
<td><tt>Category</tt>
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseIterator&gt;::iterator_category</tt>
</table>
<h3>Concept Model</h3>
The indirect iterator will model whichever <a href=
"http://www.sgi.com/tech/stl/Iterators.html">standard iterator
concept category</a> is modeled by the base iterator. Thus, if the
base iterator is a model of <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access Iterator</a> then so is the resulting indirect iterator. If
the base iterator models a more restrictive concept, the resulting
indirect iterator will model the same concept <a href="#3">[3]</a>.
<h3>Members</h3>
The indirect iterator type implements the member functions and operators
required of the <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
Iterator</a> concept. In addition it has the following constructor:
<pre>
explicit indirect_iterator_generator::type(const BaseIterator&amp; it)
</pre>
<br>
<br>
<hr>
<p>
<h2><a name="indirect_iterator_pair_generator">The Indirect Iterator Pair
Generator</a></h2>
Sometimes a pair of <tt>const</tt>/non-<tt>const</tt> pair of iterators is
needed, such as when implementing a container. The
<tt>indirect_iterator_pair_generator</tt> class makes it more convenient to
create this pair of iterator types.
<blockquote>
<pre>
template &lt;class BaseIterator,
class Value, class Reference, class ConstReference,
class Category, class Pointer, class ConstPointer&gt;
struct indirect_iterator_pair_generator;
{
public:
typedef <tt><a href=
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt;...&gt;</tt> iterator; // the mutable indirect iterator type
typedef <tt><a href=
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt;...&gt;</tt> const_iterator; // the immutable indirect iterator type
};
</pre>
</blockquote>
<h3>Example</h3>
<blockquote>
<pre>
// continuing from the last example...
typedef boost::indirect_iterator_pair_generator&lt;char**,
char, char*, char&amp;, const char*, const char&amp;&gt; PairGen;
char mutable_characters[N];
char* pointers_to_mutable_chars[N];
for (int i = 0; i &lt; N; ++i)
pointers_to_mutable_chars[i] = &amp;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&lt;char&gt;(), 1));
std::copy(mutable_indirect_first, mutable_indirect_last,
std::ostream_iterator&lt;char&gt;(std::cout, ","));
std::cout &lt;&lt; std::endl;
// to be continued...
</pre>
</blockquote>
<p>The output is:
<blockquote>
<pre>
b,c,d,e,f,g,h,
</pre>
</blockquote>
<h3>Template Parameters</h3>
<table border>
<tr>
<th>Parameter
<th>Description
<tr>
<td><tt>BaseIterator</tt>
<td>The iterator type being wrapped. The <tt>value_type</tt> of the
base iterator should itself be dereferenceable.
The return type of the <tt>operator*</tt> for the
<tt>value_type</tt> should match the <tt>Reference</tt> type.
<tr>
<td><tt>Value</tt>
<td>The <tt>value_type</tt> of the resulting iterators.
If Value is <tt>const X</tt>, a conforming compiler makes the
<tt>value_type</tt> <tt><i>non-</i>const X</tt><a href=
"iterator_adaptors.htm#1">[1]</a>. Note that if the default
is used for <tt>Value</tt>, then there must be a valid
specialization of <tt>iterator_traits</tt> for the value type
of the base iterator.<br>
<b>Default:</b> <tt>std::iterator_traits&lt;<br>
<20> std::iterator_traits&lt;BaseIterator&gt;::value_type
&gt;::value_type</tt><a href="#2">[2]</a>
<tr>
<td><tt>Reference</tt>
<td>The <tt>reference</tt> type of the resulting <tt>iterator</tt>, and
in particular, the result type of its <tt>operator*()</tt>.<br>
<b>Default:</b> <tt>Value&amp;</tt>
<tr>
<td><tt>ConstReference</tt>
<td>The <tt>reference</tt> type of the resulting
<tt>const_iterator</tt>, and in particular, the result type of its
<tt>operator*()</tt>.<br>
<b>Default:</b> <tt>const Value&amp;</tt>
<tr>
<td><tt>Category</tt>
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseIterator&gt;::iterator_category</tt>
<tr>
<td><tt>Pointer</tt>
<td>The <tt>pointer</tt> type of the resulting <tt>iterator</tt>, and
in particular, the result type of its <tt>operator-&gt;()</tt>.<br>
<b>Default:</b> <tt>Value*</tt>
<tr>
<td><tt>ConstPointer</tt>
<td>The <tt>pointer</tt> type of the resulting <tt>const_iterator</tt>,
and in particular, the result type of its <tt>operator-&gt;()</tt>.<br>
<b>Default:</b> <tt>const Value*</tt>
</table>
<h3>Concept Model</h3>
The indirect iterators will model whichever <a href=
"http://www.sgi.com/tech/stl/Iterators.html">standard iterator
concept category</a> is modeled by the base iterator. Thus, if the
base iterator is a model of <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access Iterator</a> then so are the resulting indirect
iterators. If the base iterator models a more restrictive concept,
the resulting indirect iterators will model the same concept <a
href="#3">[3]</a>.
<h3>Members</h3>
The resulting <tt>iterator</tt> and <tt>const_iterator</tt> types implement
the member functions and operators required of the <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
Iterator</a> concept. In addition they support the following constructors:
<blockquote>
<pre>
explicit indirect_iterator_pair_generator::iterator(const BaseIterator&amp; it)
explicit indirect_iterator_pair_generator::const_iterator(const BaseIterator&amp; it)
</pre>
</blockquote>
<br>
<br>
<hr>
<p>
<h2><a name="make_indirect_iterator">The Indirect Iterator Object
Generator</a></h2>
The <tt>make_indirect_iterator()</tt> function provides a more convenient
way to create indirect iterator objects. The function saves the user the
trouble of explicitly writing out the iterator types.
<blockquote>
<pre>
template &lt;class BaseIterator&gt;
typename indirect_iterator_generator&lt;BaseIterator&gt;::type
make_indirect_iterator(BaseIterator base)
</pre>
</blockquote>
<h3>Example</h3>
Here we again print the <tt>char</tt>s from the array <tt>characters</tt>
by accessing them through the array of pointers <tt>pointer_to_chars</tt>,
but this time we use the <tt>make_indirect_iterator()</tt> function which
saves us some typing.
<blockquote>
<pre>
// continuing from the last example...
std::copy(boost::make_indirect_iterator(pointers_to_chars),
boost::make_indirect_iterator(pointers_to_chars + N),
std::ostream_iterator&lt;char&gt;(std::cout, ","));
std::cout &lt;&lt; std::endl;
return 0;
}
</pre>
</blockquote>
The output is:
<blockquote>
<pre>
a,b,c,d,e,f,g,
</pre>
</blockquote>
<hr>
<h3>Notes</h3>
<p>
<p><a name="2">[2]</a> If your compiler does not support partial
specialization and the base iterator or its <tt>value_type</tt> is a
builtin pointer type, you will not be able to use the default for
<tt>Value</tt> and will need to specify this type explicitly.
<p><a name="3">[3]</a>There is a caveat to which concept the
indirect iterator can model. If the return type of the
<tt>operator*</tt> for the base iterator's value type is not a
true reference, then strickly speaking, the indirect iterator can
not be a model of <a href=
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
Iterator</a> or any of the concepts that refine it. In this case
the <tt>Category</tt> for the indirect iterator should be
specified as <tt>std::input_iterator_tag</tt>. However, even in
this case, if the base iterator is a random access iterator, the
resulting indirect iterator will still satisfy most of the
requirements for <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access Iterator</a>.
<hr>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->18 Sep 2001<!--webbot bot="Timestamp" endspan i-checksum="14941" -->
<p>&copy; Copyright Jeremy Siek and David Abrahams 2001. 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.
<!-- LocalWords: html charset alt gif hpp BaseIterator const namespace struct
-->
<!-- LocalWords: ConstPointer ConstReference typename iostream int abcdefg
-->
<!-- LocalWords: sizeof PairGen pre Jeremy Siek David Abrahams
-->
</body>
</html>

View File

@ -0,0 +1,62 @@
// (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> PairGen;
char mutable_characters[N];
char* pointers_to_mutable_chars[N];
for (int j = 0; j < N; ++j)
pointers_to_mutable_chars[j] = &mutable_characters[j];
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()
#ifndef BOOST_MSVC
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;
#endif
return 0;
}

151
indirect_iterator_test.cpp Normal file
View File

@ -0,0 +1,151 @@
// (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.
// Revision History
// 08 Mar 2001 Jeremy Siek
// Moved test of indirect iterator into its own file. It to
// to be in iterator_adaptor_test.cpp.
#include <boost/config.hpp>
#include <iostream>
#include <algorithm>
#include <boost/iterator_adaptors.hpp>
#include <boost/pending/iterator_tests.hpp>
#include <boost/concept_archetype.hpp>
#include <stdlib.h>
#include <deque>
#include <set>
struct my_iterator_tag : public std::random_access_iterator_tag { };
using boost::dummyT;
typedef std::deque<int> storage;
typedef std::deque<int*> pointer_deque;
typedef std::set<storage::iterator> iterator_set;
void more_indirect_iterator_tests()
{
// For some reason all heck breaks loose in the compiler under these conditions.
#if !defined(BOOST_MSVC) || !defined(__STL_DEBUG)
storage store(1000);
std::generate(store.begin(), store.end(), rand);
pointer_deque ptr_deque;
iterator_set iter_set;
for (storage::iterator p = store.begin(); p != store.end(); ++p)
{
ptr_deque.push_back(&*p);
iter_set.insert(p);
}
typedef boost::indirect_iterator_pair_generator<
pointer_deque::iterator
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
, int
#endif
> IndirectDeque;
IndirectDeque::iterator db(ptr_deque.begin());
IndirectDeque::iterator de(ptr_deque.end());
assert(static_cast<std::size_t>(de - db) == store.size());
assert(db + store.size() == de);
IndirectDeque::const_iterator dci(db);
assert(db == dci);
assert(dci == db);
assert(dci != de);
assert(dci < de);
assert(dci <= de);
assert(de >= dci);
assert(de > dci);
dci = de;
assert(dci == de);
boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin()));
*db = 999;
assert(store.front() == 999);
// Borland C++ is getting very confused about the typedef's here
typedef boost::indirect_iterator_generator<
iterator_set::iterator
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
, int
#endif
>::type indirect_set_iterator;
typedef boost::indirect_iterator_generator<
iterator_set::iterator,
const int
>::type const_indirect_set_iterator;
indirect_set_iterator sb(iter_set.begin());
indirect_set_iterator se(iter_set.end());
const_indirect_set_iterator sci(iter_set.begin());
assert(sci == sb);
assert(sci != se);
sci = se;
assert(sci == se);
*boost::prior(se) = 888;
assert(store.back() == 888);
assert(std::equal(sb, se, store.begin()));
boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
assert(std::equal(db, de, store.begin()));
#endif
}
int
main()
{
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
dummyT(3), dummyT(4), dummyT(5) };
const int N = sizeof(array)/sizeof(dummyT);
// Test indirect_iterator_generator
{
dummyT* ptr[N];
for (int k = 0; k < N; ++k)
ptr[k] = array + k;
typedef boost::indirect_iterator_generator<dummyT**
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
, dummyT
#endif
>::type indirect_iterator;
typedef boost::indirect_iterator_generator<dummyT**, const dummyT>::type const_indirect_iterator;
indirect_iterator i(ptr);
boost::random_access_iterator_test(i, N, array);
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
#endif
// check operator->
assert((*i).m_x == i->foo());
const_indirect_iterator j(ptr);
boost::random_access_iterator_test(j, N, array);
dummyT*const* const_ptr = ptr;
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
#endif
boost::const_nonconst_iterator_test(i, ++j);
more_indirect_iterator_tests();
}
std::cout << "test successful " << std::endl;
return 0;
}

View File

@ -0,0 +1,27 @@
// Test boost/pending/iterator_adaptors.hpp
// (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
// 21 Jan 01 Initial version (Jeremy Siek)
#include <boost/config.hpp>
#include <list>
#include <boost/pending/iterator_adaptors.hpp>
int main()
{
typedef boost::iterator_adaptor<std::list<int>::iterator,
boost::default_iterator_policies,
int,int&,int*,std::bidirectional_iterator_tag> adaptor_type;
adaptor_type i;
i += 4;
return 0;
}

View File

@ -0,0 +1,28 @@
// Test boost/pending/iterator_adaptors.hpp
// (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
// 21 Jan 01 Initial version (Jeremy Siek)
#include <boost/config.hpp>
#include <iostream>
#include <iterator>
#include <boost/pending/iterator_adaptors.hpp>
int main()
{
typedef boost::iterator_adaptor<std::istream_iterator<int>,
boost::default_iterator_policies,
int,int&,int*,std::input_iterator_tag> adaptor_type;
adaptor_type iter;
--iter;
return 0;
}

61
iter_traits_gen_test.cpp Normal file
View File

@ -0,0 +1,61 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// 04 Nov 2001 Jeremy Siek
// Updated with respect to new named parameter interface.
// 08 Mar 2001 Jeremy Siek
// Initial checkin.
#include <boost/iterator_adaptors.hpp>
#include <boost/pending/iterator_tests.hpp>
#include <boost/static_assert.hpp>
class bar { };
void foo(bar) { }
int
main()
{
using boost::dummyT;
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
dummyT(3), dummyT(4), dummyT(5) };
typedef boost::iterator_adaptor<dummyT*,
boost::default_iterator_policies, dummyT> my_iter;
my_iter mi(array);
{
typedef boost::iterator_adaptor<my_iter, boost::default_iterator_policies,
boost::reference_is<dummyT>,
boost::iterator_category_is<std::input_iterator_tag> > iter_type;
BOOST_STATIC_ASSERT((boost::is_same<iter_type::iterator_category*,
std::input_iterator_tag*>::value));
BOOST_STATIC_ASSERT(( ! boost::is_convertible<iter_type::iterator_category*,
std::forward_iterator_tag*>::value));
iter_type i(mi);
boost::input_iterator_test(i, dummyT(0), dummyT(1));
}
{
typedef boost::iterator_adaptor<dummyT*,
boost::default_iterator_policies,
boost::value_type_is<dummyT>,
boost::reference_is<const dummyT&>,
boost::pointer_is<const dummyT*> ,
boost::iterator_category_is<std::forward_iterator_tag>,
boost::difference_type_is<std::ptrdiff_t> > adaptor_type;
adaptor_type i(array);
boost::input_iterator_test(i, dummyT(0), dummyT(1));
int zero = 0;
if (zero) // don't do this, just make sure it compiles
assert((*i).m_x == i->foo());
}
return 0;
}

View File

@ -0,0 +1,46 @@
// (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 <functional>
#include <algorithm>
#include <iostream>
#include <boost/iterator_adaptors.hpp>
#include <boost/pending/integer_range.hpp>
int
main(int, char*[])
{
// This is a simple example of using the transform_iterators class to
// generate iterators that multiply the value returned by dereferencing
// the iterator. In this case we are multiplying by 2.
// Would be cooler to use lambda library in this example.
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
typedef std::binder1st< std::multiplies<int> > Function;
typedef boost::transform_iterator_generator<Function, int*
>::type doubling_iterator;
doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),
i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2));
std::cout << "multiplying the array by 2:" << std::endl;
while (i != i_end)
std::cout << *i++ << " ";
std::cout << std::endl;
// Here is an example of counting from 0 to 5 using the integer_range class.
boost::integer_range<int> r(0,5);
std::cout << "counting to from 0 to 4:" << std::endl;
std::copy(r.begin(), r.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}

449
iterator_adaptor_test.cpp Normal file
View File

@ -0,0 +1,449 @@
// Test boost/iterator_adaptors.hpp
// (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
// 30 Nov 01 Added permutation_iterator.(Toon Knapen)
// 19 Nov 01 Added generator_iterator. (Jens Maurer)
// 04 Nov 01 Updated with respect to change in named parameters.
// (Jeremy Siek)
// 08 Mar 01 Moved indirect and transform tests to separate files.
// (Jeremy Siek)
// 19 Feb 01 Take adavantage of improved iterator_traits to do more tests
// on MSVC. Hack around an MSVC-with-STLport internal compiler
// error. (David Abrahams)
// 11 Feb 01 Added test of operator-> for forward and input iterators.
// (Jeremy Siek)
// 11 Feb 01 Borland fixes (David Abrahams)
// 10 Feb 01 Use new adaptors interface. (David Abrahams)
// 10 Feb 01 Use new filter_ interface. (David Abrahams)
// 09 Feb 01 Use new reverse_ and indirect_ interfaces. Replace
// BOOST_NO_STD_ITERATOR_TRAITS with
// BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION to prove we've
// normalized to core compiler capabilities (David Abrahams)
// 08 Feb 01 Use Jeremy's new make_reverse_iterator form; add more
// comprehensive testing. Force-decay array function arguments to
// pointers.
// 07 Feb 01 Added tests for the make_xxx_iterator() helper functions.
// (Jeremy Siek)
// 07 Feb 01 Replaced use of xxx_pair_generator with xxx_generator where
// possible (which was all but the projection iterator).
// (Jeremy Siek)
// 06 Feb 01 Removed now-defaulted template arguments where possible
// Updated names to correspond to new generator naming convention.
// Added a trivial test for make_transform_iterator().
// Gave traits for const iterators a mutable value_type, per std.
// Resurrected my original tests for indirect iterators.
// (David Abrahams)
// 04 Feb 01 Fix for compilers without standard iterator_traits
// (David Abrahams)
// 13 Jun 00 Added const version of the iterator tests (Jeremy Siek)
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
#include <boost/config.hpp>
#include <iostream>
#include <algorithm>
#include <functional>
#include <numeric>
#include <boost/iterator_adaptors.hpp>
#include <boost/generator_iterator.hpp>
#include <boost/pending/iterator_tests.hpp>
#include <boost/pending/integer_range.hpp>
#include <boost/concept_archetype.hpp>
#include <boost/type_traits/same_traits.hpp>
#include <boost/permutation_iterator.hpp>
#include <stdlib.h>
#include <vector>
#include <deque>
#include <set>
#include <list>
struct my_iterator_tag : public std::random_access_iterator_tag { };
using boost::dummyT;
struct mult_functor {
typedef int result_type;
typedef int argument_type;
// Functors used with transform_iterator must be
// DefaultConstructible, as the transform_iterator must be
// DefaultConstructible to satisfy the requirements for
// TrivialIterator.
mult_functor() { }
mult_functor(int aa) : a(aa) { }
int operator()(int b) const { return a * b; }
int a;
};
template <class Pair>
struct select1st_
: public std::unary_function<Pair, typename Pair::first_type>
{
const typename Pair::first_type& operator()(const Pair& x) const {
return x.first;
}
typename Pair::first_type& operator()(Pair& x) const {
return x.first;
}
};
struct one_or_four {
bool operator()(dummyT x) const {
return x.foo() == 1 || x.foo() == 4;
}
};
typedef std::deque<int> storage;
typedef std::deque<int*> pointer_deque;
typedef std::set<storage::iterator> iterator_set;
template <class T> struct foo;
void blah(int) { }
struct my_gen
{
typedef int result_type;
my_gen() : n(0) { }
int operator()() { return ++n; }
int n;
};
int
main()
{
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
dummyT(3), dummyT(4), dummyT(5) };
const int N = sizeof(array)/sizeof(dummyT);
// sanity check, if this doesn't pass the test is buggy
boost::random_access_iterator_test(array, N, array);
// Check that the policy concept checks and the default policy
// implementation match up.
boost::function_requires<
boost::RandomAccessIteratorPoliciesConcept<
boost::default_iterator_policies,
boost::iterator_adaptor<int*, boost::default_iterator_policies>,
boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
int*, int&>
> >();
// Test the named parameters
{
// Test computation of defaults
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
boost::value_type_is<int> > Iter1;
// don't use std::iterator_traits here to avoid VC++ problems
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, int>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, int&>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, int*>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::difference_type, std::ptrdiff_t>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::iterator_category, std::random_access_iterator_tag>::value));
}
{
// Test computation of default when the Value is const
typedef boost::iterator_adaptor<std::list<int>::iterator,
boost::default_iterator_policies,
boost::value_type_is<const int> > Iter1;
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, int>::value));
#if defined(__BORLANDC__) || defined(BOOST_MSVC)
// We currently don't know how to workaround this bug.
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, int&>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, int*>::value));
#else
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, const int&>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, const int*>::value));
#endif
}
{
// Test with no defaults
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
boost::reference_is<long>,
boost::pointer_is<float*>,
boost::value_type_is<char>,
boost::iterator_category_is<std::input_iterator_tag>,
boost::difference_type_is<int>
> Iter1;
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, char>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, long>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, float*>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::difference_type, int>::value));
BOOST_STATIC_ASSERT((boost::is_same<Iter1::iterator_category, std::input_iterator_tag>::value));
}
// Test the iterator_adaptor
{
boost::iterator_adaptor<dummyT*, boost::default_iterator_policies, dummyT> i(array);
boost::random_access_iterator_test(i, N, array);
boost::iterator_adaptor<const dummyT*, boost::default_iterator_policies, const dummyT> j(array);
boost::random_access_iterator_test(j, N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test projection_iterator_pair_generator
{
typedef std::pair<dummyT,dummyT> Pair;
Pair pair_array[N];
for (int k = 0; k < N; ++k)
pair_array[k].first = array[k];
typedef boost::projection_iterator_pair_generator<select1st_<Pair>,
Pair*, const Pair*
> Projection;
Projection::iterator i(pair_array);
boost::random_access_iterator_test(i, N, array);
boost::random_access_iterator_test(boost::make_projection_iterator(pair_array, select1st_<Pair>()), N, array);
boost::random_access_iterator_test(boost::make_projection_iterator< select1st_<Pair> >(pair_array), N, array);
Projection::const_iterator j(pair_array);
boost::random_access_iterator_test(j, N, array);
boost::random_access_iterator_test(boost::make_const_projection_iterator(pair_array, select1st_<Pair>()), N, array);
boost::random_access_iterator_test(boost::make_const_projection_iterator<select1st_<Pair> >(pair_array), N, array);
boost::const_nonconst_iterator_test(i, ++j);
}
// Test reverse_iterator_generator
{
dummyT reversed[N];
std::copy(array, array + N, reversed);
std::reverse(reversed, reversed + N);
typedef boost::reverse_iterator_generator<dummyT*
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
, dummyT
#endif
>::type reverse_iterator;
reverse_iterator i(reversed + N);
boost::random_access_iterator_test(i, N, array);
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
#endif
typedef boost::reverse_iterator_generator<const dummyT*
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
, dummyT, const dummyT&, const dummyT
#endif
>::type const_reverse_iterator;
const_reverse_iterator j(reversed + N);
boost::random_access_iterator_test(j, N, array);
const dummyT* const_reversed = reversed;
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
#endif
boost::const_nonconst_iterator_test(i, ++j);
}
// Test reverse_iterator_generator again, with traits fully deducible on all platforms
{
std::deque<dummyT> reversed_container;
std::reverse_copy(array, array + N, std::back_inserter(reversed_container));
const std::deque<dummyT>::iterator reversed = reversed_container.begin();
typedef boost::reverse_iterator_generator<
std::deque<dummyT>::iterator>::type reverse_iterator;
typedef boost::reverse_iterator_generator<
std::deque<dummyT>::const_iterator, const dummyT>::type const_reverse_iterator;
// MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation
// (e.g. "reversed + N") is used in the constructor below.
const std::deque<dummyT>::iterator finish = reversed_container.end();
reverse_iterator i(finish);
boost::random_access_iterator_test(i, N, array);
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
const_reverse_iterator j = reverse_iterator(finish);
boost::random_access_iterator_test(j, N, array);
const std::deque<dummyT>::const_iterator const_reversed = reversed;
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
// Many compilers' builtin deque iterators don't interoperate well, though
// STLport fixes that problem.
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && !defined(BOOST_MSVC)
boost::const_nonconst_iterator_test(i, ++j);
#endif
}
// Test integer_range's iterators
{
int int_array[] = { 0, 1, 2, 3, 4, 5 };
boost::integer_range<int> r(0, 5);
boost::random_access_iterator_test(r.begin(), r.size(), int_array);
}
// Test filter iterator
{
// Using typedefs for filter_gen::type confused Borland terribly.
typedef boost::detail::non_bidirectional_category<dummyT*>::type category;
typedef boost::filter_iterator_generator<one_or_four, dummyT*
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
, dummyT
#endif
>::type filter_iter;
#if defined(__BORLANDC__)
// Borland is choking on accessing the policies_type explicitly
// from the filter_iter.
boost::forward_iterator_test(make_filter_iterator(array, array+N,
one_or_four()),
dummyT(1), dummyT(4));
#else
filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N));
boost::forward_iterator_test(i, dummyT(1), dummyT(4));
#endif
#if !defined(__BORLANDC__)
//
enum { is_forward = boost::is_same<
filter_iter::iterator_category,
std::forward_iterator_tag>::value };
BOOST_STATIC_ASSERT(is_forward);
#endif
// On compilers not supporting partial specialization, we can do more type
// deduction with deque iterators than with pointers... unless the library
// is broken ;-(
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
std::deque<dummyT> array2;
std::copy(array+0, array+N, std::back_inserter(array2));
boost::forward_iterator_test(
boost::make_filter_iterator(array2.begin(), array2.end(), one_or_four()),
dummyT(1), dummyT(4));
boost::forward_iterator_test(
boost::make_filter_iterator<one_or_four>(array2.begin(), array2.end()),
dummyT(1), dummyT(4));
#endif
#if !defined(BOOST_MSVC) // This just freaks MSVC out completely
boost::forward_iterator_test(
boost::make_filter_iterator<one_or_four>(
boost::make_reverse_iterator(array2.end()),
boost::make_reverse_iterator(array2.begin())
),
dummyT(4), dummyT(1));
#endif
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
boost::forward_iterator_test(
boost::make_filter_iterator(array+0, array+N, one_or_four()),
dummyT(1), dummyT(4));
boost::forward_iterator_test(
boost::make_filter_iterator<one_or_four>(array, array + N),
dummyT(1), dummyT(4));
#endif
}
// check operator-> with a forward iterator
{
boost::forward_iterator_archetype<dummyT> forward_iter;
#if defined(__BORLANDC__)
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
boost::default_iterator_policies,
dummyT, const dummyT&, const dummyT*,
std::forward_iterator_tag, std::ptrdiff_t> adaptor_type;
#else
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
boost::default_iterator_policies,
boost::reference_is<const dummyT&>,
boost::pointer_is<const dummyT*> ,
boost::iterator_category_is<std::forward_iterator_tag>,
boost::value_type_is<dummyT>,
boost::difference_type_is<std::ptrdiff_t>
> adaptor_type;
#endif
adaptor_type i(forward_iter);
int zero = 0;
if (zero) // don't do this, just make sure it compiles
assert((*i).m_x == i->foo());
}
// check operator-> with an input iterator
{
boost::input_iterator_archetype<dummyT> input_iter;
typedef boost::iterator_adaptor<boost::input_iterator_archetype<dummyT>,
boost::default_iterator_policies,
dummyT, const dummyT&, const dummyT*,
std::input_iterator_tag, std::ptrdiff_t> adaptor_type;
adaptor_type i(input_iter);
int zero = 0;
if (zero) // don't do this, just make sure it compiles
assert((*i).m_x == i->foo());
}
{
// check generator_iterator
my_gen g1;
boost::generator_iterator_generator<my_gen>::type gen =
boost::make_generator_iterator(g1);
assert(*gen == 1);
++gen;
gen++;
assert(*gen == 3);
}
{
// check permutation_iterator
typedef std::deque< int > element_range_type;
typedef std::list< int > index_type;
static const int element_range_size = 10;
static const int index_size = 4;
element_range_type elements( element_range_size );
for(element_range_type::iterator el_it = elements.begin();
el_it != elements.end();
++el_it)
{
*el_it = std::distance( elements.begin(), el_it );
}
index_type indices( index_size );
for(index_type::iterator i_it = indices.begin();
i_it != indices.end();
++i_it)
{
*i_it = element_range_size - index_size
+ std::distance(indices.begin(), i_it );
}
std::reverse( indices.begin(), indices.end() );
typedef boost::permutation_iterator_generator< element_range_type::iterator, index_type::iterator >::type permutation_type;
permutation_type begin = boost::make_permutation_iterator( elements.begin(), indices.begin() );
permutation_type end = boost::make_permutation_iterator( elements.begin(), indices.end() );
int expected_outcome[] = { 9, 8, 7, 6 };
assert( std::equal( begin, end, expected_outcome ) );
}
std::cout << "test successful " << std::endl;
return 0;
}

View File

@ -1,11 +1,954 @@
<!-- Copyright David Abrahams 2004. Distributed under the Boost -->
<!-- Software License, Version 1.0. (See accompanying -->
<!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -->
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="refresh" content="0; URL=../iterator/doc/index.html">
<meta name="generator" content="HTML Tidy, see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Boost Iterator Adaptor Library</title>
</head>
<body>
This documentation moved to <a href="../iterator/doc/index.html">../iterator/doc/index.html</a>.
<body bgcolor="#FFFFFF" text="#000000">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"center" width="277" height="86">
<h1>Boost Iterator Adaptor Library</h1>
<h2>Introduction</h2>
<p>The Iterator Adaptor library allows you transform an arbitrary ``base''
type into a standard-conforming iterator with the behaviors you choose.
Doing so is especially easy if the ``base'' type is itself an iterator. The
library also supplies several example <a href=
"../../more/generic_programming.html#adaptors">adaptors</a> which apply
specific useful behaviors to arbitrary base iterators.
<h2>Backward Compatibility Note</h2>
<p>The library's interface has changed since it was first released, breaking
backward compatibility:
<ol>
<li><a href="#policies">Policies classes</a> now operate on instances of the
whole <tt>iterator_adaptor</tt> object, rather than just operating on the
<tt>Base</tt> object. This change not only gives the policies class access
to both members of a pair of interacting iterators, but also eliminates the
need for the ugly <tt>type&lt;Reference&gt;</tt> and
<tt>type&lt;Difference&gt;</tt> parameters to various policy functions.
<li>The <a href="#named_template_parameters">Named Template Parameter</a>
interface has been made simpler, easier to use, and compatible with more
compilers.
</ol>
<h2>Other Documentation</h2>
<p><a href="iterator_adaptors.pdf">``Policy Adaptors and the Boost Iterator
Adaptor Library''</a> is a technical paper describing this library and the
powerful design pattern on which it is based. It was presented at the <a
href="http://www.oonumerics.org/tmpw01">C++ Template Workshop</a> at OOPSLA
2001; the slides from the talk are available <a
href="iterator_adaptors.ppt">here</a>. Please note that while the slides
incorporate the minor interface changes described in the previous section,
the paper does not.
<h2>Table of Contents</h2>
<ul>
<li>
Header <tt><a href=
"../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a></tt>
<ul>
<li>
Generalized Iterator Adaptor
<ul>
<li>Class template <tt><a href=
"#iterator_adaptor">iterator_adaptor</a></tt>
<li><a href="#template_parameters">Template Parameters</a>
<li><a href="#named_template_parameters">Named Template Parameters</a>
<li><a href="#policies">The Policies Class</a>
<li><a href="#additional_members">Additional Class Members</a>
<li><a href="#example">Example</a>
<li>(<tt>const</tt>/non-<tt>const</tt>) <a href=
"#iterator_interactions">Iterator Interactions</a>
<li><a href="#challenge">Challenge</a>
<li><a href="#concept_model">Concept Model</a>
<li><a href="#declaration_synopsis">Declaration Synopsis</a>
<li><a href="#portability">Portability</a>
<li><a href="#notes">Notes</a>
</ul>
<li>
<a name="specialized_adaptors">Specialized Iterator Adaptors</a>
<ul>
<li><a href="indirect_iterator.htm">Indirect Iterator Adaptor</a>
<li><a href="reverse_iterator.htm">Reverse Iterator Adaptor</a>
<li><a href="transform_iterator.htm">Transform Iterator
Adaptor</a>
<li><a href="projection_iterator.htm">Projection Iterator
Adaptor</a>
<li><a href="filter_iterator.htm">Filter Iterator Adaptor</a>
</ul>
</ul>
<li>Header <tt><a href=
"../../boost/counting_iterator.hpp">boost/counting_iterator.hpp</a></tt><br>
<a href="counting_iterator.htm">Counting Iterator Adaptor</a>
<li>Header <tt><a href=
"../../boost/function_output_iterator.hpp">boost/function_output_iterator.hpp</a></tt><br>
<a href="function_output_iterator.htm">Function Output Iterator Adaptor</a>
<li>Header <tt><a href="../../boost/generator_iterator.hpp">boost/generator_iterator.hpp</a></tt><br>
<a href="generator_iterator.htm">Generator Iterator Adaptor</a>
<li>Header <tt><a href="../../boost/permutation_iterator.hpp">boost/permutation_iterator.hpp</a></tt><br>
<a href="permutation_iterator.htm">Permutation Iterator Adaptor</a>
</ul>
<p><b><a href="../../people/dave_abrahams.htm">Dave
Abrahams</a></b> started the library, applying <a href=
"../../more/generic_programming.html#policy">policy class</a> technique and
handling const/non-const iterator interactions. He also contributed the
<tt><a href="indirect_iterator.htm">indirect_</a></tt> and <tt><a href=
"reverse_iterator.htm">reverse_</a></tt> iterator generators, and expanded
<tt><a href="counting_iterator.htm">counting_iterator_generator</a></tt> to
cover all incrementable types. He edited most of the documentation,
sometimes heavily.<br>
<b><a href="../../people/jeremy_siek.htm">Jeremy
Siek</a></b> contributed the <a href="transform_iterator.htm">transform
iterator</a> adaptor, the integer-only version of <tt><a href=
"counting_iterator.htm">counting_iterator_generator</a></tt>,
the <a href="function_output_iterator.htm">function output iterator</a>
adaptor, and most of the documentation.<br>
<b><a href="http://www.boost.org/people/john_potter.htm">John
Potter</a></b> contributed the <tt><a href=
"projection_iterator.htm">projection_</a></tt> and <tt><a href=
"filter_iterator.htm">filter_</a></tt> iterator generators and made some
simplifications to the main <tt><a href=
"#iterator_adaptor">iterator_adaptor</a></tt> template.<br>
<b><a href="../../people/jens_maurer.htm">Jens Maurer</a></b>
contributed the <a href="generator_iterator.htm">generator iterator</a>
adaptor.<br>
Toon Knapen contributed the <a href="permutation_iterator.htm">permutation
iterator</a> adaptor.<br>
<h2><a name="iterator_adaptor">Class template</a>
<tt>iterator_adaptor</tt></h2>
Implementing standard conforming iterators is a non-trivial task. There are
some fine points such as the interactions between an iterator and its
corresponding const_iterator, and there are myriad operators that should be
implemented but are easily forgotten or mishandled, such as
<tt>operator-&gt;()</tt>. Using <tt>iterator_adaptor</tt>, you can easily
implement an iterator class, and even more easily extend and <a href=
"../../more/generic_programming.html#adaptors">adapt</a> existing iterator
types. Moreover, it is easy to make a pair of interoperable <tt>const</tt>
and <tt>non-const</tt> iterators.
<p><tt>iterator_adaptor</tt> is declared like this:
<pre>
template &lt;class Base, class Policies,
class ValueOrNamedParam = typename std::iterator_traits&lt;Base&gt;::value_type,
class ReferenceOrNamedParam = <i>...(see below)</i>,
class PointerOrNamedParam = <i>...(see below)</i>,
class CategoryOrNamedParam = typename std::iterator_traits&lt;Base&gt;::iterator_category,
class DistanceOrNamedParam = typename std::iterator_traits&lt;Base&gt;::difference_type&gt;
struct iterator_adaptor;
</pre>
<h3><a name="template_parameters">Template Parameters</a></h3>
<p>Although <tt>iterator_adaptor</tt> takes seven template parameters,
defaults have been carefully chosen to minimize the number of parameters
you must supply in most cases, especially if <tt>BaseType</tt> is an
iterator.
<table border="1" summary="iterator_adaptor template parameters">
<tr>
<th>Parameter
<th>Description
<tr>
<td><tt>BaseType</tt>
<td>The type being wrapped.
<tr>
<td><tt>Policies</tt>
<td>A <a href="../../more/generic_programming.html#policy">policy
class</a> that supplies core functionality to the resulting iterator. A
detailed description can be found <a href="#policies">below</a>.
<tr>
<td><tt>Value</tt>
<td>The <tt>value_type</tt> of the resulting iterator, unless const. If
Value is <tt>const X</tt> the
<tt>value_type</tt> will be (<i>non-</i><tt>const</tt>) <tt>X</tt><a href=
"#1">[1]</a>. If the <tt>value_type</tt> you wish to use is an abstract
base class see note <a href="#5">[5]</a>.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseType&gt;::value_type</tt> <a href=
"#2">[2]</a>
<tr>
<td><tt>Reference</tt>
<td>The <tt>reference</tt> type of the resulting iterator, and in
particular, the result type of <tt>operator*()</tt>.<br>
<b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&amp;</tt> is
used. Otherwise
<tt>std::iterator_traits&lt;BaseType&gt;::reference</tt> is used. <a href="#7">[7]</a>
<tr>
<td><tt>Pointer</tt>
<td>The <tt>pointer</tt> type of the resulting iterator, and in
particular, the result type of <tt>operator-&gt;()</tt>.<br>
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
otherwise <tt>std::iterator_traits&lt;BaseType&gt;::pointer</tt>. <a href="#7">[7]</a>
<tr>
<td><tt>Category</tt>
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseType&gt;::iterator_category</tt>
<tr>
<td><tt>Distance</tt>
<td>The <tt>difference_type</tt> for the resulting iterator.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseType&gt;::difference_type</tt>
<tr>
<td><tt>NamedParam</tt>
<td>A named template parameter (see below).
</table>
<h3><a name="named_template_parameters">Named Template Parameters</a></h3>
With seven template parameters, providing arguments for
<tt>iterator_adaptor</tt> in the correct order can be challenging.
Also, often times one would like to specify the sixth or seventh
template parameter, but use the defaults for the third through
fifth. As a solution to these problems we provide a mechanism for
naming the last five template parameters, and providing them in
any order through a set of named template parameters. The following
classes are provided for specifying the parameters. Any of these
classes can be used for any of the last five template parameters
of <tt>iterator_adaptor</tt>.
<blockquote>
<pre>
template &lt;class Value&gt; struct value_type_is;
template &lt;class Reference&gt; struct reference_is;
template &lt;class Pointer&gt; struct pointer_is;
template &lt;class Distance&gt; struct difference_type_is;
template &lt;class Category&gt; struct iterator_category_is;
</pre>
</blockquote>
For example, the following adapts <tt>foo_iterator</tt> to create
an <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>
with <tt>reference</tt> type <tt>foo</tt>, and whose other traits
are determined according to the defaults described <a
href="#template_parameters">above</a>.
<blockquote>
<pre>
typedef iterator_adaptor&lt;foo_iterator, foo_policies,
reference_is&lt;foo&gt;, iterator_category_is&lt;std::input_iterator_tag&gt;
&gt; MyIterator;
</pre>
</blockquote>
<h3><a name="policies">The Policies Class</a></h3>
<p>The main task in using <tt>iterator_adaptor</tt> is creating an
appropriate <tt>Policies</tt> class. The <tt>Policies</tt> class will become
the functional heart of the resulting iterator, supplying the core
operations that determine its behavior. The <tt>iterator_adaptor</tt>
template defines all of the operators required of a <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
Iterator</a> by dispatching to a <tt>Policies</tt> object. Your
<tt>Policies</tt> class must implement a subset of the core iterator
operations below corresponding to the iterator categories you want it to
support.<br>
<br>
<table border="1" summary="iterator_adaptor Policies operations">
<caption>
<b>Policies Class Requirements</b><br>
<tt><b>T</b></tt>: adapted iterator type; <tt><b>x, y</b></tt>: objects of type
T; <tt><b>p</b></tt>: <tt>T::policies_type</tt>
<tt><b>d</b></tt>:
<tt>T::difference_type</tt>; <tt><b>i1</b></tt>, <tt><b>i2</b></tt>:
<tt>T::base_type</tt>
</caption>
<tr>
<th>Expression
<th>Effects
<th>Implements Operations
<th>Required for Iterator Categories
<tr>
<td nowrap><tt>p.initialize(b)</tt>
<td>optionally modify base iterator during iterator construction
<td>constructors
<td rowspan="4"><a href=
"http://www.sgi.com/tech/stl/InputIterator.html">Input</a>/ <a href=
"http://www.sgi.com/tech/stl/OutputIterator.html">Output</a>/ <a href=
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward</a>/ <a
href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random&nbsp;Access</a>
<tr>
<td nowrap><tt>p.dereference(x)</tt>
<td>returns an element of the iterator's <tt>reference</tt> type
<td><tt>*x</tt>, <tt>x[d]</tt>
<tr>
<td nowrap><tt>p.equal(x, y)</tt>
<td>tests the iterator for equality
<td><tt>i1&nbsp;==&nbsp;i2</tt>, <tt>i1&nbsp;!=&nbsp;i2</tt>
<tr>
<td nowrap><tt>p.increment(x)</tt>
<td>increments the iterator
<td><tt>++p</tt>, <tt>p++</tt>
<tr>
<td nowrap><tt>p.decrement(x)</tt>
<td>decrements the iterator
<td><tt>--x</tt>, <tt>x--</tt>
<td><a href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random&nbsp;Access</a>
<tr>
<td nowrap><tt>p.distance(x, y)</tt>
<td>measures the distance between iterators
<td><tt>y&nbsp;-&nbsp;x</tt>, <tt>x&nbsp;&lt;&nbsp;y</tt>
<td rowspan="2"><a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access</a>
<tr>
<td nowrap><tt>p.advance(x, n)</tt>
<td>adds an integer offset to iterators
<td>
<tt>x&nbsp;+&nbsp;d</tt>,
<tt>d&nbsp;+&nbsp;x</tt>,
<br>
<tt>x&nbsp;+=&nbsp;d</tt>,
<tt>x&nbsp;-&nbsp;d</tt>,<br>
<tt>x&nbsp;-=&nbsp;d</tt>
</table>
<p>The library also supplies a "trivial" policy class,
<tt>default_iterator_policies</tt>, which implements all seven of the core
operations in the usual way. If you wish to create an iterator adaptor that
only changes a few of the base type's behaviors, then you can derive your
new policy class from <tt>default_iterator_policies</tt> to avoid retyping
the usual behaviors. You should also look at
<tt>default_iterator_policies</tt> as the ``boilerplate'' for your own
policy classes, defining functions with the same interface. This is the
definition of <tt>default_iterator_policies</tt>:<br>
<br>
<blockquote>
<pre>
struct <a name="default_iterator_policies">default_iterator_policies</a>
{
// Some of these members were defined static, but Borland got confused
// and thought they were non-const. Also, Sun C++ does not like static
// function templates.
template &lt;class Base&gt;
void initialize(Base&amp;)
{ }
template &lt;class IteratorAdaptor&gt;
typename IteratorAdaptor::reference dereference(const IteratorAdaptor&amp; x) const
{ return *x.base(); }
template &lt;class IteratorAdaptor&gt;
void increment(IteratorAdaptor&amp; x)
{ ++x.base(); }
template &lt;class IteratorAdaptor&gt;
void decrement(IteratorAdaptor&amp; x)
{ --x.base(); }
template &lt;class IteratorAdaptor, class DifferenceType&gt;
void advance(IteratorAdaptor&amp; x, DifferenceType n)
{ x.base() += n; }
template &lt;class IteratorAdaptor1, class IteratorAdaptor2&gt;
typename IteratorAdaptor1::difference_type
distance(const IteratorAdaptor1&amp; x, const IteratorAdaptor2&amp; y) const
{ return y.base() - x.base(); }
template &lt;class IteratorAdaptor1, class IteratorAdaptor2&gt;
bool equal(const IteratorAdaptor1&amp; x, const IteratorAdaptor2&amp; y) const
{ return x.base() == y.base(); }
};
</pre></blockquote>
<p>Template member functions are used throughout
<tt>default_iterator_policies</tt> so that it can be employed with a wide
range of iterators. If we had used concrete types above, we'd have tied the
usefulness of <tt>default_iterator_policies</tt> to a particular range of
adapted iterators. If you follow the same pattern with your
<tt>Policies</tt> classes, you can use them to generate more specialized
adaptors along the lines of <a href="#specialized_adaptors">those supplied by this library</a>.
<h3><a name="additional_members">Additional Members</a></h3>
In addition to all of the member functions required of a <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
Iterator</a>, the <tt>iterator_adaptor</tt> class template defines the
following members. <br>
<br>
<table border="1" summary="additional iterator_adaptor members">
<tr>
<td><tt>explicit iterator_adaptor(const Base&amp;, const Policies&amp; =
Policies())</tt>
<br><br>
Construct an adapted iterator from a base object and a policies
object. As this constructor is <tt>explicit</tt>, it does not
provide for implicit conversions from the <tt>Base</tt> type to
the iterator adaptor.
<tr>
<td><tt>template &lt;class B, class V, class R, class P&gt;<br>
iterator_adaptor(const
iterator_adaptor&lt;B,Policies,V,R,P,Category,Distance&gt;&amp;)</tt>
<br><br>
This constructor allows for conversion from mutable to
constant adapted iterators. See <a href=
"#iterator_interactions">below</a> for more details.<br>
Requires: <tt>B</tt> is convertible to <tt>Base</tt>.
<tr>
<td><tt>const base_type& base() const;</tt>
<br><br>
Return a const reference to the base object.
<tr> <td><tt>base_type& base();</tt>
<br><br>
Return a reference to the base object. This is to give the policies object
access to the base object. See <a href="#policies">above</a> for policies
iterator_adaptor interaction.<a href="#8">[8]</a>
</table>
<h3><a name="example">Example</a></h3>
<p>It is often useful to automatically apply some function to the value
returned by dereferencing an iterator. The <a href=
"./transform_iterator.htm">transform iterator</a> makes it easy to create
an iterator adaptor which does just that. Here we will show how easy it is
to implement the transform iterator using the <tt>iterator_adaptor</tt>
template.
<p>We want to be able to adapt a range of iterators and functions, so the
policies class will have a template parameter for the function type and it
will have a data member of that type. We know that the function takes one
argument and that we'll need to be able to deduce the <tt>result_type</tt>
of the function so we can use it for the adapted iterator's
<tt>value_type</tt>. <a href=
"http://www.sgi.com/Technology/STL/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>
is the <a href="../../more/generic_programming.html#concept">Concept</a>
that fulfills those requirements.
<p>To implement a transform iterator we will only change one of the base
iterator's behaviors, so the <tt>transform_iterator_policies</tt> class can
inherit the rest from <tt>default_iterator_policies</tt>. We will define the
<tt>dereference()</tt> member function, which is used to implement
<tt>operator*()</tt> of the adapted iterator. The implementation will
dereference the base iterator and apply the function object. The complete
code for <tt>transform_iterator_policies</tt> is:<br>
<br>
<blockquote><pre>
template &lt;class AdaptableUnaryFunction&gt;
struct transform_iterator_policies : public default_iterator_policies
{
transform_iterator_policies() { }
transform_iterator_policies(const AdaptableUnaryFunction&amp; f)
: m_f(f) { }
template &lt;class IteratorAdaptor&gt;
typename IteratorAdaptor::reference
dereference(const IteratorAdaptor&amp; iter) const
{ return m_f(*iter.base()); }
AdaptableUnaryFunction m_f;
};
</pre></blockquote>
<p>The next step is to use the <tt>iterator_adaptor</tt> template to
construct the transform iterator type. The nicest way to package the
construction of the transform iterator is to create a <a href=
"../../more/generic_programming.html#type_generator">type generator</a>.
The first template parameter to the generator will be the type of the
function object and the second will be the base iterator type. We use
<tt>iterator_adaptor</tt> to define the transform iterator type as a nested
<tt>typedef</tt> inside the <tt>transform_iterator_generator</tt> class.
Because the function may return by-value, we must limit the
<tt>iterator_category</tt> to <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>, and
the iterator's <tt>reference</tt> type cannot be a true reference (the
standard allows this for input iterators), so in this case we can use few
of <tt>iterator_adaptor</tt>'s default template arguments.<br>
<br>
<blockquote>
<pre>
template &lt;class AdaptableUnaryFunction, class Iterator&gt;
struct transform_iterator_generator
{
typedef typename AdaptableUnaryFunction::result_type value_type;
public:
typedef iterator_adaptor&lt;Iterator,
transform_iterator_policies&lt;AdaptableUnaryFunction&gt;,
value_type, value_type, value_type*, std::input_iterator_tag&gt;
type;
};
</pre>
</blockquote>
<p>As a finishing touch, we will create an <a href=
"../../more/generic_programming.html#object_generator">object generator</a>
for the transform iterator. Our object generator makes it more
convenient to create a transform iterator.<br>
<br>
<blockquote>
<pre>
template &lt;class AdaptableUnaryFunction, class Iterator&gt;
typename transform_iterator_generator&lt;AdaptableUnaryFunction,Iterator&gt;::type
make_transform_iterator(Iterator base,
const AdaptableUnaryFunction&amp; f = AdaptableUnaryFunction())
{
typedef typename transform_iterator_generator&lt;AdaptableUnaryFunction,
Iterator&gt;::type result_t;
return result_t(base, f);
}
</pre>
</blockquote>
<p>Here is an example that shows how to use a transform iterator to iterate
through a range of numbers, multiplying each of them by 2 and printing the
result to standard output.<br>
<br>
<blockquote>
<pre>
#include &lt;functional&gt;
#include &lt;algorithm&gt;
#include &lt;iostream&gt;
#include &lt;boost/iterator_adaptors.hpp&gt;
int main(int, char*[])
{
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
const int N = sizeof(x)/sizeof(int);
std::cout &lt;&lt; &quot;multiplying the array by 2:&quot; &lt;&lt; std::endl;
std::copy(boost::make_transform_iterator(x, std::bind1st(std::multiplies&lt;int&gt;(), 2)),
boost::make_transform_iterator(x + N, std::bind1st(std::multiplies&lt;int&gt;(), 2)),
std::ostream_iterator&lt;int&gt;(std::cout, &quot; &quot;));
std::cout &lt;&lt; std::endl;
return 0;
}
</pre>
This output is:
<pre>
2 4 6 8 10 12 14 16
</pre>
</blockquote>
<h3><a name="iterator_interactions">Iterator Interactions</a></h3>
<p>C++ allows <tt>const</tt> and non-<tt>const</tt> pointers to interact in
the following intuitive ways:
<ul>
<li>a non-<tt>const</tt> pointer to <tt>T</tt> can be implicitly
converted to a <tt>const</tt> pointer to <tt>T</tt>.
<li><tt>const</tt> and non-<tt>const</tt> pointers to <tt>T</tt> can be
freely mixed in comparison expressions.
<li><tt>const</tt> and non-<tt>const</tt> pointers to <tt>T</tt> can be
freely subtracted, in any order.
</ul>
Getting user-defined iterators to work together that way is nontrivial (see
<a href="reverse_iterator.htm#interactions">here</a> for an example of where
the C++ standard got it wrong), but <tt>iterator_adaptor</tt> can make it
easy. The rules are as follows:
<ul>
<li><a name="interoperable">Adapted iterators that share the same <tt>Policies</tt>,
<tt>Category</tt>, and <tt>Distance</tt> parameters are called
<i>interoperable</i>.</a>
<li>An adapted iterator can be implicitly converted to any other adapted
iterator with which it is interoperable, so long as the <tt>Base</tt>
type of the source iterator can be converted to the <tt>Base</tt> type of
the target iterator.
<li>Interoperable iterators can be freely mixed in comparison expressions
so long as the <tt>Policies</tt> class has <tt>equal</tt> (and, for
random access iterators, <tt>distance</tt>) members that can accept both
<tt>Base</tt> types in either order.
<li>Interoperable iterators can be freely mixed in subtraction
expressions so long as the <tt>Policies</tt> class has a
<tt>distance</tt> member that can accept both <tt>Base</tt> types in
either order.
</ul>
<h4>Example</h4>
<p>The <a href="projection_iterator.htm">Projection Iterator</a> adaptor is similar to the <a
href="./transform_iterator.htm">transform iterator adaptor</a> in that
its <tt>operator*()</tt> applies some function to the result of
dereferencing the base iterator and then returns the result. The
difference is that the function must return a reference to some
existing object (for example, a data member within the
<tt>value_type</tt> of the base iterator).
<p>
The <a
href="projection_iterator.htm#projection_iterator_pair_generator">projection_iterator_pair_generator</a> template
is a special two-<a href="../../more/generic_programming.html#type_generator">type generator</a> for mutable and constant versions of a
projection iterator. It is defined as follows:
<blockquote>
<pre>
template &lt;class AdaptableUnaryFunction, class Iterator, class ConstIterator&gt;
struct projection_iterator_pair_generator {
typedef typename AdaptableUnaryFunction::result_type value_type;
typedef projection_iterator_policies&lt;AdaptableUnaryFunction&gt; policies;
public:
typedef iterator_adaptor&lt;Iterator,policies,value_type&gt; iterator;
typedef iterator_adaptor&lt;ConstIterator,policies,value_type,
const value_type&amp;,const value_type*&gt; const_iterator;
};
</pre>
</blockquote>
<p>It is assumed that the <tt>Iterator</tt> and <tt>ConstIterator</tt> arguments are corresponding mutable
and constant iterators. <ul>
<li>
Clearly, then, the
<tt>projection_iterator_pair_generator</tt>'s <tt>iterator</tt> and
<tt>const_iterator</tt> are <a href="#interoperable">interoperable</a>, since
they share the same <tt>Policies</tt> and since <tt>Category</tt> and
<tt>Distance</tt> as supplied by <tt>std::iterator_traits</tt> through the
<a href="#template_parameters">default template parameters</a> to
<tt>iterator_adaptor</tt> should be the same.
<li>Since <tt>Iterator</tt> can presumably be converted to
<tt>ConstIterator</tt>, the projection <tt>iterator</tt> will be convertible to
the projection <tt>const_iterator</tt>.
<li> Since <tt>projection_iterator_policies</tt> implements only the
<tt>dereference</tt> operation, and inherits all other behaviors from
<tt><a
href="#default_iterator_policies">default_iterator_policies</a></tt>,
which has fully-templatized <tt>equal</tt> and <tt>distance</tt>
operations, the <tt>iterator</tt> and <tt>const_iterator</tt> can be
freely mixed in comparison and subtraction expressions.
</ul>
<h3><a name="challenge">Challenge</a></h3>
<p>There is an unlimited number of ways the <tt>iterator_adaptors</tt>
class can be used to create iterators. One interesting exercise would be to
re-implement the iterators of <tt>std::list</tt> and <tt>slist</tt>
using <tt>iterator_adaptors</tt>, where the adapted <tt>Iterator</tt> types
would be node pointers.
<h3><a name="concept_model">Concept Model</a></h3>
Depending on the <tt>Base</tt> and <tt>Policies</tt> template parameters,
an <tt>iterator_adaptor</tt> can be a <a href=
"http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>, <a
href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
Iterator</a>, <a href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional
Iterator</a>, or <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
Iterator</a>.
<h3><a name="declaration_synopsis">Declaration Synopsis</a></h3>
<pre>
template &lt;class Base, class Policies,
class Value = typename std::iterator_traits&lt;Base&gt;::value_type,
class Reference = <i>...(see below)</i>,
class Pointer = <i>...(see below)</i>,
class Category = typename std::iterator_traits&lt;Base&gt;::iterator_category,
class Distance = typename std::iterator_traits&lt;Base&gt;::difference_type
&gt;
struct iterator_adaptor
{
typedef Distance difference_type;
typedef typename boost::remove_const&lt;Value&gt;::type value_type;
typedef Pointer pointer;
typedef Reference reference;
typedef Category iterator_category;
typedef Base base_type;
typedef Policies policies_type;
iterator_adaptor();
explicit iterator_adaptor(const Base&amp;, const Policies&amp; = Policies());
base_type& base();
const base_type& base() const;
template &lt;class B, class V, class R, class P&gt;
iterator_adaptor(
const iterator_adaptor&lt;B,Policies,V,R,P,Category,Distance&gt;&amp;);
reference operator*() const; <a href="#6">[6]</a>
<i>operator_arrow_result_type</i> operator-&gt;() const; <a href=
"#3">[3]</a>
<i>value_type</i> operator[](difference_type n) const; <a href="#3">[4]</a>, <a href="#6">[6]</a>
iterator_adaptor&amp; operator++();
iterator_adaptor&amp; operator++(int);
iterator_adaptor&amp; operator--();
iterator_adaptor&amp; operator--(int);
iterator_adaptor&amp; operator+=(difference_type n);
iterator_adaptor&amp; operator-=(difference_type n);
iterator_adaptor&amp; operator-(Distance x) const;
};
template &lt;class B, class P, class V, class R, class Ptr,
class C, class D1, class D2&gt;
iterator_adaptor&lt;B,P,V,R,Ptr,C,D1&gt;
operator+(iterator_adaptor&lt;B,P,V,R,Ptr,C,D1&gt;, D2);
template &lt;class B, class P, class V, class R, class Ptr,
class C, class D1, class D2&gt;
iterator_adaptor&lt;B,P,V,R,P,C,D1&gt;
operator+(D2, iterator_adaptor&lt;B,P,V,R,Ptr,C,D1&gt; p);
template &lt;class B1, class B2, class P, class V1, class V2,
class R1, class R2, class P1, class P2, class C, class D&gt;
Distance operator-(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
const iterator_adaptor&lt;B2,P,V2,R2,P2,C,D&gt;&amp;);
template &lt;class B1, class B2, class P, class V1, class V2,
class R1, class R2, class P1, class P2, class C, class D&gt;
bool operator==(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
const iterator_adaptor&lt;B2,P,V2,R2,P2,C,D&gt;&amp;);
// and similarly for operators !=, &lt;, &lt;=, &gt;=, &gt;
</pre>
<h3><a name="portability">Portability</a></h3>
<p>Generally, the iterator adaptors library can be compiled with all compilers
supporting iterator traits and type traits.</p>
<p>Microsoft VC++ is not able to handle iterator adaptors based on a
<code>vector<T>::iterator</code> without specifying all template paramters explicitly.
In case not all template parameters are specified explicitly, the iterator adaptors
library will deduce these types using iterator_traits. But since in VC++ a
<code>vector<T>::iterator</code> is a <code>T*</code>, VC++ can't handle using
iterator_traits due to the lack of partial template specialization.</p>
<h3><a name="notes">Notes</a></h3>
<p><a name="1">[1]</a> The standard specifies that the <tt>value_type</tt>
of <tt>const</tt> iterators to <tt>T</tt> (e.g. <tt>const T*</tt>) is
<tt><i>non-</i>const T</tt>, while the <tt>pointer</tt> and
<tt>reference</tt> types for all <a href=
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterators</a> are
<tt>const T*</tt> and <tt>const T&amp;</tt>, respectively. Stripping the
<tt>const</tt>-ness of <tt>Value</tt> allows you to easily make a constant
iterator by supplying a <tt>const</tt> type for <tt>Value</tt>, and allowing
the defaults for the <tt>Pointer</tt> and <tt>Reference</tt> parameters to
take effect. Although compilers that don't support partial specialization
won't strip <tt>const</tt> for you, having a <tt>const value_type</tt> is
often harmless in practice.
<p><a name="2">[2]</a> If your compiler does not support partial
specialization and the base iterator is a builtin pointer type, you
will not be able to use the default for <tt>Value</tt> and will have to
specify this type explicitly.
<p><a name="3">[3]</a> The result type for the <tt>operator-&gt;()</tt>
depends on the category and value type of the iterator and is somewhat
complicated to describe. But be assured, it works in a stardard conforming
fashion, providing access to members of the objects pointed to by the
iterator.
<p><a name="4">[4]</a> The result type of <tt>operator[]()</tt> is
<tt>value_type</tt> instead of <tt>reference</tt> as might be expected.
There are two reasons for this choice. First, the C++ standard only
requires that the return type of an arbitrary <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
Iterator</a>'s <tt>operator[]</tt>be ``convertible to T'' (Table 76), so
when adapting an arbitrary base iterator we may not have a reference to
return. Second, and more importantly, for certain kinds of iterators,
returning a reference could cause serious memory problems due to the
reference being bound to a temporary object whose lifetime ends inside of
the <tt>operator[]</tt>.
<p><a name="5">[5]</a>
The <tt>value_type</tt> of an iterator may not be
an abstract base class, however many common uses of iterators
never need the <tt>value_type</tt>, only the <tt>reference</tt> type.
If you wish to create such an iterator adaptor, use a dummy
type such as <tt>char</tt> for the <tt>Value</tt> parameter,
and use a reference to your abstract base class for
the <tt>Reference</tt> parameter. Note that such an iterator
does not fulfill the C++ standards requirements for a
<a href= "http://www.sgi.com/tech/stl/ForwardIterator.html">
Forward Iterator</a>, so you will need to use a less restrictive
iterator category such as <tt>std::input_iterator_tag</tt>.
<p><a name="6">[6]</a>
There is a common misconception that an iterator should have two
versions of <tt>operator*</tt> and of <tt>operator[]</tt>, one
version that is a <tt>const</tt> member function and one version
that is non-<tt>const</tt>. Perhaps the source of this
misconception is that containers typically have const and
non-const versions of many of their member functions. Iterators,
however, are different. A particular iterator type can be either
<i>mutable</i> or <i>constant</i> (but not both). One can assign
to and change the object pointed to by a mutable iterator whereas a
constant iterator returns constant objects when dereferenced. Whether
the iterator object itself is <tt>const</tt> has nothing to do with
whether the iterator is mutable or constant. This is analogous to
the way built-in pointer types behave. For example, one can
modify objects pointed to by a <tt>const</tt> pointer
<pre>
int* const x = new int;
int i = 3;
*x = i;
</pre>
but one cannot modify objects pointed to by a pointer
to <tt>const</tt>
<pre>
int const* x = new int;
int i = 3;
*x = i;
</pre>
<p><a name="7">[7]</a>
If you are using a compiler that does not have a version of
<tt>std::iterator_traits</tt> that works for pointers (i.e., if your
compiler does not support partial specialization) then if the
<tt>Base</tt> type is a const pointer, then the correct defaults
for the <tt>reference</tt> and <tt>pointer</tt> types can not be
deduced. You must specify these types explicitly.
<p><a name="8">[8]</a>
Exposing the base object might be considered as being dangerous.
A possible fix would require compiler support for template friends.
As this is not widely available today, the base object remains exposed for now.
<hr>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->30 Nov 2001<!--webbot bot="Timestamp" endspan i-checksum="15239" -->
<p>&copy; Copyright Dave Abrahams and Jeremy Siek 2001. 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.
</body>
<!-- LocalWords: HTML html charset alt gif abrahams htm const iterator
incrementable david abrahams
-->
<!-- LocalWords: jeremy siek mishandled interoperable typename struct Iter iter src
-->
<!-- LocalWords: int bool ForwardIterator BidirectionalIterator BaseIterator
-->
<!-- LocalWords: RandomAccessIterator DifferenceType AdaptableUnaryFunction
-->
<!-- LocalWords: iostream hpp sizeof InputIterator constness ConstIterator
David Abrahams
-->
<!-- LocalWords: Iterators dereferenced
-->
</html>

BIN
iterator_adaptors.pdf Normal file

Binary file not shown.

BIN
iterator_adaptors.ppt Normal file

Binary file not shown.

210
iterator_traits_test.cpp Normal file
View File

@ -0,0 +1,210 @@
// (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
// 04 Mar 2001 Patches for Intel C++ (Dave Abrahams)
// 19 Feb 2001 Take advantage of improved iterator_traits to do more tests
// on MSVC. Reordered some #ifdefs for coherency.
// (David Abrahams)
// 13 Feb 2001 Test new VC6 workarounds (David Abrahams)
// 11 Feb 2001 Final fixes for Borland (David Abrahams)
// 11 Feb 2001 Some fixes for Borland get it closer on that compiler
// (David Abrahams)
// 07 Feb 2001 More comprehensive testing; factored out static tests for
// better reuse (David Abrahams)
// 21 Jan 2001 Quick fix to my_iterator, which wasn't returning a
// reference type from operator* (David Abrahams)
// 19 Jan 2001 Initial version with iterator operators (David Abrahams)
#include <boost/detail/iterator.hpp>
#include <boost/type_traits.hpp>
#include <boost/operators.hpp>
#include <boost/static_assert.hpp>
#include <iterator>
#include <vector>
#include <list>
#include <cassert>
#include <iostream>
// An iterator for which we can get traits.
struct my_iterator1
: boost::forward_iterator_helper<my_iterator1, char, long, const char*, const char&>
{
my_iterator1(const char* p) : m_p(p) {}
bool operator==(const my_iterator1& rhs) const
{ return this->m_p == rhs.m_p; }
my_iterator1& operator++() { ++this->m_p; return *this; }
const char& operator*() { return *m_p; }
private:
const char* m_p;
};
// Used to prove that we don't require std::iterator<> in the hierarchy under
// MSVC6, and that we can compute all the traits for a standard-conforming UDT
// iterator.
struct my_iterator2
: boost::equality_comparable<my_iterator2
, boost::incrementable<my_iterator2
, boost::dereferenceable<my_iterator2,const char*> > >
{
typedef char value_type;
typedef long difference_type;
typedef const char* pointer;
typedef const char& reference;
typedef std::forward_iterator_tag iterator_category;
my_iterator2(const char* p) : m_p(p) {}
bool operator==(const my_iterator2& rhs) const
{ return this->m_p == rhs.m_p; }
my_iterator2& operator++() { ++this->m_p; return *this; }
const char& operator*() { return *m_p; }
private:
const char* m_p;
};
// Used to prove that we're not overly confused by the existence of
// std::iterator<> in the hierarchy under MSVC6 - we should find that
// boost::detail::iterator_traits<my_iterator3>::difference_type is int.
struct my_iterator3 : my_iterator1
{
typedef int difference_type;
my_iterator3(const char* p) : my_iterator1(p) {}
};
template <class Iterator,
class value_type, class difference_type, class pointer, class reference, class category>
struct non_portable_tests
{
// Unfortunately, the VC6 standard library doesn't supply these :(
BOOST_STATIC_ASSERT((
boost::is_same<
typename boost::detail::iterator_traits<Iterator>::pointer,
pointer
>::value));
BOOST_STATIC_ASSERT((
boost::is_same<
typename boost::detail::iterator_traits<Iterator>::reference,
reference
>::value));
};
template <class Iterator,
class value_type, class difference_type, class pointer, class reference, class category>
struct portable_tests
{
BOOST_STATIC_ASSERT((
boost::is_same<
typename boost::detail::iterator_traits<Iterator>::difference_type,
difference_type
>::value));
BOOST_STATIC_ASSERT((
boost::is_same<
typename boost::detail::iterator_traits<Iterator>::iterator_category,
category
>::value));
};
// Test iterator_traits
template <class Iterator,
class value_type, class difference_type, class pointer, class reference, class category>
struct input_iterator_test
: portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
{
BOOST_STATIC_ASSERT((
boost::is_same<
typename boost::detail::iterator_traits<Iterator>::value_type,
value_type
>::value));
};
template <class Iterator,
class value_type, class difference_type, class pointer, class reference, class category>
struct non_pointer_test
: input_iterator_test<Iterator,value_type,difference_type,pointer,reference,category>
, non_portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
{
};
template <class Iterator,
class value_type, class difference_type, class pointer, class reference, class category>
struct maybe_pointer_test
: portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
, non_portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
#endif
{
};
input_iterator_test<std::istream_iterator<int>, int, std::ptrdiff_t, int*, int&, std::input_iterator_tag>
istream_iterator_test;
//
#if defined(__BORLANDC__) && !defined(__SGI_STL_PORT)
typedef ::std::char_traits<char>::off_type distance;
non_pointer_test<std::ostream_iterator<int>,int,
distance,int*,int&,std::output_iterator_tag> ostream_iterator_test;
#elif defined(BOOST_MSVC_STD_ITERATOR)
non_pointer_test<std::ostream_iterator<int>,
int, void, void, void, std::output_iterator_tag>
ostream_iterator_test;
#else
non_pointer_test<std::ostream_iterator<int>,
void, void, void, void, std::output_iterator_tag>
ostream_iterator_test;
#endif
#ifdef __KCC
typedef long std_list_diff_type;
#else
typedef std::ptrdiff_t std_list_diff_type;
#endif
non_pointer_test<std::list<int>::iterator, int, std_list_diff_type, int*, int&, std::bidirectional_iterator_tag>
list_iterator_test;
maybe_pointer_test<std::vector<int>::iterator, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag>
vector_iterator_test;
maybe_pointer_test<int*, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag>
int_pointer_test;
non_pointer_test<my_iterator1, char, long, const char*, const char&, std::forward_iterator_tag>
my_iterator1_test;
non_pointer_test<my_iterator2, char, long, const char*, const char&, std::forward_iterator_tag>
my_iterator2_test;
non_pointer_test<my_iterator3, char, int, const char*, const char&, std::forward_iterator_tag>
my_iterator3_test;
int main()
{
char chars[100];
int ints[100];
for (std::ptrdiff_t length = 3; length < 100; length += length / 3)
{
std::list<int> l(length);
assert(boost::detail::distance(l.begin(), l.end()) == length);
std::vector<int> v(length);
assert(boost::detail::distance(v.begin(), v.end()) == length);
assert(boost::detail::distance(&ints[0], ints + length) == length);
assert(boost::detail::distance(my_iterator1(chars), my_iterator1(chars + length)) == length);
assert(boost::detail::distance(my_iterator2(chars), my_iterator2(chars + length)) == length);
assert(boost::detail::distance(my_iterator3(chars), my_iterator3(chars + length)) == length);
}
return 0;
}

View File

@ -1,9 +1,10 @@
// Demonstrate and test boost/operators.hpp on std::iterators --------------//
// (C) Copyright Jeremy Siek 1999.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (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.
@ -23,7 +24,7 @@
#include <cstring> // for std::strcmp
#include <iostream> // for std::cout (std::endl, ends, and flush indirectly)
#include <string> // for std::string
#include <sstream> // for std::stringstream
#include <strstream> // for std::ostrstream
# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::strcmp; }
@ -64,16 +65,20 @@ class test_opr_base
protected:
// Test data and types
BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u );
BOOST_STATIC_CONSTANT( std::size_t, scratch_length = 40u );
typedef std::string fruit_array_type[ fruit_length ];
typedef char scratch_array_type[ scratch_length ];
static fruit_array_type fruit;
static scratch_array_type scratch;
}; // test_opr_base
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
// A definition is required even for integral static constants
const std::size_t test_opr_base::fruit_length;
const std::size_t test_opr_base::scratch_length;
#endif
template <typename T, typename R = T&, typename P = T*>
@ -115,6 +120,9 @@ private:
test_opr_base::fruit_array_type
test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" };
test_opr_base::scratch_array_type
test_opr_base::scratch = "";
template <typename T, typename R, typename P>
typename test_opr<T, R, P>::iter_type const
test_opr<T, R, P>::fruit_begin = test_iter<T,R,P>( fruit );
@ -168,13 +176,15 @@ test_opr<T, R, P>::post_increment_test
{
std::cout << "\tDoing post-increment test." << std::endl;
std::stringstream oss;
std::ostrstream oss( scratch, scratch_length );
for ( iter_type i = fruit_begin ; i != fruit_end ; )
{
oss << *i++ << ' ';
}
BOOST_CHECK( oss.str() == "apple orange pear peach grape plum ");
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ")
== 0 );
}
// Test post-decrement
@ -186,14 +196,16 @@ test_opr<T, R, P>::post_decrement_test
{
std::cout << "\tDoing post-decrement test." << std::endl;
std::stringstream oss;
std::ostrstream oss( scratch, scratch_length );
for ( iter_type i = fruit_end ; i != fruit_begin ; )
{
i--;
oss << *i << ' ';
}
BOOST_CHECK( oss.str() == "plum grape peach pear orange apple ");
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "plum grape peach pear orange apple ")
== 0 );
}
// Test indirect structure referral
@ -205,13 +217,14 @@ test_opr<T, R, P>::indirect_referral_test
{
std::cout << "\tDoing indirect reference test." << std::endl;
std::stringstream oss;
std::ostrstream oss( scratch, scratch_length );
for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
{
oss << i->size() << ' ';
}
BOOST_CHECK( oss.str() == "5 6 4 5 5 4 ");
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "5 6 4 5 5 4 ") == 0 );
}
// Test offset addition
@ -224,13 +237,14 @@ test_opr<T, R, P>::offset_addition_test
std::cout << "\tDoing offset addition test." << std::endl;
std::ptrdiff_t const two = 2;
std::stringstream oss;
std::ostrstream oss( scratch, scratch_length );
for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two )
{
oss << *i << ' ';
}
BOOST_CHECK( oss.str() == "apple pear grape ");
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 );
}
// Test offset addition, in reverse order
@ -243,13 +257,14 @@ test_opr<T, R, P>::reverse_offset_addition_test
std::cout << "\tDoing reverse offset addition test." << std::endl;
std::ptrdiff_t const two = 2;
std::stringstream oss;
std::ostrstream oss( scratch, scratch_length );
for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i )
{
oss << *i << ' ';
}
BOOST_CHECK( oss.str() == "apple pear grape ");
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 );
}
// Test offset subtraction
@ -262,7 +277,7 @@ test_opr<T, R, P>::offset_subtraction_test
std::cout << "\tDoing offset subtraction test." << std::endl;
std::ptrdiff_t const two = 2;
std::stringstream oss;
std::ostrstream oss( scratch, scratch_length );
for ( iter_type i = fruit_end ; fruit_begin < i ; )
{
i = i - two;
@ -272,7 +287,8 @@ test_opr<T, R, P>::offset_subtraction_test
}
}
BOOST_CHECK( oss.str() == "grape pear apple ");
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "grape pear apple ") == 0 );
}
// Test comparisons
@ -296,10 +312,10 @@ test_opr<T, R, P>::comparison_test
{
ptrdiff_t const j_offset = j - fruit_begin;
BOOST_CHECK( (i != j) == (i_offset != j_offset) );
BOOST_CHECK( (i > j) == (i_offset > j_offset) );
BOOST_CHECK( (i <= j) == (i_offset <= j_offset) );
BOOST_CHECK( (i >= j) == (i_offset >= j_offset) );
BOOST_TEST( (i != j) == (i_offset != j_offset) );
BOOST_TEST( (i > j) == (i_offset > j_offset) );
BOOST_TEST( (i <= j) == (i_offset <= j_offset) );
BOOST_TEST( (i >= j) == (i_offset >= j_offset) );
}
}
cout << std::endl;
@ -314,11 +330,13 @@ test_opr<T, R, P>::indexing_test
{
std::cout << "\tDoing indexing test." << std::endl;
std::stringstream oss;
std::ostrstream oss( scratch, scratch_length );
for ( std::size_t k = 0u ; k < fruit_length ; ++k )
{
oss << fruit_begin[ k ] << ' ';
}
BOOST_CHECK( oss.str() == "apple orange pear peach grape plum ");
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ")
== 0 );
}

View File

@ -1,8 +1,10 @@
// boost class noncopyable test program ------------------------------------//
// (C) Copyright Beman Dawes 1999. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright boost.org 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.
@ -10,7 +12,7 @@
// 9 Jun 99 Add unnamed namespace
// 2 Jun 99 Initial Version
#include <boost/noncopyable.hpp>
#include <boost/utility.hpp>
#include <iostream>
// This program demonstrates compiler errors resulting from trying to copy

View File

@ -1,7 +1,8 @@
// (C) Copyright David Abrahams 2001.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (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.
@ -57,22 +58,14 @@ struct complement
struct traits
{
private:
// indirection through complement_traits_aux necessary to keep MSVC happy
// indirection through complement_traits_aux neccessary to keep MSVC happy
typedef complement_traits_aux<Number, size - 1> prev;
public:
#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 2
// GCC 4.0.2 ICEs on these C-style casts
BOOST_STATIC_CONSTANT(Number, max =
Number((prev::max) << CHAR_BIT)
+ Number(UCHAR_MAX));
BOOST_STATIC_CONSTANT(Number, min = Number((prev::min) << CHAR_BIT));
#else
BOOST_STATIC_CONSTANT(Number, max =
Number(Number(prev::max) << CHAR_BIT)
+ Number(UCHAR_MAX));
BOOST_STATIC_CONSTANT(Number, min = Number(Number(prev::min) << CHAR_BIT));
#endif
};
};
@ -221,7 +214,7 @@ struct signed_tag {};
// Tests for unsigned numbers. The extra default Number parameter works around
// an MSVC bug.
template <class Number>
void test_aux(unsigned_tag, Number*)
void test_aux(unsigned_tag, Number* = 0)
{
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
BOOST_STATIC_ASSERT(!boost::detail::is_signed<Number>::value);
@ -229,16 +222,10 @@ void test_aux(unsigned_tag, Number*)
(sizeof(Number) < sizeof(boost::intmax_t))
| (boost::is_same<difference_type, boost::intmax_t>::value));
#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 2
// GCC 4.0.2 ICEs on this C-style cases
BOOST_STATIC_ASSERT((complement_traits<Number>::max) > Number(0));
BOOST_STATIC_ASSERT((complement_traits<Number>::min) == Number(0));
#else
// Force casting to Number here to work around the fact that it's an enum on MSVC
BOOST_STATIC_ASSERT(Number(complement_traits<Number>::max) > Number(0));
BOOST_STATIC_ASSERT(Number(complement_traits<Number>::min) == Number(0));
#endif
const Number max = complement_traits<Number>::max;
const Number min = complement_traits<Number>::min;
@ -269,7 +256,7 @@ struct in_range_tag {};
// This test morsel gets executed for numbers whose difference will always be
// representable in intmax_t
template <class Number>
void signed_test(in_range_tag, Number*)
void signed_test(in_range_tag, Number* = 0)
{
BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
@ -290,7 +277,7 @@ void signed_test(in_range_tag, Number*)
// This test morsel gets executed for numbers whose difference may exceed the
// capacity of intmax_t.
template <class Number>
void signed_test(out_of_range_tag, Number*)
void signed_test(out_of_range_tag, Number* = 0)
{
BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
@ -314,7 +301,7 @@ void signed_test(out_of_range_tag, Number*)
}
template <class Number>
void test_aux(signed_tag, Number*)
void test_aux(signed_tag, Number* = 0)
{
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
@ -322,15 +309,10 @@ void test_aux(signed_tag, Number*)
(sizeof(Number) < sizeof(boost::intmax_t))
| (boost::is_same<difference_type, Number>::value));
#if defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 2
// GCC 4.0.2 ICEs on this cast
BOOST_STATIC_ASSERT((complement_traits<Number>::max) > Number(0));
BOOST_STATIC_ASSERT((complement_traits<Number>::min) < Number(0));
#else
// Force casting to Number here to work around the fact that it's an enum on MSVC
BOOST_STATIC_ASSERT(Number(complement_traits<Number>::max) > Number(0));
BOOST_STATIC_ASSERT(Number(complement_traits<Number>::min) < Number(0));
#endif
const Number max = complement_traits<Number>::max;
const Number min = complement_traits<Number>::min;
@ -346,7 +328,7 @@ void test_aux(signed_tag, Number*)
out_of_range_tag
>::type
range_tag;
signed_test<Number>(range_tag(), 0);
signed_test<Number>(range_tag());
}
@ -365,7 +347,7 @@ void test(Number* = 0)
// factoring out difference_type for the assert below confused Borland :(
typedef boost::detail::is_signed<
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
#ifndef BOOST_MSVC
typename
#endif
boost::detail::numeric_traits<Number>::difference_type
@ -376,7 +358,7 @@ void test(Number* = 0)
boost::detail::is_signed<Number>::value
>::template then<signed_tag, unsigned_tag>::type signedness;
test_aux<Number>(signedness(), 0);
test_aux<Number>(signedness());
std::cout << "passed" << std::endl;
}
@ -393,8 +375,8 @@ int main()
test<long>();
test<unsigned long>();
#if defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_INTEGRAL_INT64_T)
test< ::boost::long_long_type>();
test< ::boost::ulong_long_type>();
test<long long>();
test<unsigned long long>();
#elif defined(BOOST_MSVC)
// The problem of not having compile-time static class constants other than
// enums prevents this from working, since values get truncated.

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,11 @@
// Demonstrate and test boost/operators.hpp -------------------------------//
// Copyright Beman Dawes 1999. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright Beman Dawes 1999. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
// See http://www.boost.org/libs/utility for documentation.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 01 Oct 01 Added tests for "left" operators
@ -269,17 +270,17 @@ namespace
template <class X1, class Y1, class X2, class Y2>
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
BOOST_CHECK( true_value(y1) == true_value(y2) );
BOOST_CHECK( true_value(x1) == true_value(x2) );
BOOST_TEST( true_value(y1) == true_value(y2) );
BOOST_TEST( true_value(x1) == true_value(x2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
BOOST_CHECK( (x1 < y1) == (x2 < y2) );
BOOST_CHECK( (x1 <= y1) == (x2 <= y2) );
BOOST_CHECK( (x1 >= y1) == (x2 >= y2) );
BOOST_CHECK( (x1 > y1) == (x2 > y2) );
BOOST_TEST( (x1 < y1) == (x2 < y2) );
BOOST_TEST( (x1 <= y1) == (x2 <= y2) );
BOOST_TEST( (x1 >= y1) == (x2 >= y2) );
BOOST_TEST( (x1 > y1) == (x2 > y2) );
}
template <class X1, class Y1, class X2, class Y2>
@ -293,8 +294,8 @@ namespace
template <class X1, class Y1, class X2, class Y2>
void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
BOOST_CHECK( (x1 == y1) == (x2 == y2) );
BOOST_CHECK( (x1 != y1) == (x2 != y2) );
BOOST_TEST( (x1 == y1) == (x2 == y2) );
BOOST_TEST( (x1 != y1) == (x2 != y2) );
}
template <class X1, class Y1, class X2, class Y2>
@ -308,7 +309,7 @@ namespace
template <class X1, class Y1, class X2, class Y2>
void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
BOOST_CHECK( (x1 * y1).value() == (x2 * y2) );
BOOST_TEST( (x1 * y1).value() == (x2 * y2) );
}
template <class X1, class Y1, class X2, class Y2>
@ -318,20 +319,11 @@ namespace
test_multipliable_aux( x1, y1, x2, y2 );
test_multipliable_aux( y1, x1, y2, x2 );
}
template <class A, class B>
void test_value_equality(A a, B b)
{
BOOST_CHECK(a.value() == b);
}
#define TEST_OP_R(op) test_value_equality(x1 op y1, x2 op y2)
#define TEST_OP_L(op) test_value_equality(y1 op x1, y2 op x2)
template <class X1, class Y1, class X2, class Y2>
void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
TEST_OP_R(+);
BOOST_TEST( (x1 + y1).value() == (x2 + y2) );
}
template <class X1, class Y1, class X2, class Y2>
@ -341,19 +333,19 @@ namespace
test_addable_aux( x1, y1, x2, y2 );
test_addable_aux( y1, x1, y2, x2 );
}
template <class X1, class Y1, class X2, class Y2>
void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
TEST_OP_R(-);
BOOST_TEST( (x1 - y1).value() == (x2 - y2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_subtractable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
TEST_OP_L(-);
BOOST_TEST( (y1 - x1).value() == (y2 - x2) );
}
template <class X1, class Y1, class X2, class Y2>
@ -361,7 +353,7 @@ namespace
{
sanity_check( x1, y1, x2, y2 );
if ( y2 != 0 )
TEST_OP_R(/);
BOOST_TEST( (x1 / y1).value() == (x2 / y2) );
}
template <class X1, class Y1, class X2, class Y2>
@ -369,7 +361,7 @@ namespace
{
sanity_check( x1, y1, x2, y2 );
if ( x2 != 0 )
TEST_OP_L(/);
BOOST_TEST( (y1 / x1).value() == (y2 / x2) );
}
template <class X1, class Y1, class X2, class Y2>
@ -377,7 +369,7 @@ namespace
{
sanity_check( x1, y1, x2, y2 );
if ( y2 != 0 )
TEST_OP_R(%);
BOOST_TEST( (x1 % y1).value() == (x2 % y2) );
}
template <class X1, class Y1, class X2, class Y2>
@ -385,13 +377,13 @@ namespace
{
sanity_check( x1, y1, x2, y2 );
if ( x2 != 0 )
TEST_OP_L(%);
BOOST_TEST( (y1 % x1).value() == (y2 % x2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
TEST_OP_R(^);
BOOST_TEST( (x1 ^ y1).value() == (x2 ^ y2) );
}
template <class X1, class Y1, class X2, class Y2>
@ -405,7 +397,7 @@ namespace
template <class X1, class Y1, class X2, class Y2>
void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
TEST_OP_R(&);
BOOST_TEST( (x1 & y1).value() == (x2 & y2) );
}
template <class X1, class Y1, class X2, class Y2>
@ -419,7 +411,7 @@ namespace
template <class X1, class Y1, class X2, class Y2>
void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
TEST_OP_R(|);
BOOST_TEST( (x1 | y1).value() == (x2 | y2) );
}
template <class X1, class Y1, class X2, class Y2>
@ -434,30 +426,30 @@ namespace
void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
TEST_OP_R(<<);
BOOST_TEST( (x1 << y1).value() == (x2 << y2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
TEST_OP_R(>>);
BOOST_TEST( (x1 >> y1).value() == (x2 >> y2) );
}
template <class X1, class X2>
void test_incrementable(X1 x1, X2 x2)
{
sanity_check( x1, x1, x2, x2 );
BOOST_CHECK( (x1++).value() == x2++ );
BOOST_CHECK( x1.value() == x2 );
BOOST_TEST( (x1++).value() == x2++ );
BOOST_TEST( x1.value() == x2 );
}
template <class X1, class X2>
void test_decrementable(X1 x1, X2 x2)
{
sanity_check( x1, x1, x2, x2 );
BOOST_CHECK( (x1--).value() == x2-- );
BOOST_CHECK( x1.value() == x2 );
BOOST_TEST( (x1--).value() == x2-- );
BOOST_TEST( x1.value() == x2 );
}
template <class X1, class Y1, class X2, class Y2>
@ -536,7 +528,7 @@ namespace
// inherited operator templates at the moment it must, so the following
// explicit instantiations force it to do that.
#if defined(BOOST_MSVC) && (_MSC_VER < 1300)
#if defined(BOOST_MSVC) && (_MSC_VER <= 1200)
template Wrapped1<int>;
template Wrapped1<long>;
template Wrapped1<unsigned int>;
@ -561,7 +553,8 @@ template Wrapped6<unsigned long, unsigned char>;
template Wrapped6<unsigned int, unsigned char>;
#endif
#define PRIVATE_EXPR_TEST(e, t) BOOST_CHECK( ((e), (t)) )
#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) )
int
test_main( int , char * [] )
@ -576,7 +569,7 @@ test_main( int , char * [] )
cout << "Created point, and operated on it." << endl;
for (int n = 0; n < 1000; ++n) // was 10,000 but took too long (Beman)
for (int n = 0; n < 10000; ++n)
{
boost::minstd_rand r;
tester<long, int>()(r);
@ -606,22 +599,22 @@ test_main( int , char * [] )
MyInt i2(2);
MyInt i;
BOOST_CHECK( i1.value() == 1 );
BOOST_CHECK( i2.value() == 2 );
BOOST_CHECK( i.value() == 0 );
BOOST_TEST( i1.value() == 1 );
BOOST_TEST( i2.value() == 2 );
BOOST_TEST( i.value() == 0 );
cout << "Created MyInt objects.\n";
PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) );
BOOST_CHECK( i2 == i );
BOOST_CHECK( i1 != i2 );
BOOST_CHECK( i1 < i2 );
BOOST_CHECK( i1 <= i2 );
BOOST_CHECK( i <= i2 );
BOOST_CHECK( i2 > i1 );
BOOST_CHECK( i2 >= i1 );
BOOST_CHECK( i2 >= i );
BOOST_TEST( i2 == i );
BOOST_TEST( i1 != i2 );
BOOST_TEST( i1 < i2 );
BOOST_TEST( i1 <= i2 );
BOOST_TEST( i <= i2 );
BOOST_TEST( i2 > i1 );
BOOST_TEST( i2 >= i1 );
BOOST_TEST( i2 >= i );
PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) );
PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) );
@ -638,93 +631,93 @@ test_main( int , char * [] )
PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) );
PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) );
cout << "Performed tests on MyInt objects.\n";
MyLong j1(1);
MyLong j2(2);
MyLong j;
BOOST_CHECK( j1.value() == 1 );
BOOST_CHECK( j2.value() == 2 );
BOOST_CHECK( j.value() == 0 );
BOOST_TEST( j1.value() == 1 );
BOOST_TEST( j2.value() == 2 );
BOOST_TEST( j.value() == 0 );
cout << "Created MyLong objects.\n";
PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) );
BOOST_CHECK( j2 == j );
BOOST_CHECK( 2 == j );
BOOST_CHECK( j2 == 2 );
BOOST_CHECK( j == j2 );
BOOST_CHECK( j1 != j2 );
BOOST_CHECK( j1 != 2 );
BOOST_CHECK( 1 != j2 );
BOOST_CHECK( j1 < j2 );
BOOST_CHECK( 1 < j2 );
BOOST_CHECK( j1 < 2 );
BOOST_CHECK( j1 <= j2 );
BOOST_CHECK( 1 <= j2 );
BOOST_CHECK( j1 <= j );
BOOST_CHECK( j <= j2 );
BOOST_CHECK( 2 <= j2 );
BOOST_CHECK( j <= 2 );
BOOST_CHECK( j2 > j1 );
BOOST_CHECK( 2 > j1 );
BOOST_CHECK( j2 > 1 );
BOOST_CHECK( j2 >= j1 );
BOOST_CHECK( 2 >= j1 );
BOOST_CHECK( j2 >= 1 );
BOOST_CHECK( j2 >= j );
BOOST_CHECK( 2 >= j );
BOOST_CHECK( j2 >= 2 );
BOOST_TEST( j2 == j );
BOOST_TEST( 2 == j );
BOOST_TEST( j2 == 2 );
BOOST_TEST( j == j2 );
BOOST_TEST( j1 != j2 );
BOOST_TEST( j1 != 2 );
BOOST_TEST( 1 != j2 );
BOOST_TEST( j1 < j2 );
BOOST_TEST( 1 < j2 );
BOOST_TEST( j1 < 2 );
BOOST_TEST( j1 <= j2 );
BOOST_TEST( 1 <= j2 );
BOOST_TEST( j1 <= j );
BOOST_TEST( j <= j2 );
BOOST_TEST( 2 <= j2 );
BOOST_TEST( j <= 2 );
BOOST_TEST( j2 > j1 );
BOOST_TEST( 2 > j1 );
BOOST_TEST( j2 > 1 );
BOOST_TEST( j2 >= j1 );
BOOST_TEST( 2 >= j1 );
BOOST_TEST( j2 >= 1 );
BOOST_TEST( j2 >= j );
BOOST_TEST( 2 >= j );
BOOST_TEST( j2 >= 2 );
BOOST_CHECK( (j1 + 2) == 3 );
BOOST_CHECK( (1 + j2) == 3 );
BOOST_TEST( (j1 + 2) == 3 );
BOOST_TEST( (1 + j2) == 3 );
PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) );
BOOST_CHECK( (j + 2) == 5 );
BOOST_CHECK( (3 + j2) == 5 );
BOOST_TEST( (j + 2) == 5 );
BOOST_TEST( (3 + j2) == 5 );
PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) );
BOOST_CHECK( (j - 1) == 4 );
BOOST_TEST( (j - 1) == 4 );
PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) );
BOOST_CHECK( (j * 2) == 8 );
BOOST_CHECK( (4 * j2) == 8 );
BOOST_TEST( (j * 2) == 8 );
BOOST_TEST( (4 * j2) == 8 );
PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) );
BOOST_CHECK( (j / 2) == 4 );
BOOST_TEST( (j / 2) == 4 );
PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) );
BOOST_CHECK( (j % 3) == 1 );
BOOST_TEST( (j % 3) == 1 );
PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) );
PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) );
BOOST_CHECK( (1 | j2 | j) == 7 );
BOOST_CHECK( (j1 | 2 | j) == 7 );
BOOST_CHECK( (j1 | j2 | 4) == 7 );
BOOST_TEST( (1 | j2 | j) == 7 );
BOOST_TEST( (j1 | 2 | j) == 7 );
BOOST_TEST( (j1 | j2 | 4) == 7 );
PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) );
BOOST_CHECK( (7 & j2) == 2 );
BOOST_CHECK( (j & 2) == 2 );
BOOST_TEST( (7 & j2) == 2 );
BOOST_TEST( (j & 2) == 2 );
PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) );
PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) );
BOOST_CHECK( (3 ^ j1) == 2 );
BOOST_CHECK( (j ^ 1) == 2 );
BOOST_TEST( (3 ^ j1) == 2 );
BOOST_TEST( (j ^ 1) == 2 );
PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) );
PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) );
BOOST_CHECK( (j1 << 2) == 4 );
BOOST_CHECK( (j2 << 1) == 4 );
BOOST_TEST( (j1 << 2) == 4 );
BOOST_TEST( (j2 << 1) == 4 );
PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) );
BOOST_CHECK( (j >> 2) == 1 );
BOOST_CHECK( (j2 >> 1) == 1 );
BOOST_TEST( (j >> 2) == 1 );
BOOST_TEST( (j2 >> 1) == 1 );
PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) );
cout << "Performed tests on MyLong objects.\n";
@ -733,22 +726,22 @@ test_main( int , char * [] )
MyChar k2(2);
MyChar k;
BOOST_CHECK( k1.value() == 1 );
BOOST_CHECK( k2.value() == 2 );
BOOST_CHECK( k.value() == 0 );
BOOST_TEST( k1.value() == 1 );
BOOST_TEST( k2.value() == 2 );
BOOST_TEST( k.value() == 0 );
cout << "Created MyChar objects.\n";
PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) );
BOOST_CHECK( k2 == k );
BOOST_CHECK( k1 != k2 );
BOOST_CHECK( k1 < k2 );
BOOST_CHECK( k1 <= k2 );
BOOST_CHECK( k <= k2 );
BOOST_CHECK( k2 > k1 );
BOOST_CHECK( k2 >= k1 );
BOOST_CHECK( k2 >= k );
BOOST_TEST( k2 == k );
BOOST_TEST( k1 != k2 );
BOOST_TEST( k1 < k2 );
BOOST_TEST( k1 <= k2 );
BOOST_TEST( k <= k2 );
BOOST_TEST( k2 > k1 );
BOOST_TEST( k2 >= k1 );
BOOST_TEST( k2 >= k );
cout << "Performed tests on MyChar objects.\n";
@ -756,39 +749,39 @@ test_main( int , char * [] )
MyShort l2(2);
MyShort l;
BOOST_CHECK( l1.value() == 1 );
BOOST_CHECK( l2.value() == 2 );
BOOST_CHECK( l.value() == 0 );
BOOST_TEST( l1.value() == 1 );
BOOST_TEST( l2.value() == 2 );
BOOST_TEST( l.value() == 0 );
cout << "Created MyShort objects.\n";
PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) );
BOOST_CHECK( l2 == l );
BOOST_CHECK( 2 == l );
BOOST_CHECK( l2 == 2 );
BOOST_CHECK( l == l2 );
BOOST_CHECK( l1 != l2 );
BOOST_CHECK( l1 != 2 );
BOOST_CHECK( 1 != l2 );
BOOST_CHECK( l1 < l2 );
BOOST_CHECK( 1 < l2 );
BOOST_CHECK( l1 < 2 );
BOOST_CHECK( l1 <= l2 );
BOOST_CHECK( 1 <= l2 );
BOOST_CHECK( l1 <= l );
BOOST_CHECK( l <= l2 );
BOOST_CHECK( 2 <= l2 );
BOOST_CHECK( l <= 2 );
BOOST_CHECK( l2 > l1 );
BOOST_CHECK( 2 > l1 );
BOOST_CHECK( l2 > 1 );
BOOST_CHECK( l2 >= l1 );
BOOST_CHECK( 2 >= l1 );
BOOST_CHECK( l2 >= 1 );
BOOST_CHECK( l2 >= l );
BOOST_CHECK( 2 >= l );
BOOST_CHECK( l2 >= 2 );
BOOST_TEST( l2 == l );
BOOST_TEST( 2 == l );
BOOST_TEST( l2 == 2 );
BOOST_TEST( l == l2 );
BOOST_TEST( l1 != l2 );
BOOST_TEST( l1 != 2 );
BOOST_TEST( 1 != l2 );
BOOST_TEST( l1 < l2 );
BOOST_TEST( 1 < l2 );
BOOST_TEST( l1 < 2 );
BOOST_TEST( l1 <= l2 );
BOOST_TEST( 1 <= l2 );
BOOST_TEST( l1 <= l );
BOOST_TEST( l <= l2 );
BOOST_TEST( 2 <= l2 );
BOOST_TEST( l <= 2 );
BOOST_TEST( l2 > l1 );
BOOST_TEST( 2 > l1 );
BOOST_TEST( l2 > 1 );
BOOST_TEST( l2 >= l1 );
BOOST_TEST( 2 >= l1 );
BOOST_TEST( l2 >= 1 );
BOOST_TEST( l2 >= l );
BOOST_TEST( 2 >= l );
BOOST_TEST( l2 >= 2 );
cout << "Performed tests on MyShort objects.\n";
@ -798,44 +791,44 @@ test_main( int , char * [] )
MyDoubleInt di;
MyDoubleInt tmp;
BOOST_CHECK( di1.value() == 1 );
BOOST_CHECK( di2.value() == 2 );
BOOST_CHECK( di2.value() == 2 );
BOOST_CHECK( di.value() == 0 );
BOOST_TEST( di1.value() == 1 );
BOOST_TEST( di2.value() == 2 );
BOOST_TEST( di2.value() == 2 );
BOOST_TEST( di.value() == 0 );
cout << "Created MyDoubleInt objects.\n";
PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) );
BOOST_CHECK( di2 == di );
BOOST_CHECK( 2 == di );
BOOST_CHECK( di == 2 );
BOOST_CHECK( di1 < di2 );
BOOST_CHECK( 1 < di2 );
BOOST_CHECK( di1 <= di2 );
BOOST_CHECK( 1 <= di2 );
BOOST_CHECK( di2 > di1 );
BOOST_CHECK( di2 > 1 );
BOOST_CHECK( di2 >= di1 );
BOOST_CHECK( di2 >= 1 );
BOOST_CHECK( di1 / di2 == half );
BOOST_CHECK( di1 / 2 == half );
BOOST_CHECK( 1 / di2 == half );
BOOST_TEST( di2 == di );
BOOST_TEST( 2 == di );
BOOST_TEST( di == 2 );
BOOST_TEST( di1 < di2 );
BOOST_TEST( 1 < di2 );
BOOST_TEST( di1 <= di2 );
BOOST_TEST( 1 <= di2 );
BOOST_TEST( di2 > di1 );
BOOST_TEST( di2 > 1 );
BOOST_TEST( di2 >= di1 );
BOOST_TEST( di2 >= 1 );
BOOST_TEST( di1 / di2 == half );
BOOST_TEST( di1 / 2 == half );
BOOST_TEST( 1 / di2 == half );
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=2) == half) );
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=di2) == half) );
BOOST_CHECK( di1 * di2 == di2 );
BOOST_CHECK( di1 * 2 == di2 );
BOOST_CHECK( 1 * di2 == di2 );
BOOST_TEST( di1 * di2 == di2 );
BOOST_TEST( di1 * 2 == di2 );
BOOST_TEST( 1 * di2 == di2 );
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=2) == di2) );
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=di2) == di2) );
BOOST_CHECK( di2 - di1 == di1 );
BOOST_CHECK( di2 - 1 == di1 );
BOOST_CHECK( 2 - di1 == di1 );
BOOST_TEST( di2 - di1 == di1 );
BOOST_TEST( di2 - 1 == di1 );
BOOST_TEST( 2 - di1 == di1 );
PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=1) == di1) );
PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=di1) == di1) );
BOOST_CHECK( di1 + di1 == di2 );
BOOST_CHECK( di1 + 1 == di2 );
BOOST_CHECK( 1 + di1 == di2 );
BOOST_TEST( di1 + di1 == di2 );
BOOST_TEST( di1 + 1 == di2 );
BOOST_TEST( 1 + di1 == di2 );
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=1) == di2) );
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=di1) == di2) );
@ -846,48 +839,48 @@ test_main( int , char * [] )
MyLongInt li;
MyLongInt tmp2;
BOOST_CHECK( li1.value() == 1 );
BOOST_CHECK( li2.value() == 2 );
BOOST_CHECK( li.value() == 0 );
BOOST_TEST( li1.value() == 1 );
BOOST_TEST( li2.value() == 2 );
BOOST_TEST( li.value() == 0 );
cout << "Created MyLongInt objects.\n";
PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) );
BOOST_CHECK( li2 == li );
BOOST_CHECK( 2 == li );
BOOST_CHECK( li == 2 );
BOOST_CHECK( li1 < li2 );
BOOST_CHECK( 1 < li2 );
BOOST_CHECK( li1 <= li2 );
BOOST_CHECK( 1 <= li2 );
BOOST_CHECK( li2 > li1 );
BOOST_CHECK( li2 > 1 );
BOOST_CHECK( li2 >= li1 );
BOOST_CHECK( li2 >= 1 );
BOOST_CHECK( li1 % li2 == li1 );
BOOST_CHECK( li1 % 2 == li1 );
BOOST_CHECK( 1 % li2 == li1 );
BOOST_TEST( li2 == li );
BOOST_TEST( 2 == li );
BOOST_TEST( li == 2 );
BOOST_TEST( li1 < li2 );
BOOST_TEST( 1 < li2 );
BOOST_TEST( li1 <= li2 );
BOOST_TEST( 1 <= li2 );
BOOST_TEST( li2 > li1 );
BOOST_TEST( li2 > 1 );
BOOST_TEST( li2 >= li1 );
BOOST_TEST( li2 >= 1 );
BOOST_TEST( li1 % li2 == li1 );
BOOST_TEST( li1 % 2 == li1 );
BOOST_TEST( 1 % li2 == li1 );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=2) == li1) );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=li2) == li1) );
BOOST_CHECK( li1 / li2 == 0 );
BOOST_CHECK( li1 / 2 == 0 );
BOOST_CHECK( 1 / li2 == 0 );
BOOST_TEST( li1 / li2 == 0 );
BOOST_TEST( li1 / 2 == 0 );
BOOST_TEST( 1 / li2 == 0 );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=2) == 0) );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=li2) == 0) );
BOOST_CHECK( li1 * li2 == li2 );
BOOST_CHECK( li1 * 2 == li2 );
BOOST_CHECK( 1 * li2 == li2 );
BOOST_TEST( li1 * li2 == li2 );
BOOST_TEST( li1 * 2 == li2 );
BOOST_TEST( 1 * li2 == li2 );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=2) == li2) );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=li2) == li2) );
BOOST_CHECK( li2 - li1 == li1 );
BOOST_CHECK( li2 - 1 == li1 );
BOOST_CHECK( 2 - li1 == li1 );
BOOST_TEST( li2 - li1 == li1 );
BOOST_TEST( li2 - 1 == li1 );
BOOST_TEST( 2 - li1 == li1 );
PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=1) == li1) );
PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=li1) == li1) );
BOOST_CHECK( li1 + li1 == li2 );
BOOST_CHECK( li1 + 1 == li2 );
BOOST_CHECK( 1 + li1 == li2 );
BOOST_TEST( li1 + li1 == li2 );
BOOST_TEST( li1 + 1 == li2 );
BOOST_TEST( 1 + li1 == li2 );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=1) == li2) );
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=li1) == li2) );

177
permutation_iterator.htm Normal file
View File

@ -0,0 +1,177 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>Permutation Iterator Adaptor Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1>Permutation Iterator Adaptor</h1>
<p>Defined in header <a href="../../boost/permutation_iterator.hpp">boost/permutation_iterator.hpp</a></p>
<p>The permutation iterator adaptor provides an iterator to a permutation of a given range.
(<a href="http://www.cut-the-knot.com/do_you_know/permutation.html">see definition of permutation</a>).
The adaptor takes two arguments
<ul>
<li>an iterator to the range V on which the <a href="http://www.cut-the-knot.com/do_you_know/permutation.html">permutation</a> will be applied</li>
<li>the reindexing scheme that defines how the elements of V will be permuted.</li>
</ul>
<p>Note that the permutation iterator is not limited to strict permutations of the given range V.
The distance between begin and end of the reindexing iterators is allowed to be smaller compared to the
size of the range V, in which case the permutation iterator only provides a permutation of a subrange of V.
The indexes neither need to be unique. In this same context, it must be noted that the past the end permutation iterator is
completely defined by means of the past-the-end iterator to the indices</p>
<h2>Synopsis</h2>
<blockquote>
<pre>
namespace boost {
template &lt;class IndexIterator&gt;
class permutation_iterator_policies;
template &lt;class ElementIterator, class IndexIterator&gt;
class permutation_iterator_generator;
template &lt;class ElementIterator, class IndexIterator&gt;
typename permutation_iterator_generator&lt;ElementIterator, IndexIterator&gt;::type
make_permutation_iterator(ElementIterator&amp; base, IndexIterator&amp; indexing);
}
</pre>
</blockquote>
<h2>The Permutation Iterator Generator Class Template</h2>
<p>The <code>permutation_iterator_generator</code> is a helper class whose purpose
is to construct a permutation iterator <strong>type</strong>. This class has
two template arguments, the first being the iterator type over the range V, the
second being the type of the iterator over the indices.
<blockquote>
<pre>
template &lt;class ElementIterator, class IndexIterator&gt;
class permutation_iterator_generator
{
public:
typedef <a href="iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt...&gt; type; // the resulting permutation iterator type
}
</pre>
</blockquote>
<h3>Template Parameters</h3>
<table border>
<tr>
<th>Parameter</th>
<th>Description</th>
</tr>
<tr>
<td><tt>ElementIterator</tt></td>
<td>The iterator over the elements to be permuted. This type must be a model
of <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a></td>
</td>
<tr>
<td><tt>IndexIterator</tt></td>
<td>The iterator over the new indexing scheme. This type must at least be a model
of <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>.
The <code>IndexIterator::value_type</code> must be convertible to the
<code>ElementIterator::difference_type</code>.</td>
</table>
<h3>Concept Model</h3>
The permutation iterator is always a model of the same concept as the IndexIterator.
<h3>Members</h3>
The permutation iterator implements the member functions
and operators required for the
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterator</a>
concept. However, the permutation iterator can only meet the complexity guarantees
of the same concept as the IndexIterator. Thus for instance, although the permutation
iterator provides <code>operator+=(distance)</code>, this operation will take linear time
in case the IndexIterator is a model of ForwardIterator instead of amortized constant time.
<br>
<h2><a name="make_generator_iterator">The Permutation Iterator Object Generator</a></h2>
The <code>make_permutation_iterator()</code> function provides a
convenient way to create permutation iterator objects. The function
saves the user the trouble of explicitly writing out the iterator
types.
<blockquote>
<pre>
template &lt;class ElementIterator, class IndexIterator &gt;
typename permutation_iterator_generator&lt;ElementIterator, IndexIterator&gt;::type
make_permutation_iterator(ElementIterator&amp; base, IndexIterator&amp; indices);
</pre>
</blockquote>
<h2>Example</h2>
<blockquote>
<pre>
using namespace boost;
int i = 0;
typedef std::vector< int > element_range_type;
typedef std::list< int > index_type;
static const int element_range_size = 10;
static const int index_size = 4;
element_range_type elements( element_range_size );
for(element_range_type::iterator el_it = elements.begin() ; el_it != elements.end() ; ++el_it) *el_it = std::distance(elements.begin(), el_it);
index_type indices( index_size );
for(index_type::iterator i_it = indices.begin() ; i_it != indices.end() ; ++i_it ) *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it);
std::reverse( indices.begin(), indices.end() );
typedef permutation_iterator_generator< element_range_type::iterator, index_type::iterator >::type permutation_type;
permutation_type begin = make_permutation_iterator( elements.begin(), indices.begin() );
permutation_type it = begin;
permutation_type end = make_permutation_iterator( elements.begin(), indices.end() );
std::cout << "The original range is : ";
std::copy( elements.begin(), elements.end(), std::ostream_iterator< int >( std::cout, " " ) );
std::cout << "\n";
std::cout << "The reindexing scheme is : ";
std::copy( indices.begin(), indices.end(), std::ostream_iterator< int >( std::cout, " " ) );
std::cout << "\n";
std::cout << "The permutated range is : ";
std::copy( begin, end, std::ostream_iterator< int >( std::cout, " " ) );
std::cout << "\n";
std::cout << "Elements at even indices in the permutation : ";
it = begin;
for(i = 0; i < index_size / 2 ; ++i, it+=2 ) std::cout << *it << " ";
std::cout << "\n";
std::cout << "Permutation backwards : ";
it = begin + (index_size);
assert( it != begin );
for( ; it-- != begin ; ) std::cout << *it << " ";
std::cout << "\n";
std::cout << "Iterate backward with stride 2 : ";
it = begin + (index_size - 1);
for(i = 0 ; i < index_size / 2 ; ++i, it-=2 ) std::cout << *it << " ";
std::cout << "\n";
</pre>
</blockquote>
<br><br><br><hr>
Thanks: The permutation iterator is only a small addition to the superb iterator adaptors
library of David Abrahams and Jeremy Siek.
<br><br>
Copyright 2001 Toon Knapen.
</body>
</html>

391
projection_iterator.htm Normal file
View File

@ -0,0 +1,391 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Projection Iterator Adaptor Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
align="center" width="277" height="86">
<h1>Projection Iterator Adaptor</h1>
Defined in header
<a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
<p>
The projection iterator adaptor is similar to the <a
href="./transform_iterator.htm">transform iterator adaptor</a> in that
its <tt>operator*()</tt> applies some function to the result of
dereferencing the base iterator and then returns the result. The
difference is that the function must return a reference to some
existing object (for example, a data member within the
<tt>value_type</tt> of the base iterator). The following
<b>pseudo-code</b> gives the basic idea. The data member <tt>p</tt> is
the function object.
<pre>
reference projection_iterator::operator*() const {
return this->p(*this->base_iterator);
}
</pre>
<h2>Synopsis</h2>
<pre>
namespace boost {
template &lt;class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator&gt;
struct projection_iterator_generator;
template &lt;class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>,
class BaseIterator, class ConstBaseIterator&gt;
struct projection_iterator_pair_generator;
template &lt;class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator&gt;
typename projection_iterator_generator&lt;AdaptableUnaryFunction, BaseIterator&gt;::type
make_projection_iterator(BaseIterator base,
const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
template &lt;class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class ConstBaseIterator&gt;
typename projection_iterator_generator&lt;AdaptableUnaryFunction, ConstBaseIterator&gt;::type
make_const_projection_iterator(ConstBaseIterator base,
const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
}
</pre>
<hr>
<h2><a name="projection_iterator_generator">The Projection Iterator Type
Generator</a></h2>
The class <tt>projection_iterator_generator</tt> is a helper class
whose purpose is to construct an projection iterator type. The main
template parameter for this class is the <a
href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a>
function object type and the <tt>BaseIterator</tt> type that is being
wrapped.
<pre>
template &lt;class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator&gt;
class projection_iterator_generator
{
public:
typedef <tt><a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt...&gt;</tt> type; // the resulting projection iterator type
};
</pre>
<h3>Example</h3>
In the following example we have a list of personnel records. Each
record has an employee's name and ID number. We want to be able to
traverse through the list accessing either the name or the ID numbers
of the employees using the projection iterator so we create the
function object classes <tt>select_name</tt> and
<tt>select_ID</tt>. We then use the
<tt>projection_iterator_generator</tt> class to create a projection
iterator and use it to print out the names of the employees.
<pre>
#include &lt;boost/config.hpp&gt;
#include &lt;list&gt;
#include &lt;iostream&gt;
#include &lt;iterator&gt;
#include &lt;algorithm&gt;
#include &lt;string&gt;
#include &lt;boost/iterator_adaptors.hpp&gt;
struct personnel_record {
personnel_record(std::string n, int id) : m_name(n), m_ID(id) { }
std::string m_name;
int m_ID;
};
struct select_name {
typedef personnel_record argument_type;
typedef std::string result_type;
const std::string&amp; operator()(const personnel_record&amp; r) const {
return r.m_name;
}
std::string&amp; operator()(personnel_record&amp; r) const {
return r.m_name;
}
};
struct select_ID {
typedef personnel_record argument_type;
typedef int result_type;
const int&amp; operator()(const personnel_record&amp; r) const {
return r.m_ID;
}
int&amp; operator()(personnel_record&amp; r) const {
return r.m_ID;
}
};
int main(int, char*[])
{
std::list&lt;personnel_record&gt; personnel_list;
personnel_list.push_back(personnel_record("Barney", 13423));
personnel_list.push_back(personnel_record("Fred", 12343));
personnel_list.push_back(personnel_record("Wilma", 62454));
personnel_list.push_back(personnel_record("Betty", 20490));
// Example of using projection_iterator_generator
// to print out the names in the personnel list.
boost::projection_iterator_generator&lt;select_name,
std::list&lt;personnel_record&gt;::iterator&gt;::type
personnel_first(personnel_list.begin()),
personnel_last(personnel_list.end());
std::copy(personnel_first, personnel_last,
std::ostream_iterator&lt;std::string&gt;(std::cout, "\n"));
std::cout &lt;&lt; std::endl;
// to be continued...
</pre>
The output for this part is:
<pre>
Barney
Fred
Wilma
Betty
</pre>
<h3>Template Parameters</h3>
<Table border>
<TR>
<TH>Parameter</TH><TH>Description</TH>
</TR>
<TR>
<TD><a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a></TD>
<TD>The type of the function object. The <tt>argument_type</tt> of the
function must match the value type of the base iterator. The function
should return a reference to the function's <tt>result_type</tt>.
The <tt>result_type</tt> will be the resulting iterator's <tt>value_type</tt>.
</TD>
</TD>
<TR>
<TD><tt>BaseIterator</tt></TD>
<TD>The iterator type being wrapped.</TD>
</TD>
</TR>
</Table>
<h3>Model of</h3>
If the base iterator is a model of <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access Iterator</a> then so is the resulting projection iterator. If
the base iterator supports less functionality than this the resulting
projection iterator will also support less functionality.
<h3>Members</h3>
The projection iterator type implements the member functions and
operators required of the <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access Iterator</a> concept.
In addition it has the following constructor:
<pre>
projection_iterator_generator::type(const BaseIterator&amp; it,
const AdaptableUnaryFunction&amp; p = AdaptableUnaryFunction())
</pre>
<p>
<hr>
<p>
<h2><a name="projection_iterator_pair_generator">The Projection Iterator Pair
Generator</a></h2>
Sometimes a mutable/const pair of iterator types is needed, such as
when implementing a container type. The
<tt>projection_iterator_pair_generator</tt> class makes it more
convenient to create this pair of iterator types.
<pre>
template &lt;class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator, class ConstBaseIterator&gt;
class projection_iterator_pair_generator
{
public:
typedef <tt><a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt...&gt;</tt> iterator; // the mutable projection iterator type
typedef <tt><a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt...&gt;</tt> const_iterator; // the immutable projection iterator type
};
</pre>
<h3>Example</h3>
In this part of the example we use the
<tt>projection_iterator_pair_generator</tt> to create a mutable/const
pair of projection iterators that access the ID numbers of the
personnel. We use the mutable iterator to re-index the ID numbers from
zero. We then use the constant iterator to print the ID numbers out.
<pre>
// continuing from the last example...
typedef boost::projection_iterator_pair_generator&lt;select_ID,
std::list&lt;personnel_record&gt;::iterator,
std::list&lt;personnel_record&gt;::const_iterator&gt; PairGen;
PairGen::iterator ID_first(personnel_list.begin()),
ID_last(personnel_list.end());
int new_id = 0;
while (ID_first != ID_last) {
*ID_first = new_id++;
++ID_first;
}
PairGen::const_iterator const_ID_first(personnel_list.begin()),
const_ID_last(personnel_list.end());
std::copy(const_ID_first, const_ID_last,
std::ostream_iterator&lt;int&gt;(std::cout, " "));
std::cout &lt;&lt; std::endl;
std::cout &lt;&lt; std::endl;
// to be continued...
</pre&gt;
The output is:
<pre>
0 1 2 3
</pre>
<h3>Template Parameters</h3>
<Table border>
<TR>
<TH>Parameter</TH><TH>Description</TH>
</TR>
<TR>
<TD><a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a></TD>
<TD>The type of the function object. The <tt>argument_type</tt> of the
function must match the value type of the base iterator. The function
should return a true reference to the function's <tt>result_type</tt>.
The <tt>result_type</tt> will be the resulting iterator's <tt>value_type</tt>.
</TD>
</TD>
<TR>
<TD><tt>BaseIterator</tt></TD>
<TD>The mutable iterator type being wrapped.</TD>
</TD>
</TR>
<TR>
<TD><tt>ConstBaseIterator</tt></TD>
<TD>The constant iterator type being wrapped.</TD>
</TD>
</TR>
</Table>
<h3>Model of</h3>
If the base iterator types model the <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access Iterator</a> then so do the resulting projection iterator
types. If the base iterators support less functionality the
resulting projection iterator types will also support less
functionality. The resulting <tt>iterator</tt> type is mutable, and
the resulting <tt>const_iterator</tt> type is constant.
<h3>Members</h3>
The resulting <tt>iterator</tt> and <tt>const_iterator</tt> types
implements the member functions and operators required of the <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access Iterator</a> concept. In addition they support the following
constructors:
<pre>
projection_iterator_pair_generator::iterator(const BaseIterator&amp; it,
const AdaptableUnaryFunction&amp; p = AdaptableUnaryFunction())</pre>
<pre>
projection_iterator_pair_generator::const_iterator(const BaseIterator&amp; it,
const AdaptableUnaryFunction&amp; p = AdaptableUnaryFunction())
</pre>
<p>
<hr>
<p>
<h2><a name="make_projection_iterator">The Projection Iterator Object Generators</a></h2>
The <tt>make_projection_iterator()</tt> and
<tt>make_const_projection_iterator()</tt> functions provide a more
convenient way to create projection iterator objects. The functions
save the user the trouble of explicitly writing out the iterator
types.
<pre>
template &lt;class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator&gt;
typename projection_iterator_generator&lt;AdaptableUnaryFunction, BaseIterator&gt;::type
make_projection_iterator(BaseIterator base,
const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
template &lt;class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class ConstBaseIterator&gt;
typename projection_iterator_generator&lt;AdaptableUnaryFunction, ConstBaseIterator&gt;::type
make_const_projection_iterator(ConstBaseIterator base,
const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
</pre>
<h3>Example</h3>
In this part of the example, we again print out the names of the
personnel, but this time we use the
<tt>make_const_projection_iterator()</tt> function to save some typing.
<pre>
// continuing from the last example...
std::copy
(boost::make_const_projection_iterator&lt;select_name&gt;(personnel_list.begin()),
boost::make_const_projection_iterator&lt;select_name&gt;(personnel_list.end()),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
</pre>
The output is:
<pre>
Barney
Fred
Wilma
Betty
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" --></p>
<p><EFBFBD> Copyright Jeremy Siek 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 &quot;as is&quot;
without express or implied warranty, and with no claim as to its suitability for
any purpose.</p>
</body>
</html>
<!-- LocalWords: html charset alt gif hpp BaseIterator const namespace struct
-->
<!-- LocalWords: ConstPointer ConstReference typename iostream int abcdefg
-->
<!-- LocalWords: sizeof PairGen pre Siek htm AdaptableUnaryFunction
-->
<!-- LocalWords: ConstBaseIterator
-->

View File

@ -0,0 +1,96 @@
// (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 <list>
#include <iostream>
#include <iterator>
#include <algorithm>
#include <string>
#include <boost/iterator_adaptors.hpp>
struct personnel_record {
personnel_record(std::string n, int id) : m_name(n), m_ID(id) { }
std::string m_name;
int m_ID;
};
struct select_name {
typedef personnel_record argument_type;
typedef std::string result_type;
const std::string& operator()(const personnel_record& r) const {
return r.m_name;
}
std::string& operator()(personnel_record& r) const {
return r.m_name;
}
};
struct select_ID {
typedef personnel_record argument_type;
typedef int result_type;
const int& operator()(const personnel_record& r) const {
return r.m_ID;
}
int& operator()(personnel_record& r) const {
return r.m_ID;
}
};
int main(int, char*[])
{
std::list<personnel_record> personnel_list;
personnel_list.push_back(personnel_record("Barney", 13423));
personnel_list.push_back(personnel_record("Fred", 12343));
personnel_list.push_back(personnel_record("Wilma", 62454));
personnel_list.push_back(personnel_record("Betty", 20490));
// Example of using projection_iterator_generator
// to print out the names in the personnel list.
boost::projection_iterator_generator<select_name,
std::list<personnel_record>::iterator>::type
personnel_first(personnel_list.begin()),
personnel_last(personnel_list.end());
std::copy(personnel_first, personnel_last,
std::ostream_iterator<std::string>(std::cout, "\n"));
std::cout << std::endl;
// Example of using projection_iterator_pair_generator
// to assign new ID numbers to the personnel.
typedef boost::projection_iterator_pair_generator<select_ID,
std::list<personnel_record>::iterator,
std::list<personnel_record>::const_iterator> PairGen;
PairGen::iterator ID_first(personnel_list.begin()),
ID_last(personnel_list.end());
int new_id = 0;
while (ID_first != ID_last) {
*ID_first = new_id++;
++ID_first;
}
PairGen::const_iterator const_ID_first(personnel_list.begin()),
const_ID_last(personnel_list.end());
std::copy(const_ID_first, const_ID_last,
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
std::cout << std::endl;
// Example of using make_const_projection_iterator()
// to print out the names in the personnel list again.
std::copy
(boost::make_const_projection_iterator<select_name>(personnel_list.begin()),
boost::make_const_projection_iterator<select_name>(personnel_list.end()),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}

View File

@ -1,18 +1,9 @@
// Copyright David Abrahams and Aleksey Gurtovoy
// 2002-2004. Distributed under the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// compile-time test for "boost/ref.hpp" header content
// see 'ref_test.cpp' for run-time part
#include <boost/ref.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_const.hpp>
#include <boost/type_traits/same_traits.hpp>
#include <boost/static_assert.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/mpl/assert.hpp>
namespace {
@ -39,23 +30,13 @@ void is_reference_wrapper_test(T)
template< typename R, typename Ref >
void cxx_reference_test(Ref)
{
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
typedef typename boost::remove_const<Ref>::type ref;
BOOST_STATIC_ASSERT((boost::is_same<R,ref>::value));
#else
BOOST_STATIC_ASSERT((boost::is_same<R,Ref>::value));
#endif
}
template< typename R, typename Ref >
void unwrap_reference_test(Ref)
{
#if BOOST_WORKAROUND(__BORLANDC__, < 0x600)
typedef typename boost::remove_const<Ref>::type ref;
typedef typename boost::unwrap_reference<ref>::type type;
#else
typedef typename boost::unwrap_reference<Ref>::type type;
#endif
BOOST_STATIC_ASSERT((boost::is_same<R,type>::value));
}

View File

@ -1,7 +1,3 @@
// Copyright David Abrahams and Aleksey Gurtovoy
// 2002-2004. Distributed under the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// run-time test for "boost/ref.hpp" header content
// see 'ref_ct_test.cpp' for compile-time part
@ -60,11 +56,11 @@ struct ref_wrapper
static void test(T x)
{
BOOST_CHECK(passthru(ref(x)) == &x);
BOOST_CHECK(&ref(x).get() == &x);
BOOST_TEST(passthru(ref(x)) == &x);
BOOST_TEST(&ref(x).get() == &x);
BOOST_CHECK(cref_passthru(cref(x)) == &x);
BOOST_CHECK(&cref(x).get() == &x);
BOOST_TEST(cref_passthru(cref(x)) == &x);
BOOST_TEST(&cref(x).get() == &x);
}
};

331
reverse_iterator.htm Normal file
View File

@ -0,0 +1,331 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<meta name="generator" content="HTML Tidy, see www.w3.org">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Reverse Iterator Adaptor Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
"center" width="277" height="86">
<h1>Reverse Iterator Adaptor</h1>
Defined in header <a href=
"../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
<p>The reverse iterator adaptor flips the direction of a base iterator's
motion. Invoking <tt>operator++()</tt> moves the base iterator backward and
invoking <tt>operator--()</tt> moves the base iterator forward. The Boost
reverse iterator adaptor is better to use than the
<tt>std::reverse_iterator</tt> class in situations where pairs of
mutable/constant iterators are needed (e.g., in containers) because
comparisons and conversions between the mutable and const versions are
implemented correctly.
<h2>Synopsis</h2>
<pre>
namespace boost {
template &lt;class <a href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>,
class Value, class Reference, class Pointer, class Category, class Distance&gt;
struct reverse_iterator_generator;
template &lt;class <a href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>&gt;
typename reverse_iterator_generator&lt;BidirectionalIterator&gt;::type
make_reverse_iterator(BidirectionalIterator base)
}
</pre>
<hr>
<h2><a name="reverse_iterator_generator">The Reverse Iterator Type
Generator</a></h2>
The <tt>reverse_iterator_generator</tt> template is a <a href=
"../../more/generic_programming.html#type_generator">generator</a> of
reverse iterator types. The main template parameter for this class is the
base <tt>BidirectionalIterator</tt> type that is being adapted. In most
cases the associated types of the base iterator can be deduced using
<tt>std::iterator_traits</tt>, but in some situations the user may want to
override these types, so there are also template parameters for the base
iterator's associated types.
<blockquote>
<pre>
template &lt;class <a href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>,
class Value, class Reference, class Pointer, class Category, class Distance&gt;
class reverse_iterator_generator
{
public:
typedef <tt><a href=
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt;...&gt;</tt> type; // the resulting reverse iterator type
};
</pre>
</blockquote>
<h3>Example</h3>
In this example we sort a sequence of letters and then output the sequence
in descending order using reverse iterators.
<blockquote>
<pre>
#include &lt;boost/config.hpp&gt;
#include &lt;iostream&gt;
#include &lt;algorithm&gt;
#include &lt;boost/iterator_adaptors.hpp&gt;
int main(int, char*[])
{
char letters[] = "hello world!";
const int N = sizeof(letters)/sizeof(char) - 1;
std::cout &lt;&lt; "original sequence of letters:\t"
&lt;&lt; letters &lt;&lt; std::endl;
std::sort(letters, letters + N);
// Use reverse_iterator_generator to print a sequence
// of letters in reverse order.
boost::reverse_iterator_generator&lt;char*&gt;::type
reverse_letters_first(letters + N),
reverse_letters_last(letters);
std::cout &lt;&lt; "letters in descending order:\t";
std::copy(reverse_letters_first, reverse_letters_last,
std::ostream_iterator&lt;char&gt;(std::cout));
std::cout &lt;&lt; std::endl;
// to be continued...
</pre>
</blockquote>
The output is:
<blockquote>
<pre>
original sequence of letters: hello world!
letters in descending order: wroolllhed!
</pre>
</blockquote>
<h3>Template Parameters</h3>
<table border>
<tr>
<th>Parameter
<th>Description
<tr>
<td><tt><a href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a></tt>
<td>The iterator type being wrapped.
<tr>
<td><tt>Value</tt>
<td>The value-type of the base iterator and the resulting reverse
iterator.<br>
<b>Default:</b><tt>std::iterator_traits&lt;BidirectionalIterator&gt;::value_type</tt>
<tr>
<td><tt>Reference</tt>
<td>The <tt>reference</tt> type of the resulting iterator, and in
particular, the result type of <tt>operator*()</tt>.<br>
<b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&amp;</tt> is
used. Otherwise
<tt>std::iterator_traits&lt;BidirectionalIterator&gt;::reference</tt>
is used.
<tr>
<td><tt>Pointer</tt>
<td>The <tt>pointer</tt> type of the resulting iterator, and in
particular, the result type of <tt>operator-&gt;()</tt>.<br>
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
otherwise
<tt>std::iterator_traits&lt;BidirectionalIterator&gt;::pointer</tt>.
<tr>
<td><tt>Category</tt>
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BidirectionalIterator&gt;::iterator_category</tt>
<tr>
<td><tt>Distance</tt>
<td>The <tt>difference_type</tt> for the resulting iterator.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BidirectionalIterator&amp;gt::difference_type</tt>
</table>
<h3>Concept Model</h3>
The indirect iterator will model whichever <a href=
"http://www.sgi.com/tech/stl/Iterators.html">standard iterator concept
category</a> is modeled by the base iterator. Thus, if the base iterator is
a model of <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
Iterator</a> then so is the resulting indirect iterator. If the base
iterator models a more restrictive concept, the resulting indirect iterator
will model the same concept. The base iterator must be at least a <a href=
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional
Iterator</a>
<h3>Members</h3>
The reverse iterator type implements the member functions and operators
required of the <a href=
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
Iterator</a> concept. In addition it has the following constructor:
<blockquote>
<pre>
reverse_iterator_generator::type(const BidirectionalIterator&amp; it)
</pre>
</blockquote>
<br>
<br>
<hr>
<p>
<h2><a name="make_reverse_iterator">The Reverse Iterator Object
Generator</a></h2>
The <tt>make_reverse_iterator()</tt> function provides a more convenient
way to create reverse iterator objects. The function saves the user the
trouble of explicitly writing out the iterator types.
<blockquote>
<pre>
template &lt;class BidirectionalIterator&gt;
typename reverse_iterator_generator&lt;BidirectionalIterator&gt;::type
make_reverse_iterator(BidirectionalIterator base);
</pre>
</blockquote>
<h3>Example</h3>
In this part of the example we use <tt>make_reverse_iterator()</tt> to
print the sequence of letters in reverse-reverse order, which is the
original order.
<blockquote>
<pre>
// continuing from the previous example...
std::cout &lt;&lt; "letters in ascending order:\t";
std::copy(boost::make_reverse_iterator(reverse_letters_last),
boost::make_reverse_iterator(reverse_letters_first),
std::ostream_iterator&lt;char&gt;(std::cout));
std::cout &lt;&lt; std::endl;
return 0;
}
</pre>
</blockquote>
The output is:
<blockquote>
<pre>
letters in ascending order: !dehllloorw
</pre>
</blockquote>
<hr>
<h2><a name="interactions">Constant/Mutable Iterator Interactions</a></h2>
<p>One failing of the standard <tt><a
href="http://www.sgi.com/tech/stl/ReverseIterator.html">reverse_iterator</a></tt>
adaptor is that it doesn't properly support interactions between adapted
<tt>const</tt> and non-<tt>const</tt> iterators. For example:
<blockquote>
<pre>
#include &lt;vector&gt;
template &lt;class T&gt; void convert(T x) {}
// Test interactions of a matched pair of random access iterators
template &lt;class Iterator, class ConstIterator&gt;
void test_interactions(Iterator i, ConstIterator ci)
{
bool eq = i == ci; // comparisons
bool ne = i != ci;
bool lt = i &lt; ci;
bool le = i &lt;= ci;
bool gt = i &gt; ci;
bool ge = i &gt;= ci;
std::size_t distance = i - ci; // difference
ci = i; // assignment
ConstIterator ci2(i); // construction
convert&lt;ConstIterator&gt;(i); // implicit conversion
}
void f()
{
typedef std::vector&lt;int&gt; vec;
vec v;
const vec&amp; cv;
test_interactions(v.begin(), cv.begin()); // <font color="#007F00">OK</font>
test_interactions(v.rbegin(), cv.rbegin()); // <font color="#FF0000">ERRORS ON EVERY TEST!!</font>
</pre>
</blockquote>
Reverse iterators created with <tt>boost::reverse_iterator_generator</tt> don't have this problem, though:
<blockquote>
<pre>
typedef boost::reverse_iterator_generator&lt;vec::iterator&gt;::type ri;
typedef boost::reverse_iterator_generator&lt;vec::const_iterator&gt;::type cri;
test_interactions(ri(v.begin()), cri(cv.begin())); // <font color="#007F00">OK!!</font>
</pre>
</blockquote>
Or, more simply,
<blockquote>
<pre>
test_interactions(
boost::make_reverse_iterator(v.begin()),
boost::make_reverse_iterator(cv.begin())); // <font color="#007F00">OK!!</font>
}
</pre>
</blockquote>
<p>If you are wondering why there is no
<tt>reverse_iterator_pair_generator</tt> in the manner of <tt><a
href="projection_iterator.htm#projection_iterator_pair_generator">projection_iterator_pair_generator</a></tt>,
the answer is simple: we tried it, but found that in practice it took
<i>more</i> typing to use <tt>reverse_iterator_pair_generator</tt> than to
simply use <tt>reverse_iterator_generator</tt> twice!<br><br>
<hr>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" -->
<p>&copy; Copyright Jeremy Siek 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.
<!-- LocalWords: html charset alt gif hpp BidirectionalIterator const namespace struct
-->
<!-- LocalWords: ConstPointer ConstReference typename iostream int abcdefg
-->
<!-- LocalWords: sizeof PairGen pre Siek wroolllhed dehllloorw
-->
</body>
</html>

View File

@ -0,0 +1,51 @@
// (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 <iostream>
#include <algorithm>
#include <boost/iterator_adaptors.hpp>
int main(int, char*[])
{
char letters_[] = "hello world!";
const int N = sizeof(letters_)/sizeof(char) - 1;
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// Assume there won't be proper iterator traits for pointers. This
// is just a wrapper for char* which has the right traits.
typedef boost::iterator_adaptor<char*, boost::default_iterator_policies, char> base_iterator;
#else
typedef char* base_iterator;
#endif
base_iterator letters(letters_);
std::cout << "original sequence of letters:\t"
<< letters_ << std::endl;
std::sort(letters, letters + N);
// Use reverse_iterator_generator to print a sequence
// of letters in reverse order.
boost::reverse_iterator_generator<base_iterator>::type
reverse_letters_first(letters + N),
reverse_letters_last(letters);
std::cout << "letters in descending order:\t";
std::copy(reverse_letters_first, reverse_letters_last,
std::ostream_iterator<char>(std::cout));
std::cout << std::endl;
// Use make_reverse_iterator() to print the sequence
// of letters in reverse-reverse order.
std::cout << "letters in ascending order:\t";
std::copy(boost::make_reverse_iterator(reverse_letters_last),
boost::make_reverse_iterator(reverse_letters_first),
std::ostream_iterator<char>(std::cout));
std::cout << std::endl;
return 0;
}

View File

@ -1,322 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Shared Container Iterator Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<img src="../../boost.png" alt="boost.png (6897 bytes)"
align="center" width="277" height="86">
<h1>Shared Container Iterator</h1>
Defined in header
<a href="../../boost/shared_container_iterator.hpp">boost/shared_container_iterator.hpp</a>
<p>
The purpose of the shared container iterator is to attach the lifetime
of a container to the lifetime of its iterators. In other words, the
container will not be deleted until after all its iterators are
destroyed. The shared container iterator is typically used to
implement functions that return iterators over a range of objects that
only need to exist for the lifetime of the iterators. By returning a
pair of shared iterators from a function, the callee can return a
heap-allocated range of objects whose lifetime is automatically managed.
<p>
The shared container iterator augments an iterator over a shared
container. It maintains a reference count on the shared
container. If only shared container iterators hold references to
the container, the container's lifetime will end when the last shared
container iterator over it is destroyed. In any case, the shared
container is guaranteed to persist beyond the lifetime of all
the iterators. In all other ways, the
shared container iterator behaves the same as its base iterator.
<h2>Synopsis</h2>
<pre>
namespace boost {
template &lt;typename <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>&gt;
class shared_container_iterator;
template &lt;typename <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>&gt;
shared_container_iterator&lt;Container&gt;
make_shared_container_iterator(typename Container::iterator base,
boost::shared_ptr&lt;Container&gt; const&amp; container);
std::pair&lt;
typename shared_container_iterator&lt;Container&gt;,
typename shared_container_iterator&lt;Container&gt;
&gt;
make_shared_container_range(boost::shared_ptr&lt;Container&gt; const&amp; container);
}
</pre>
<hr>
<h2><a name="generator">The Shared Container Iterator Type</a></h2>
<pre>
template &lt;typename Container&gt; class shared_container_iterator;
</pre>
The class template <tt>shared_container_iterator</tt>
is the shared container iterator type. The <tt>Container</tt> template
type argument must model the
<a href="http://www.sgi.com/tech/stl/Container.html">Container</a>
concept.
<h3>Example</h3>
<p>
The following example illustrates how to create an iterator that
regulates the lifetime of a reference counted <tt>std::vector</tt>.
Though the original shared pointer <tt>ints</tt> ceases to exist
after <tt>set_range()</tt> returns, the
<tt>shared_counter_iterator</tt> objects maintain references to the
underlying vector and thereby extend the container's lifetime.
<p>
<a href="./shared_iterator_example1.cpp">shared_iterator_example1.cpp</a>:
<PRE>
<font color="#008040">#include "shared_container_iterator.hpp"</font>
<font color="#008040">#include "boost/shared_ptr.hpp"</font>
<font color="#008040">#include &lt;algorithm&gt;</font>
<font color="#008040">#include &lt;iostream&gt;</font>
<font color="#008040">#include &lt;vector&gt;</font>
<B>typedef</B> boost::shared_container_iterator&lt; std::vector&lt;<B>int</B>&gt; &gt; iterator;
<B>void</B> set_range(iterator& i, iterator& end) {
boost::shared_ptr&lt; std::vector&lt;<B>int</B>&gt; &gt; ints(<B>new</B> std::vector&lt;<B>int</B>&gt;());
ints-&gt;push_back(<font color="#0000A0">0</font>);
ints-&gt;push_back(<font color="#0000A0">1</font>);
ints-&gt;push_back(<font color="#0000A0">2</font>);
ints-&gt;push_back(<font color="#0000A0">3</font>);
ints-&gt;push_back(<font color="#0000A0">4</font>);
ints-&gt;push_back(<font color="#0000A0">5</font>);
i = iterator(ints-&gt;begin(),ints);
end = iterator(ints-&gt;end(),ints);
}
<B>int</B> main() {
iterator i,end;
set_range(i,end);
std::copy(i,end,std::ostream_iterator&lt;<B>int</B>&gt;(std::cout,<font color="#0000FF">","</font>));
std::cout.put(<font color="#0000FF">'\n'</font>);
<B>return</B> <font color="#0000A0">0</font>;
}
</PRE>
The output from this part is:
<pre>
0,1,2,3,4,5,
</pre>
<h3>Template Parameters</h3>
<Table border>
<TR>
<TH>Parameter</TH><TH>Description</TH>
</TR>
<TR>
<TD><a
href="http://www.sgi.com/tech/stl/Container.html"><tt>Container</tt></a></TD>
<TD>The type of the container that we wish to iterate over. It must be
a model of the
<a href="http://www.sgi.com/tech/stl/Container.html"><tt>Container</tt></a>
concept.
</TD>
</TR>
</Table>
<h3>Model of</h3>
The <tt>shared_container_iterator<Container></tt> type models the
same iterator concept as the base iterator
(<tt>Container::iterator</tt>).
<h3>Members</h3>
The shared container iterator type implements the member functions and
operators required of the <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterator</a>
concept, though only operations defined for the base iterator will be valid.
In addition it has the following constructor:
<pre>
shared_container_iterator(Container::iterator const&amp; it,
boost::shared_ptr&lt;Container&gt; const&amp; container)
</pre>
<p>
<hr>
<p>
<h2><a name="make_iterator">The Shared Container Iterator Object Generator</a></h2>
<pre>
template &lt;typename Container&gt;
shared_container_iterator&lt;Container&gt;
make_shared_container_iterator(Container::iterator base,
boost::shared_ptr&lt;Container&gt; const&amp; container)
</pre>
This function provides an alternative to directly constructing a
shared container iterator. Using the object generator, a shared
container iterator can be created and passed to a function without
explicitly specifying its type.
<h3>Example</h3>
This example, similar to the previous, uses
<tt>make_shared_container_iterator()</tt> to create the iterators.
<p>
<a href="./shared_iterator_example2.cpp">shared_iterator_example2.cpp</a>:
<PRE>
<font color="#008040">#include "shared_container_iterator.hpp"</font>
<font color="#008040">#include "boost/shared_ptr.hpp"</font>
<font color="#008040">#include &lt;algorithm&gt;</font>
<font color="#008040">#include &lt;iterator&gt;</font>
<font color="#008040">#include &lt;iostream&gt;</font>
<font color="#008040">#include &lt;vector&gt;</font>
<B>template</B> &lt;<B>typename</B> Iterator&gt;
<B>void</B> print_range_nl (Iterator begin, Iterator end) {
<B>typedef</B> <B>typename</B> std::iterator_traits&lt;Iterator&gt;::value_type val;
std::copy(begin,end,std::ostream_iterator&lt;val&gt;(std::cout,<font color="#0000FF">","</font>));
std::cout.put(<font color="#0000FF">'\n'</font>);
}
<B>int</B> main() {
<B>typedef</B> boost::shared_ptr&lt; std::vector&lt;<B>int</B>&gt; &gt; ints_t;
{
ints_t ints(<B>new</B> std::vector&lt;<B>int</B>&gt;());
ints-&gt;push_back(<font color="#0000A0">0</font>);
ints-&gt;push_back(<font color="#0000A0">1</font>);
ints-&gt;push_back(<font color="#0000A0">2</font>);
ints-&gt;push_back(<font color="#0000A0">3</font>);
ints-&gt;push_back(<font color="#0000A0">4</font>);
ints-&gt;push_back(<font color="#0000A0">5</font>);
print_range_nl(boost::make_shared_container_iterator(ints-&gt;begin(),ints),
boost::make_shared_container_iterator(ints-&gt;end(),ints));
}
<B>return</B> <font color="#0000A0">0</font>;
}
</PRE>
Observe that the <tt>shared_container_iterator</tt> type is never
explicitly named. The output from this example is the same as the previous.
<h2><a name="make_range">The Shared Container Iterator Range Generator</a></h2>
<pre>
template &lt;typename Container&gt;
std::pair&lt
shared_container_iterator&lt;Container&gt;,
shared_container_iterator&lt;Container&gt;
&gt;
make_shared_container_range(boost::shared_ptr&lt;Container&gt; const&amp; container);
</pre>
Class <tt>shared_container_iterator</tt> is meant primarily to return,
using iterators, a range of values that we can guarantee will be alive as
long as the iterators are. This is a convenience
function to do just that. It is equivalent to
<pre>
std::make_pair(make_shared_container_iterator(container-&gt;begin(),container),
make_shared_container_iterator(container-&gt;end(),container));
</pre>
<h3>Example</h3>
In the following example, a range of values is returned as a pair of
<tt>shared_container_iterator</tt> objects.
<p>
<a href="./shared_iterator_example3.cpp">shared_iterator_example3.cpp</a>:
<PRE>
<font color="#008040">#include "shared_container_iterator.hpp"</font>
<font color="#008040">#include "boost/shared_ptr.hpp"</font>
<font color="#008040">#include "boost/tuple/tuple.hpp" // for boost::tie</font>
<font color="#008040">#include &lt;algorithm&gt; // for std::copy</font>
<font color="#008040">#include &lt;iostream&gt; </font>
<font color="#008040">#include &lt;vector&gt;</font>
<B>typedef</B> boost::shared_container_iterator&lt; std::vector&lt;<B>int</B>&gt; &gt; iterator;
std::pair&lt;iterator,iterator&gt;
return_range() {
boost::shared_ptr&lt; std::vector&lt;<B>int</B>&gt; &gt; range(<B>new</B> std::vector&lt;<B>int</B>&gt;());
range-&gt;push_back(<font color="#0000A0">0</font>);
range-&gt;push_back(<font color="#0000A0">1</font>);
range-&gt;push_back(<font color="#0000A0">2</font>);
range-&gt;push_back(<font color="#0000A0">3</font>);
range-&gt;push_back(<font color="#0000A0">4</font>);
range-&gt;push_back(<font color="#0000A0">5</font>);
<B>return</B> boost::make_shared_container_range(range);
}
<B>int</B> main() {
iterator i,end;
boost::tie(i,end) = return_range();
std::copy(i,end,std::ostream_iterator&lt;<B>int</B>&gt;(std::cout,<font color="#0000FF">","</font>));
std::cout.put(<font color="#0000FF">'\n'</font>);
<B>return</B> <font color="#0000A0">0</font>;
}
</PRE>
Though the <tt>range</tt> object only lives for the duration of the
<tt>return_range</tt> call, the reference counted
<tt>std::vector</tt> will live until <tt>i</tt> and <tt>end</tt>
are both destroyed. The output from this example is the same as
the previous two.
<hr>
<!-- hhmts start -->
Last modified: Mon Aug 11 11:27:03 EST 2003
<!-- hhmts end -->
<p><EFBFBD> Copyright 2003 The Trustees of Indiana University.
Use, modification and distribution is subject to the Boost Software
License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
http:www.boost.org/LICENSE_1_0.txt)</p>
</body>
</html>

View File

@ -1,42 +0,0 @@
// Copyright 2003 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/shared_container_iterator.hpp"
#include "boost/shared_ptr.hpp"
#include <algorithm>
#include <iostream>
#include <vector>
typedef boost::shared_container_iterator< std::vector<int> > iterator;
void set_range(iterator& i, iterator& end) {
boost::shared_ptr< std::vector<int> > ints(new std::vector<int>());
ints->push_back(0);
ints->push_back(1);
ints->push_back(2);
ints->push_back(3);
ints->push_back(4);
ints->push_back(5);
i = iterator(ints->begin(),ints);
end = iterator(ints->end(),ints);
}
int main() {
iterator i,end;
set_range(i,end);
std::copy(i,end,std::ostream_iterator<int>(std::cout,","));
std::cout.put('\n');
return 0;
}

View File

@ -1,43 +0,0 @@
// Copyright 2003 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/shared_container_iterator.hpp"
#include "boost/shared_ptr.hpp"
#include <algorithm>
#include <iterator>
#include <iostream>
#include <vector>
template <typename Iterator>
void print_range_nl (Iterator begin, Iterator end) {
typedef typename std::iterator_traits<Iterator>::value_type val;
std::copy(begin,end,std::ostream_iterator<val>(std::cout,","));
std::cout.put('\n');
}
int main() {
typedef boost::shared_ptr< std::vector<int> > ints_t;
{
ints_t ints(new std::vector<int>());
ints->push_back(0);
ints->push_back(1);
ints->push_back(2);
ints->push_back(3);
ints->push_back(4);
ints->push_back(5);
print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints),
boost::make_shared_container_iterator(ints->end(),ints));
}
return 0;
}

View File

@ -1,41 +0,0 @@
// Copyright 2003 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include "boost/shared_container_iterator.hpp"
#include "boost/shared_ptr.hpp"
#include "boost/tuple/tuple.hpp" // for boost::tie
#include <algorithm> // for std::copy
#include <iostream>
#include <vector>
typedef boost::shared_container_iterator< std::vector<int> > iterator;
std::pair<iterator,iterator>
return_range() {
boost::shared_ptr< std::vector<int> > range(new std::vector<int>());
range->push_back(0);
range->push_back(1);
range->push_back(2);
range->push_back(3);
range->push_back(4);
range->push_back(5);
return boost::make_shared_container_range(range);
}
int main() {
iterator i,end;
boost::tie(i,end) = return_range();
std::copy(i,end,std::ostream_iterator<int>(std::cout,","));
std::cout.put('\n');
return 0;
}

View File

@ -1,64 +0,0 @@
// Copyright 2003 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Shared container iterator adaptor
// Author: Ronald Garcia
// See http://boost.org/libs/utility/shared_container_iterator.html
// for documentation.
//
// shared_iterator_test.cpp - Regression tests for shared_container_iterator.
//
#include "boost/shared_container_iterator.hpp"
#include "boost/shared_ptr.hpp"
#include <vector>
#include <cassert>
struct resource {
static int count;
resource() { ++count; }
resource(resource const&) { ++count; }
~resource() { --count; }
};
int resource::count = 0;
typedef std::vector<resource> resources_t;
typedef boost::shared_container_iterator< resources_t > iterator;
void set_range(iterator& i, iterator& end) {
boost::shared_ptr< resources_t > objs(new resources_t());
for (int j = 0; j != 6; ++j)
objs->push_back(resource());
i = iterator(objs->begin(),objs);
end = iterator(objs->end(),objs);
assert(resource::count == 6);
}
int main() {
assert(resource::count == 0);
{
iterator i;
{
iterator end;
set_range(i,end);
assert(resource::count == 6);
}
assert(resource::count == 6);
}
assert(resource::count == 0);
return 0;
}

View File

@ -1 +0,0 @@
The existance of this file tells the regression reporting programs that the directory contains sub-directories which are libraries.

View File

@ -1,36 +0,0 @@
# Copyright David Abrahams 2003. Permission to copy, use,
# modify, sell and distribute this software is granted provided this
# copyright notice appears in all copies. This software is provided
# "as is" without express or implied warranty, and with no claim as
# to its suitability for any purpose.
# For more information, see http://www.boost.org/
# bring in rules for testing
import testing ;
# Please keep the tests ordered by filename
test-suite utility
:
[ run ../addressof_test.cpp ]
[ run ../assert_test.cpp ]
[ run ../base_from_member_test.cpp ]
[ run ../binary_search_test.cpp ]
[ run ../call_traits_test.cpp : -u ]
[ compile-fail ../checked_delete_test.cpp ]
[ run ../compressed_pair_test.cpp ../../test/build//boost_test_exec_monitor/<link>static : -u ]
[ run ../current_function_test.cpp : : : <test-info>always_show_run_output ]
[ run ../iterators_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ]
[ run next_prior_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ]
[ compile-fail ../noncopyable_test.cpp ]
[ run ../numeric_traits_test.cpp ]
[ run ../operators_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ]
[ compile ../ref_ct_test.cpp ]
[ run ../ref_test.cpp ../../test/build//boost_test_exec_monitor/<link>static ]
[ compile result_of_test.cpp ]
[ run ../shared_iterator_test.cpp ]
[ run ../value_init_test.cpp ]
[ compile-fail ../value_init_test_fail1.cpp ]
[ compile-fail ../value_init_test_fail2.cpp ]
[ compile-fail ../value_init_test_fail3.cpp ]
;

View File

@ -1,79 +0,0 @@
// Boost test program for next() and prior() utilities.
// Copyright 2003 Daniel Walker. Use, modification, and distribution
// are subject to the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt.)
// See http://www.boost.org/libs/utility for documentation.
// Revision History 13 Dec 2003 Initial Version (Daniel Walker)
// next() and prior() are replacements for operator+ and operator- for
// non-random-access iterators. The semantics of these operators are
// such that after executing j = i + n, std::distance(i, j) equals
// n. Tests are provided to ensure next() has the same
// result. Parallel tests are provided for prior(). The tests call
// next() and prior() several times. next() and prior() are very
// simple functions, though, and it would be very strange if these
// tests were to fail.
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <list>
#include <vector>
#include <boost/next_prior.hpp>
template<class RandomAccessIterator, class ForwardIterator>
bool plus_one_test(RandomAccessIterator first, RandomAccessIterator last, ForwardIterator first2)
{
RandomAccessIterator i = first;
ForwardIterator j = first2;
while(i != last)
i = i + 1, j = boost::next(j);
return std::distance(first, i) == std::distance(first2, j);
}
template<class RandomAccessIterator, class ForwardIterator>
bool plus_n_test(RandomAccessIterator first, RandomAccessIterator last, ForwardIterator first2)
{
RandomAccessIterator i = first;
ForwardIterator j = first2;
for(int n = 0; i != last; ++n)
i = first + n, j = boost::next(first2, n);
return std::distance(first, i) == std::distance(first2, j);
}
template<class RandomAccessIterator, class BidirectionalIterator>
bool minus_one_test(RandomAccessIterator first, RandomAccessIterator last, BidirectionalIterator last2)
{
RandomAccessIterator i = last;
BidirectionalIterator j = last2;
while(i != first)
i = i - 1, j = boost::prior(j);
return std::distance(i, last) == std::distance(j, last2);
}
template<class RandomAccessIterator, class BidirectionalIterator>
bool minus_n_test(RandomAccessIterator first, RandomAccessIterator last, BidirectionalIterator last2)
{
RandomAccessIterator i = last;
BidirectionalIterator j = last2;
for(int n = 0; i != first; ++n)
i = last - n, j = boost::prior(last2, n);
return std::distance(i, last) == std::distance(j, last2);
}
int test_main(int, char*[])
{
std::vector<int> x(8);
std::list<int> y(x.begin(), x.end());
BOOST_REQUIRE(plus_one_test(x.begin(), x.end(), y.begin()));
BOOST_REQUIRE(plus_n_test(x.begin(), x.end(), y.begin()));
BOOST_REQUIRE(minus_one_test(x.begin(), x.end(), y.end()));
BOOST_REQUIRE(minus_n_test(x.begin(), x.end(), y.end()));
return 0;
}

Some files were not shown because too many files have changed in this diff Show More