Compare commits

...

47 Commits

Author SHA1 Message Date
46dd855904 This commit was manufactured by cvs2svn to create branch 'mpl_v2_2'.
[SVN r18675]
2003-06-05 05:15:05 +00:00
1c7a2a1476 IBM C++ support added.
[SVN r18587]
2003-05-28 13:45:58 +00:00
7c40cc0b63 Fixed bool_testable for compilers with BOOST_NO_OPERATORS_IN_NAMESPACE
[SVN r18521]
2003-05-23 23:09:21 +00:00
73a9e0d351 Intel support.
[SVN r18520]
2003-05-23 22:30:23 +00:00
dc9856744a Fixed tests for bool_testable
[SVN r18502]
2003-05-23 00:18:57 +00:00
88f4e47550 Added bool_testable by Sam Partington
[SVN r18413]
2003-05-15 22:40:33 +00:00
1be04eeec5 Fix a bug in preprocessor usage
[SVN r18231]
2003-04-11 06:56:52 +00:00
56acf9c325 Fixed shift-operators to respect BOOST_FORCE_SYMMETRIC_OPERATORS
[SVN r17664]
2003-02-26 21:26:57 +00:00
c6e3957efc MPL names/directory structure refactoring
[SVN r17651]
2003-02-25 23:11:41 +00:00
25e8284950 Qualified checked_delete calls to prevent ADL (reported by Daniel Frey)
[SVN r17636]
2003-02-25 13:00:22 +00:00
37a6537a5b fix metafunctions for MPL
[SVN r17621]
2003-02-25 00:57:33 +00:00
80df1d8f12 split utility.hpp header
[SVN r17472]
2003-02-17 06:20:57 +00:00
75afed7f17 Made operator()s const.
[SVN r17411]
2003-02-14 16:20:01 +00:00
1d7066aee1 __func__ is a predefined identifier, not a macro.
[SVN r17308]
2003-02-10 16:25:41 +00:00
12272a38d4 Initial Commit (was left out when the Optional Library was commited)
[SVN r17204]
2003-02-04 15:29:12 +00:00
04f901e52e fixed some typos
[SVN r17052]
2003-01-27 19:14:18 +00:00
fabfb31bf6 add value_init
[SVN r16826]
2003-01-09 13:26:13 +00:00
683701cd07 fix invalid bookmarks
[SVN r16823]
2003-01-09 13:03:37 +00:00
119c64be0b Workaround VC7 bug which strips const from nested classes
[SVN r16797]
2003-01-08 17:21:10 +00:00
d429c9a7d8 minor cleanup
[SVN r16709]
2002-12-27 16:58:27 +00:00
1e8216431b add or update See www.boost.org comments
[SVN r16708]
2002-12-27 16:51:53 +00:00
e45b2e2136 Doc link updated.
[SVN r16699]
2002-12-24 12:34:42 +00:00
9e6951009b Add /libs/lib-name to comment
[SVN r16685]
2002-12-23 02:43:12 +00:00
a009a209f1 Use BOOST_WORKAROUND
[SVN r16668]
2002-12-20 00:03:04 +00:00
97605056ed Added a note that throw_exception must not return (Beman Dawes)
[SVN r16471]
2002-12-02 12:12:42 +00:00
8fcfa33d33 Fix: Comeau with bcc32 as backend defines __BORLANDC__ as 1.
[SVN r16455]
2002-11-28 13:32:44 +00:00
aa65e3da3b sort_by_value(std::list<std::string>& l) is not declared inline anymore to make it compile with vacpp
[SVN r16407]
2002-11-25 15:54:37 +00:00
b4cfadb4d5 Metrowerks support (Bertolt Mildner)
[SVN r16263]
2002-11-15 19:44:18 +00:00
45a6249668 New BOOST_ASSERT, including documentation.
[SVN r16240]
2002-11-14 16:09:29 +00:00
1d601aef4d boost::throw_exception documentation added.
[SVN r16239]
2002-11-14 15:13:59 +00:00
32fb45eba9 checked_delete.hpp documentation added.
[SVN r16238]
2002-11-14 14:53:32 +00:00
2b7d10aceb BOOST_CURRENT_FUNCTION documentation added.
[SVN r16236]
2002-11-14 14:41:25 +00:00
5dc62711e1 Fix from Yitzhak Sapir <yitzhaks@actimize.com>
[SVN r16198]
2002-11-11 19:50:05 +00:00
252c02aca0 Works with MSVC and Intel5 now. Thanks, Aleksey!!
[SVN r16165]
2002-11-08 17:08:17 +00:00
9655beb7ba Cleanups on boost::iterator_traits<>
Broke MSVC though :(


[SVN r16157]
2002-11-08 06:57:31 +00:00
f0ea53e77e rip out illegal semicolons
[SVN r16134]
2002-11-06 18:20:38 +00:00
4755b42909 Daniel Frey's NRVO patches
[SVN r16084]
2002-11-04 01:59:32 +00:00
ef9af03c6c Changed typename to class; some libraries helpfully #define typename
[SVN r15970]
2002-10-23 13:55:18 +00:00
7439073cbf Merged from branch to trunk
[SVN r15572]
2002-09-30 16:54:26 +00:00
aff985a563 explicit "private" inheritance to avoid compiler warnings (MIPSpro)
[SVN r15422]
2002-09-17 21:06:32 +00:00
db425222d5 mpl_v2 branch checkin
[SVN r15258]
2002-09-11 05:35:41 +00:00
e20af510f7 Initial Revision
[SVN r15254]
2002-09-10 16:13:08 +00:00
d8230c6a73 Added Shared Container Iterator adaptor to iterator adaptor library.
[SVN r15169]
2002-09-05 14:05:29 +00:00
f5690787bf Distinguish between VC++ versions
[SVN r15127]
2002-09-01 14:57:40 +00:00
a4fd7b32dd Misc Kylix fixes
[SVN r15086]
2002-08-25 11:57:37 +00:00
f4336ec693 fixed typo.
[SVN r14798]
2002-08-12 20:47:54 +00:00
03d906976b Reduced probes from 10,000 to 1,000 to speed regression tests
[SVN r14789]
2002-08-12 15:05:23 +00:00
72 changed files with 272 additions and 14498 deletions

View File

@ -1,116 +0,0 @@
<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>
<h3>Description</h3>
A type is Assignable if it is possible to assign one object of the type
to another object of that type.
<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>
<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>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>
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>
</table>
<h3>Models</h3>
<UL>
<LI><tt>int</tt>
<LI><tt>std::pair</tt>
</UL>
<h3>See also</h3>
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</A>
and
<A href="./CopyConstructible.html">CopyConstructible</A>
<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>
</BODY>
</HTML>

View File

@ -1,210 +0,0 @@
<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>
<h3>Description</h3>
A type is Copy Constructible if it is possible to copy objects of that
type.
<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>
<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>
<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>
T(u)
</pre>
</TD>
<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>
t.~T()
</pre>
</TD>
<TD VAlign=top>
<tt>T</tt>
</TD>
<TD VAlign=top>
&nbsp;
</TD>
</TR>
<TR>
<TD VAlign=top>
Address Operator
</TD>
<TD VAlign=top>
<pre>
&amp;t
</pre>
</TD>
<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>
&amp;u
</pre>
</TD>
<TD VAlign=top>
<tt>T*</tt>
</TD>
<TD VAlign=top>
denotes the address of <tt>u</tt>
</TD>
</TR>
</table>
</table>
<h3>Models</h3>
<UL>
<LI><tt>int</tt>
<LI><tt>std::pair</tt>
</UL>
<h3>Concept Checking Class</h3>
<pre>
template &lt;class T&gt;
struct CopyConstructibleConcept
{
void constraints() {
T a(b); // require copy constructor
T* ptr = &amp;a; // require address of operator
const_constraints(a);
ignore_unused_variable_warning(ptr);
}
void const_constraints(const T&amp; a) {
T c(a); // require const copy constructor
const T* ptr = &amp;a; // require const address of operator
ignore_unused_variable_warning(c);
ignore_unused_variable_warning(ptr);
}
T b;
};
</pre>
<h3>See also</h3>
<A
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</A>
and
<A hrefa="./Assignable.html">Assignable</A>
<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>
</BODY>
</HTML>

View File

@ -1,212 +0,0 @@
<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.
-->
<!--
-- 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>
<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.
<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>
<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>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>
<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>
</BODY>
</HTML>

View File

@ -1,92 +0,0 @@
<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">
<BR Clear>
<H2>
<A NAME="concept:MultiPassInputIterator"></A>
Multi-Pass Input Iterator
</H2>
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>.
<h3>Design Notes</h3>
comments by Valentin Bonnard:
<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> 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>
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>
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>
reply by Jeremy Siek:
<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>
<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>
</BODY>
</HTML>

View File

@ -1,46 +0,0 @@
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
// Doug Gregor (gregod@cs.rpi.edu)
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// 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
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
#include <boost/utility.hpp>
struct useless_type {};
class nonaddressable {
public:
void dummy(); // Silence GCC warning: all member of class are private
private:
useless_type operator&() const;
};
int test_main(int, char*[])
{
nonaddressable* px = new nonaddressable();
nonaddressable& x = *px;
BOOST_TEST(boost::addressof(x) == px);
const nonaddressable& cx = *px;
BOOST_TEST(boost::addressof(cx) == static_cast<const nonaddressable*>(px));
volatile nonaddressable& vx = *px;
BOOST_TEST(boost::addressof(vx) == static_cast<volatile nonaddressable*>(px));
const volatile nonaddressable& cvx = *px;
BOOST_TEST(boost::addressof(cvx) == static_cast<const volatile nonaddressable*>(px));
return 0;
}

View File

@ -1,33 +0,0 @@
#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.
//
// 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.
//
#define BOOST_DEBUG 1
#include <boost/assert.hpp>
#include <cstdio>
bool boost_error(char const * expr, char const * func, char const * file, long line)
{
std::printf("%s(%ld): Assertion '%s' failed in function '%s'\n", file, line, expr, func);
return true; // fail w/ standard assert()
}
int main()
{
BOOST_ASSERT(0 == 1);
}

View File

@ -1,341 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>Boost: Base-from-Member Idiom Documentation</title>
</head>
<body bgcolor="white" link="blue" text="black" vlink="purple" alink="red">
<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>.
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>
<h2><a name="contents">Contents</a></h2>
<ul>
<li><a href="#contents">Contents</a></li>
<li><a href="#rationale">Rationale</a></li>
<li><a href="#synopsis">Synopsis</a></li>
<li><a href="#usage">Usage</a></li>
<li><a href="#example">Example</a></li>
<li><a href="#credits">Credits</a>
<ul>
<li><a href="#contributors">Contributors</a></li>
</ul></li>
</ul>
<h2><a name="rationale">Rationale</a></h2>
<p>When developing a class, sometimes a base class needs to be
initialized with a member of the current class. As a na&iuml;ve
example:</p>
<blockquote><pre>
#include &lt;streambuf&gt; <i>// for std::streambuf</i>
#include &lt;ostream&gt; <i>// for std::ostream</i>
class fdoutbuf
: public std::streambuf
{
public:
explicit fdoutbuf( int fd );
//...
};
class fdostream
: public std::ostream
{
protected:
fdoutbuf buf;
public:
explicit fdostream( int fd )
: buf( fd ), std::ostream( &amp;buf )
{}
//...
};
</pre></blockquote>
<p>This is undefined because C++'s initialization order mandates that
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>
<blockquote><pre>
#include &lt;streambuf&gt; <i>// for std::streambuf</i>
#include &lt;ostream&gt; <i>// for std::ostream</i>
class fdoutbuf
: public std::streambuf
{
public:
explicit fdoutbuf( int fd );
//...
};
struct fdostream_pbase
{
fdoutbuf sbuffer;
explicit fdostream_pbase( int fd )
: sbuffer( fd )
{}
};
class fdostream
: private fdostream_pbase
, public std::ostream
{
typedef fdostream_pbase pbase_type;
typedef std::ostream base_type;
public:
explicit fdostream( int fd )
: pbase_type( fd ), base_type( &amp;sbuffer )
{}
//...
};
</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>Manually coding a base class may be better if the construction
and/or copying needs are too complex for the supplied template class,
or if the compiler is not advanced enough to use it.</p>
<p>Since base classes are unnamed, a class cannot have multiple (direct)
base classes of the same type. The supplied template class has an
extra template parameter, an integer, that exists solely to provide type
differentiation. This parameter has a default value so a single use of a
particular member type does not need to concern itself with the integer.</p>
<h2><a name="synopsis">Synopsis</a></h2>
<blockquote><pre>
template &lt; typename MemberType, int UniqueID = 0 &gt;
class boost::base_from_member
{
protected:
MemberType member;
explicit base_from_member();
template&lt; typename T1 &gt;
explicit base_from_member( T1 x1 );
//...
template&lt; typename T1, typename T2, typename T3 &gt;
explicit base_from_member( T1 x1, T2 x2, T3 x3 );
};
</pre></blockquote>
<p>The class template has a first template parameter
<var>MemberType</var> representing the type of the based-member.
It has a last template parameter <var>UniqueID</var>, that is an
<code>int</code>, to differentiate between multiple base classes that use
the same based-member type. The last template parameter has a default
value of zero if it is omitted. The class template has a protected
data member called <var>member</var> that the derived class can use
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 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>
<h2><a name="usage">Usage</a></h2>
<p>With the starting example, the <code>fdoutbuf</code> sub-object needs
to be encapsulated in a base class that is inheirited before
<code>std::ostream</code>.</p>
<blockquote><pre>
#include &lt;boost/utility/base_from_member.hpp&gt;
#include &lt;streambuf&gt; <i>// for std::streambuf</i>
#include &lt;ostream&gt; <i>// for std::ostream</i>
class fdoutbuf
: public std::streambuf
{
public:
explicit fdoutbuf( int fd );
//...
};
class fdostream
: private boost::base_from_member&lt;fdoutbuf&gt;
, public std::ostream
{
// Helper typedef's
typedef boost::base_from_member&lt;fdoutbuf&gt; pbase_type;
typedef std::ostream base_type;
public:
explicit fdostream( int fd )
: pbase_type( fd ), base_type( &amp;member )
{}
//...
};
</pre></blockquote>
<p>The base-from-member idiom is an implementation detail, so it
should not be visible to the clients (or any derived classes) of
<code>fdostream</code>. Due to the initialization order, the
<code>fdoutbuf</code> sub-object will get initialized before the
<code>std::ostream</code> sub-object does, making the former
sub-object safe to use in the latter sub-object's construction. Since the
<code>fdoutbuf</code> sub-object of the final type is the only sub-object
with the name &quot;member,&quot; that name can be used
unqualified within the final class.</p>
<h2><a name="example">Example</a></h2>
<p>The base-from-member class templates should commonly involve
only one base-from-member sub-object, usually for attaching a
stream-buffer to an I/O stream. The next example demonstrates how
to use multiple base-from-member sub-objects and the resulting
qualification issues.</p>
<blockquote><pre>
#include &lt;boost/utility/base_from_member.hpp&gt;
#include &lt;cstddef&gt; <i>// for NULL</i>
struct an_int
{
int y;
an_int( float yf );
};
class switcher
{
public:
switcher();
switcher( double, int * );
//...
};
class flow_regulator
{
public:
flow_regulator( switcher &amp;, switcher &amp; );
//...
};
template &lt; unsigned Size &gt;
class fan
{
public:
explicit fan( switcher );
//...
};
class system
: private boost::base_from_member&lt;an_int&gt;
, private boost::base_from_member&lt;switcher&gt;
, private boost::base_from_member&lt;switcher, 1&gt;
, private boost::base_from_member&lt;switcher, 2&gt;
, protected flow_regulator
, public fan&lt;6&gt;
{
// Helper typedef's
typedef boost::base_from_member&lt;an_int&gt; pbase0_type;
typedef boost::base_from_member&lt;switcher&gt; pbase1_type;
typedef boost::base_from_member&lt;switcher, 1&gt; pbase2_type;
typedef boost::base_from_member&lt;switcher, 2&gt; pbase3_type;
typedef flow_regulator base1_type;
typedef fan&lt;6&gt; base2_type;
public:
system( double x );
//...
};
system::system( double x )
: pbase0_type( 0.2 )
, pbase1_type()
, pbase2_type( -16, &amp;this-&gt;pbase0_type::member )
, pbase3_type( x, static_cast&lt;int *&gt;(NULL) )
, base1_type( pbase3_type::member, pbase1_type::member )
, base2_type( pbase2_type::member )
{
//...
}
</pre></blockquote>
<p>The final class has multiple sub-objects with the name
&quot;member,&quot; so any use of that name needs qualification by
a name of the appropriate base type. (Using <code>typedef</code>s
ease mentioning the base types.) However, the fix introduces a new
problem when a pointer is needed. Using the address operator with
a sub-object qualified with its class's name results in a pointer-to-member
(here, having a type of <code>an_int boost::base_from_member&lt;an_int,
0&gt; :: *</code>) instead of a pointer to the member (having a type of
<code>an_int *</code>). The new problem is fixed by qualifying the
sub-object with &quot;<code>this-&gt;</code>,&quot; and is needed just
for pointers, and not for references or values.</p>
<p>There are some argument conversions in the initialization. The
constructor argument for <code>pbase0_type</code> is converted from
<code>double</code> to <code>float</code>. The first constructor
argument for <code>pbase2_type</code> is converted from <code>int</code>
to <code>double</code>. The second constructor argument for
<code>pbase3_type</code> is a special case of necessary conversion; all
forms of the null-pointer literal in C++ also look like compile-time
integral expressions, so C++ always interprets such code as an integer
when it has overloads that can take either an integer or a pointer. The
last conversion is necessary for the compiler to call a constructor form
with the exact pointer type used in <code>switcher</code>'s constructor.</p>
<h2><a name="credits">Credits</a></h2>
<h3><a name="contributors">Contributors</a></h3>
<dl>
<dt><a href="../../people/ed_brey.htm">Ed Brey</a>
<dd>Suggested some interface changes.
<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.
<dt><a href="../../people/dietmar_kuehl.htm">Dietmar Kuehl</a>
<dd>Popularized the base-from-member idiom in his
<a href="http://www.informatik.uni-konstanz.de/~kuehl/c++/iostream/">IOStream
example classes</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>.
</dl>
<hr>
<p>Revised: 22 August 2001</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,597 +0,0 @@
// Boost test program for base-from-member class templates -----------------//
// (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 for most recent version including documentation.
// Revision History
// 29 Aug 2001 Initial Version (Daryle Walker)
#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/utility.hpp> // for boost::noncopyable
#include <boost/utility/base_from_member.hpp> // for boost::base_from_member
#include <functional> // for std::binary_function, std::less
#include <iostream> // for std::cout (std::ostream, std::endl indirectly)
#include <set> // for std::set
#include <typeinfo> // for std::type_info
#include <utility> // for std::pair, std::make_pair
#include <vector> // for std::vector
// Control if extra information is printed
#ifndef CONTROL_EXTRA_PRINTING
#define CONTROL_EXTRA_PRINTING 1
#endif
// A (sub)object can be identified by its memory location and its type.
// Both are needed since an object can start at the same place as its
// first base class subobject and/or contained subobject.
typedef std::pair< void *, std::type_info const * > object_id;
// Object IDs need to be printed
std::ostream & operator <<( std::ostream &os, object_id const &oi );
// A way to generate an object ID
template < typename T >
object_id identify( T &obj );
// A custom comparison type is needed
struct object_id_compare
: std::binary_function<object_id, object_id, bool>
{
bool operator ()( object_id const &a, object_id const &b ) const;
}; // object_id_compare
// A singleton of this type coordinates the acknowledgements
// of objects being created and used.
class object_registrar
: private boost::noncopyable
{
public:
#ifndef BOOST_NO_MEMBER_TEMPLATES
template < typename T >
void register_object( T &obj )
{ this->register_object_imp( identify(obj) ); }
template < typename T, typename U >
void register_use( T &owner, U &owned )
{ this->register_use_imp( identify(owner), identify(owned) ); }
template < typename T, typename U >
void unregister_use( T &owner, U &owned )
{ this->unregister_use_imp( identify(owner), identify(owned) ); }
template < typename T >
void unregister_object( T &obj )
{ this->unregister_object_imp( identify(obj) ); }
#endif
void register_object_imp( object_id obj );
void register_use_imp( object_id owner, object_id owned );
void unregister_use_imp( object_id owner, object_id owned );
void unregister_object_imp( object_id obj );
typedef std::set<object_id, object_id_compare> set_type;
typedef std::vector<object_id> error_record_type;
typedef std::vector< std::pair<object_id, object_id> > error_pair_type;
set_type db_;
error_pair_type defrauders_in_, defrauders_out_;
error_record_type overeager_, overkilled_;
}; // object_registrar
// A sample type to be used by containing types
class base_or_member
{
public:
explicit base_or_member( int x = 1, double y = -0.25 );
~base_or_member();
}; // base_or_member
// A sample type that uses base_or_member, used
// as a base for the main demonstration classes
class base_class
{
public:
explicit base_class( base_or_member &x, base_or_member *y = 0,
base_or_member *z = 0 );
~base_class();
private:
base_or_member *x_, *y_, *z_;
}; // base_class
// This bad class demonstrates the direct method of a base class needing
// to be initialized by a member. This is improper since the member
// isn't initialized until after the base class.
class bad_class
: public base_class
{
public:
bad_class();
~bad_class();
private:
base_or_member x_;
}; // bad_class
// The first good class demonstrates the correct way to initialize a
// base class with a member. The member is changed to another base
// class, one that is initialized before the base that needs it.
class good_class_1
: private boost::base_from_member<base_or_member>
, public base_class
{
typedef boost::base_from_member<base_or_member> pbase_type;
typedef base_class base_type;
public:
good_class_1();
~good_class_1();
}; // good_class_1
// The second good class also demonstrates the correct way to initialize
// base classes with other subobjects. This class uses the other helpers
// in the library, and shows the technique of using two base subobjects
// of the "same" type.
class good_class_2
: private boost::base_from_member<base_or_member, 0>
, private boost::base_from_member<base_or_member, 1>
, private boost::base_from_member<base_or_member, 2>
, public base_class
{
typedef boost::base_from_member<base_or_member, 0> pbase_type0;
typedef boost::base_from_member<base_or_member, 1> pbase_type1;
typedef boost::base_from_member<base_or_member, 2> pbase_type2;
typedef base_class base_type;
public:
good_class_2();
~good_class_2();
}; // good_class_2
// Declare/define the single object registrar
object_registrar obj_reg;
// Main functionality
int
test_main( int , char * [] )
{
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
{
using std::cout;
using std::endl;
bad_class bc;
BOOST_TEST( obj_reg.db_.size() == 3 );
BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
good_class_1 gc1;
BOOST_TEST( obj_reg.db_.size() == 6 );
BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
good_class_2 gc2;
BOOST_TEST( obj_reg.db_.size() == 11 );
BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
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.
cout << "Object 'bc' is at " << &bc << '.' << endl;
cout << "Object 'gc1' is at " << &gc1 << '.' << endl;
cout << "Object 'gc2' is at " << &gc2 << '.' << endl;
}
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;
}
// Print an object's ID
std::ostream &
operator <<
(
std::ostream & os,
object_id const & oi
)
{
// I had an std::ostringstream to help, but I did not need it since
// the program never screws around with formatting. Worse, using
// std::ostringstream is an issue with some compilers.
return os << '[' << ( oi.second ? oi.second->name() : "NOTHING" )
<< " at " << oi.first << ']';
}
// Get an object ID given an object
template < typename T >
inline
object_id
identify
(
T & obj
)
{
return std::make_pair( static_cast<void *>(&obj), &(typeid( obj )) );
}
// Compare two object IDs
bool
object_id_compare::operator ()
(
object_id const & a,
object_id const & b
) const
{
std::less<void *> vp_cmp;
if ( vp_cmp(a.first, b.first) )
{
return true;
}
else if ( vp_cmp(b.first, a.first) )
{
return false;
}
else
{
// object pointers are equal, compare the types
if ( a.second == b.second )
{
return false;
}
else if ( !a.second )
{
return true; // NULL preceeds anything else
}
else if ( !b.second )
{
return false; // NULL preceeds anything else
}
else
{
return a.second->before( *b.second );
}
}
}
// Let an object register its existence
void
object_registrar::register_object_imp
(
object_id obj
)
{
if ( db_.count(obj) <= 0 )
{
db_.insert( obj );
#if CONTROL_EXTRA_PRINTING
std::cout << "Registered " << obj << '.' << std::endl;
#endif
}
else
{
overeager_.push_back( obj );
#if CONTROL_EXTRA_PRINTING
std::cout << "Attempted to register a non-existant " << obj
<< '.' << std::endl;
#endif
}
}
// Let an object register its use of another object
void
object_registrar::register_use_imp
(
object_id owner,
object_id owned
)
{
if ( db_.count(owned) > 0 )
{
// We don't care to record usage registrations
}
else
{
defrauders_in_.push_back( std::make_pair(owner, owned) );
#if CONTROL_EXTRA_PRINTING
std::cout << "Attempted to own a non-existant " << owned
<< " by " << owner << '.' << std::endl;
#endif
}
}
// Let an object un-register its use of another object
void
object_registrar::unregister_use_imp
(
object_id owner,
object_id owned
)
{
if ( db_.count(owned) > 0 )
{
// We don't care to record usage un-registrations
}
else
{
defrauders_out_.push_back( std::make_pair(owner, owned) );
#if CONTROL_EXTRA_PRINTING
std::cout << "Attempted to disown a non-existant " << owned
<< " by " << owner << '.' << std::endl;
#endif
}
}
// Let an object un-register its existence
void
object_registrar::unregister_object_imp
(
object_id obj
)
{
set_type::iterator const i = db_.find( obj );
if ( i != db_.end() )
{
db_.erase( i );
#if CONTROL_EXTRA_PRINTING
std::cout << "Unregistered " << obj << '.' << std::endl;
#endif
}
else
{
overkilled_.push_back( obj );
#if CONTROL_EXTRA_PRINTING
std::cout << "Attempted to unregister a non-existant " << obj
<< '.' << std::endl;
#endif
}
}
// Macros to abstract the registration of objects
#ifndef BOOST_NO_MEMBER_TEMPLATES
#define PRIVATE_REGISTER_BIRTH(o) obj_reg.register_object( (o) )
#define PRIVATE_REGISTER_DEATH(o) obj_reg.unregister_object( (o) )
#define PRIVATE_REGISTER_USE(o, w) obj_reg.register_use( (o), (w) )
#define PRIVATE_UNREGISTER_USE(o, w) obj_reg.unregister_use( (o), (w) )
#else
#define PRIVATE_REGISTER_BIRTH(o) obj_reg.register_object_imp( \
identify((o)) )
#define PRIVATE_REGISTER_DEATH(o) obj_reg.unregister_object_imp( \
identify((o)) )
#define PRIVATE_REGISTER_USE(o, w) obj_reg.register_use_imp( identify((o)), \
identify((w)) )
#define PRIVATE_UNREGISTER_USE(o, w) obj_reg.unregister_use_imp( \
identify((o)), identify((w)) )
#endif
// Create a base_or_member, with arguments to simulate member initializations
base_or_member::base_or_member
(
int x, // = 1
double y // = -0.25
)
{
PRIVATE_REGISTER_BIRTH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy x-factor is " << x << " and my y-factor is " << y
<< '.' << std::endl;
#endif
}
// Destroy a base_or_member
inline
base_or_member::~base_or_member
(
)
{
PRIVATE_REGISTER_DEATH( *this );
}
// Create a base_class, registering any objects used
base_class::base_class
(
base_or_member & x,
base_or_member * y, // = 0
base_or_member * z // = 0
)
: x_( &x ), y_( y ), z_( z )
{
PRIVATE_REGISTER_BIRTH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy x-factor is " << x_;
#endif
PRIVATE_REGISTER_USE( *this, *x_ );
if ( y_ )
{
#if CONTROL_EXTRA_PRINTING
std::cout << ", my y-factor is " << y_;
#endif
PRIVATE_REGISTER_USE( *this, *y_ );
}
if ( z_ )
{
#if CONTROL_EXTRA_PRINTING
std::cout << ", my z-factor is " << z_;
#endif
PRIVATE_REGISTER_USE( *this, *z_ );
}
#if CONTROL_EXTRA_PRINTING
std::cout << '.' << std::endl;
#endif
}
// Destroy a base_class, unregistering the objects it uses
base_class::~base_class
(
)
{
PRIVATE_REGISTER_DEATH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy x-factor was " << x_;
#endif
PRIVATE_UNREGISTER_USE( *this, *x_ );
if ( y_ )
{
#if CONTROL_EXTRA_PRINTING
std::cout << ", my y-factor was " << y_;
#endif
PRIVATE_UNREGISTER_USE( *this, *y_ );
}
if ( z_ )
{
#if CONTROL_EXTRA_PRINTING
std::cout << ", my z-factor was " << z_;
#endif
PRIVATE_UNREGISTER_USE( *this, *z_ );
}
#if CONTROL_EXTRA_PRINTING
std::cout << '.' << std::endl;
#endif
}
// Create a bad_class, noting the improper construction order
bad_class::bad_class
(
)
: x_( -7, 16.75 ), base_class( x_ ) // this order doesn't matter
{
PRIVATE_REGISTER_BIRTH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy factor is at " << &x_
<< " and my base is at " << static_cast<base_class *>(this) << '.'
<< std::endl;
#endif
}
// Destroy a bad_class, noting the improper destruction order
bad_class::~bad_class
(
)
{
PRIVATE_REGISTER_DEATH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy factor was at " << &x_
<< " and my base was at " << static_cast<base_class *>(this)
<< '.' << std::endl;
#endif
}
// Create a good_class_1, noting the proper construction order
good_class_1::good_class_1
(
)
: pbase_type( 8 ), base_type( member )
{
PRIVATE_REGISTER_BIRTH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy factor is at " << &member
<< " and my base is at " << static_cast<base_class *>(this) << '.'
<< std::endl;
#endif
}
// Destroy a good_class_1, noting the proper destruction order
good_class_1::~good_class_1
(
)
{
PRIVATE_REGISTER_DEATH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy factor was at " << &member
<< " and my base was at " << static_cast<base_class *>(this)
<< '.' << std::endl;
#endif
}
// Create a good_class_2, noting the proper construction order
good_class_2::good_class_2
(
)
: pbase_type0(), pbase_type1(-16, 0.125), pbase_type2(2, -3)
, base_type( pbase_type1::member, &this->pbase_type0::member,
&this->pbase_type2::member )
{
PRIVATE_REGISTER_BIRTH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy factors are at " << &this->pbase_type0::member
<< ", " << &this->pbase_type1::member << ", "
<< &this->pbase_type2::member << ", and my base is at "
<< static_cast<base_class *>(this) << '.' << std::endl;
#endif
}
// Destroy a good_class_2, noting the proper destruction order
good_class_2::~good_class_2
(
)
{
PRIVATE_REGISTER_DEATH( *this );
#if CONTROL_EXTRA_PRINTING
std::cout << "\tMy factors were at " << &this->pbase_type0::member
<< ", " << &this->pbase_type1::member << ", "
<< &this->pbase_type2::member << ", and my base was at "
<< static_cast<base_class *>(this) << '.' << std::endl;
#endif
}

View File

@ -1,249 +0,0 @@
// (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>
#include <memory>
#include <climits>
#include <iostream>
#include <cassert>
#include <stdlib.h> // for rand(). Would use cstdlib but VC6.4 doesn't put it in std::
#include <list>
#include <algorithm>
#include <boost/detail/binary_search.hpp>
#if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
# define USE_SSTREAM
#endif
#ifdef USE_SSTREAM
# include <sstream>
#else
# include <strstream>
#endif
namespace {
typedef std::vector<std::string> string_vector;
const std::size_t sequence_length = 1000;
unsigned random_number()
{
return static_cast<unsigned>(::rand()) % sequence_length;
}
# ifndef USE_SSTREAM
class unfreezer {
public:
unfreezer(std::ostrstream& s) : m_stream(s) {}
~unfreezer() { m_stream.freeze(false); }
private:
std::ostrstream& m_stream;
};
# endif
template <class T>
void push_back_random_number_string(T& seq)
{
unsigned value = random_number();
# if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
std::ostringstream s;
s << value;
seq.push_back(s.str());
# else
std::ostrstream s;
auto unfreezer unfreeze(s);
s << value << char(0);
seq.push_back(std::string(s.str()));
# endif
}
inline unsigned to_int(unsigned x) { return x; }
inline unsigned to_int(const std::string& x) { return atoi(x.c_str()); }
struct cmp
{
template <class A1, class A2>
inline bool operator()(const A1& a1, const A2& a2) const
{
return to_int(a1) < to_int(a2);
}
};
inline bool operator<(const std::string& x, const unsigned y)
{
return to_int(x) < y;
}
inline bool operator<(const unsigned y, const std::string& x)
{
return y < to_int(x);
}
template <class T> void sort_by_value(T&);
template <>
void sort_by_value(std::vector<std::string>& v)
{
std::sort(v.begin(), v.end(), cmp());
}
template <class T>
void random_sorted_sequence(T& seq)
{
seq.clear();
for (std::size_t i = 0; i < sequence_length; ++i)
{
push_back_random_number_string(seq);
}
sort_by_value(seq);
}
# if defined(BOOST_MSVC) && BOOST_MSVC < 1300 && !defined(__SGI_STL_PORT)
// VC6's standard lib doesn't have a template member function for list::sort()
template <>
void random_sorted_sequence(std::list<std::string>& result)
{
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
{
template <class Iterator, class Key>
static Iterator lower_bound(Iterator start, Iterator finish, Key key, Compare cmp)
{ return boost::detail::lower_bound(start, finish, key, cmp); }
template <class Iterator, class Key>
static Iterator upper_bound(Iterator start, Iterator finish, Key key, Compare cmp)
{ return boost::detail::upper_bound(start, finish, key, cmp); }
template <class Iterator, class Key>
static std::pair<Iterator, Iterator> equal_range(Iterator start, Iterator finish, Key key, Compare cmp)
{ return boost::detail::equal_range(start, finish, key, cmp); }
template <class Iterator, class Key>
static bool binary_search(Iterator start, Iterator finish, Key key, Compare cmp)
{ return boost::detail::binary_search(start, finish, key, cmp); }
};
struct no_compare {};
template <> struct searches<no_compare>
{
template <class Iterator, class Key>
static Iterator lower_bound(Iterator start, Iterator finish, Key key, no_compare)
{ return boost::detail::lower_bound(start, finish, key); }
template <class Iterator, class Key>
static Iterator upper_bound(Iterator start, Iterator finish, Key key, no_compare)
{ return boost::detail::upper_bound(start, finish, key); }
template <class Iterator, class Key>
static std::pair<Iterator, Iterator> equal_range(Iterator start, Iterator finish, Key key, no_compare)
{ return boost::detail::equal_range(start, finish, key); }
template <class Iterator, class Key>
static bool binary_search(Iterator start, Iterator finish, Key key, no_compare)
{ return boost::detail::binary_search(start, finish, key); }
};
template <class Sequence, class Compare>
void test_loop(Sequence& x, Compare cmp, unsigned long test_count)
{
typedef typename Sequence::const_iterator const_iterator;
for (unsigned long i = 0; i < test_count; ++i)
{
random_sorted_sequence(x);
const const_iterator start = x.begin();
const const_iterator finish = x.end();
unsigned key = random_number();
const const_iterator l = searches<Compare>::lower_bound(start, finish, key, cmp);
const const_iterator u = searches<Compare>::upper_bound(start, finish, key, cmp);
bool found_l = false;
bool found_u = false;
std::size_t index = 0;
std::size_t count = 0;
unsigned last_value = 0;
for (const_iterator p = start; p != finish; ++p)
{
if (p == l)
found_l = true;
if (p == u)
{
assert(found_l);
found_u = true;
}
unsigned value = to_int(*p);
assert(value >= last_value);
last_value = value;
if (!found_l)
{
++index;
assert(to_int(*p) < key);
}
else if (!found_u)
{
++count;
assert(to_int(*p) == key);
}
else
assert(to_int(*p) > key);
}
assert(found_l || l == finish);
assert(found_u || u == finish);
std::pair<const_iterator, const_iterator>
range = searches<Compare>::equal_range(start, finish, key, cmp);
assert(range.first == l);
assert(range.second == u);
bool found = searches<Compare>::binary_search(start, finish, key, cmp);
assert(found == (u != l));
std::cout << "found " << count << " copies of " << key << " at index " << index << "\n";
}
}
}
int main()
{
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<std::string> y;
std::cout << "=== testing bidirectional iterators with <: ===\n";
test_loop(y, no_compare(), 25);
std::cout << "=== testing bidirectional iterators with compare: ===\n";
test_loop(y, cmp(), 25);
std::cerr << "******TEST PASSED******\n";
return 0;
}

View File

@ -1,764 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta name="Template"
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
<title>Call Traits</title>
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
vlink="#800080">
<h1><img src="../../c++boost.gif" width="276" height="86">Header
&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
defined inside namespace boost.</p>
<p>The template class call_traits&lt;T&gt; encapsulates the
&quot;best&quot; method to pass a parameter of some type T to or
from a function, and consists of a collection of typedefs defined
as in the table below. The purpose of call_traits is to ensure
that problems like &quot;<a href="#refs">references to references</a>&quot;
never occur, and that parameters are passed in the most efficient
manner possible (see <a href="#examples">examples</a>). In each
case if your existing practice is to use the type defined on the
left, then replace it with the call_traits defined type on the
right. </p>
<p>Note that for compilers that do not support either partial
specialization or member templates, no benefit will occur from
using call_traits: the call_traits defined types will always be
the same as the existing practice in this case. In addition if
only member templates and not partial template specialisation is
support by the compiler (for example Visual C++ 6) then
call_traits can not be used with array types (although it can be
used to solve the reference to reference problem).</p>
<table border="0" cellpadding="7" cellspacing="1" width="797">
<tr>
<td valign="top" width="17%" bgcolor="#008080"><p
align="center">Existing practice</p>
</td>
<td valign="top" width="35%" bgcolor="#008080"><p
align="center">call_traits equivalent</p>
</td>
<td valign="top" width="32%" bgcolor="#008080"><p
align="center">Description</p>
</td>
<td valign="top" width="16%" bgcolor="#008080"><p
align="center">Notes</p>
</td>
</tr>
<tr>
<td valign="top" width="17%"><p align="center">T<br>
(return by value)</p>
</td>
<td valign="top" width="35%"><p align="center"><code>call_traits&lt;T&gt;::value_type</code></p>
</td>
<td valign="top" width="32%">Defines a type that
represents the &quot;value&quot; of type T. Use this for
functions that return by value, or possibly for stored
values of type T.</td>
<td valign="top" width="16%"><p align="center">2</p>
</td>
</tr>
<tr>
<td valign="top" width="17%"><p align="center">T&amp;<br>
(return value)</p>
</td>
<td valign="top" width="35%"><p align="center"><code>call_traits&lt;T&gt;::reference</code></p>
</td>
<td valign="top" width="32%">Defines a type that
represents a reference to type T. Use for functions that
would normally return a T&amp;.</td>
<td valign="top" width="16%"><p align="center">1</p>
</td>
</tr>
<tr>
<td valign="top" width="17%"><p align="center">const
T&amp;<br>
(return value)</p>
</td>
<td valign="top" width="35%"><p align="center"><code>call_traits&lt;T&gt;::const_reference</code></p>
</td>
<td valign="top" width="32%">Defines a type that
represents a constant reference to type T. Use for
functions that would normally return a const T&amp;.</td>
<td valign="top" width="16%"><p align="center">1</p>
</td>
</tr>
<tr>
<td valign="top" width="17%"><p align="center">const
T&amp;<br>
(function parameter)</p>
</td>
<td valign="top" width="35%"><p align="center"><code>call_traits&lt;T&gt;::param_type</code></p>
</td>
<td valign="top" width="32%">Defines a type that
represents the &quot;best&quot; way to pass a parameter
of type T to a function.</td>
<td valign="top" width="16%"><p align="center">1,3</p>
</td>
</tr>
</table>
<p>Notes:</p>
<ol>
<li>If T is already reference type, then call_traits is
defined such that <a href="#refs">references to
references</a> do not occur (requires partial
specialization).</li>
<li>If T is an array type, then call_traits defines <code>value_type</code>
as a &quot;constant pointer to type&quot; rather than an
&quot;array of type&quot; (requires partial
specialization). Note that if you are using value_type as
a stored value then this will result in storing a &quot;constant
pointer to an array&quot; rather than the array itself.
This may or may not be a good thing depending upon what
you actually need (in other words take care!).</li>
<li>If T is a small built in type or a pointer, then <code>param_type</code>
is defined as <code>T const</code>, instead of <code>T
const&amp;</code>. This can improve the ability of the
compiler to optimize loops in the body of the function if
they depend upon the passed parameter, the semantics of
the passed parameter is otherwise unchanged (requires
partial specialization).</li>
</ol>
<p>&nbsp;</p>
<h3>Copy constructibility</h3>
<p>The following table defines which call_traits types can always
be copy-constructed from which other types, those entries marked
with a '?' are true only if and only if T is copy constructible:</p>
<table border="0" cellpadding="7" cellspacing="1" width="766">
<tr>
<td valign="top" width="17%">&nbsp;</td>
<td valign="top" colspan="5" width="85%"
bgcolor="#008080"><p align="center">To:</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#008080">From:</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">T</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">value_type</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">reference</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">const_reference</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">param_type</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
<td valign="top" width="17%"><p align="center">?</p>
</td>
<td valign="top" width="17%"><p align="center">?</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
<td valign="top" width="17%"><p align="center">?</p>
</td>
<td valign="top" width="17%"><p align="center">?</p>
</td>
<td valign="top" width="17%"><p align="center">N</p>
</td>
<td valign="top" width="17%"><p align="center">N</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
<td valign="top" width="17%"><p align="center">?</p>
</td>
<td valign="top" width="17%"><p align="center">?</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
<td valign="top" width="17%"><p align="center">?</p>
</td>
<td valign="top" width="17%"><p align="center">N</p>
</td>
<td valign="top" width="17%"><p align="center">N</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
<td valign="top" width="17%"><p align="center">?</p>
</td>
<td valign="top" width="17%"><p align="center">?</p>
</td>
<td valign="top" width="17%"><p align="center">N</p>
</td>
<td valign="top" width="17%"><p align="center">N</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
</tr>
</table>
<p>&nbsp;</p>
<p>If T is an assignable type the following assignments are
possible:</p>
<table border="0" cellpadding="7" cellspacing="1" width="766">
<tr>
<td valign="top" width="17%">&nbsp;</td>
<td valign="top" colspan="5" width="85%"
bgcolor="#008080"><p align="center">To:</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#008080">From:</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">T</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">value_type</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">reference</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">const_reference</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">param_type</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">Y</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
<td valign="top" width="17%"><p align="center">-</p>
</td>
</tr>
</table>
<p>&nbsp;</p>
<h3><a name="examples"></a>Examples</h3>
<p>The following table shows the effect that call_traits has on
various types, the table assumes that the compiler supports
partial specialization: if it doesn't then all types behave in
the same way as the entry for &quot;myclass&quot;, and
call_traits can not be used with reference or array types.</p>
<table border="0" cellpadding="7" cellspacing="1" width="766">
<tr>
<td valign="top" width="17%">&nbsp;</td>
<td valign="top" colspan="5" width="85%"
bgcolor="#008080"><p align="center">Call_traits type:</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#008080"><p
align="center">Original type T</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">value_type</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">reference</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">const_reference</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">param_type</p>
</td>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">Applies to:</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">myclass</p>
</td>
<td valign="top" width="17%"><p align="center">myclass</p>
</td>
<td valign="top" width="17%"><p align="center">myclass&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">const
myclass&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">myclass
const&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">All user
defined types.</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">int</p>
</td>
<td valign="top" width="17%"><p align="center">int</p>
</td>
<td valign="top" width="17%"><p align="center">int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">const
int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">int const</p>
</td>
<td valign="top" width="17%"><p align="center">All small
built-in types.</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">int*</p>
</td>
<td valign="top" width="17%"><p align="center">int*</p>
</td>
<td valign="top" width="17%"><p align="center">int*&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">int*const&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">int* const</p>
</td>
<td valign="top" width="17%"><p align="center">All
pointer types.</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">const
int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">All
reference types.</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">const int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">const
int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">const
int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">const
int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">const
int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">All
constant-references.</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">int[3]</p>
</td>
<td valign="top" width="17%"><p align="center">const int*</p>
</td>
<td valign="top" width="17%"><p align="center">int(&amp;)[3]</p>
</td>
<td valign="top" width="17%"><p align="center">const int(&amp;)[3]</p>
</td>
<td valign="top" width="17%"><p align="center">const int*
const</p>
</td>
<td valign="top" width="17%"><p align="center">All array
types.</p>
</td>
</tr>
<tr>
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
align="center">const int[3]</p>
</td>
<td valign="top" width="17%"><p align="center">const int*</p>
</td>
<td valign="top" width="17%"><p align="center">const int(&amp;)[3]</p>
</td>
<td valign="top" width="17%"><p align="center">const int(&amp;)[3]</p>
</td>
<td valign="top" width="17%"><p align="center">const int*
const</p>
</td>
<td valign="top" width="17%"><p align="center">All
constant-array types.</p>
</td>
</tr>
</table>
<p>&nbsp;</p>
<h4>Example 1:</h4>
<p>The following class is a trivial class that stores some type T
by value (see the <a href="call_traits_test.cpp">call_traits_test.cpp</a>
file), the aim is to illustrate how each of the available
call_traits typedefs may be used:</p>
<pre>template &lt;class T&gt;
struct contained
{
// define our typedefs first, arrays are stored by value
// so value_type is not the same as result_type:
typedef typename boost::call_traits&lt;T&gt;::param_type param_type;
typedef typename boost::call_traits&lt;T&gt;::reference reference;
typedef typename boost::call_traits&lt;T&gt;::const_reference const_reference;
typedef T value_type;
typedef typename boost::call_traits&lt;T&gt;::value_type result_type;
// stored value:
value_type v_;
// constructors:
contained() {}
contained(param_type p) : v_(p){}
// return byval:
result_type value() { return v_; }
// return by_ref:
reference get() { return v_; }
const_reference const_get()const { return v_; }
// pass value:
void call(param_type p){}
};</pre>
<h4><a name="refs"></a>Example 2 (the reference to reference
problem):</h4>
<p>Consider the definition of std::binder1st:</p>
<pre>template &lt;class Operation&gt;
class binder1st :
public unary_function&lt;typename Operation::second_argument_type, typename Operation::result_type&gt;
{
protected:
Operation op;
typename Operation::first_argument_type value;
public:
binder1st(const Operation&amp; x, const typename Operation::first_argument_type&amp; y);
typename Operation::result_type operator()(const typename Operation::second_argument_type&amp; x) const;
}; </pre>
<p>Now consider what happens in the relatively common case that
the functor takes its second argument as a reference, that
implies that <code>Operation::second_argument_type</code> is a
reference type, <code>operator()</code> will now end up taking a
reference to a reference as an argument, and that is not
currently legal. The solution here is to modify <code>operator()</code>
to use call_traits:</p>
<pre>typename Operation::result_type operator()(typename call_traits&lt;typename Operation::second_argument_type&gt;::param_type x) const;</pre>
<p>Now in the case that <code>Operation::second_argument_type</code>
is a reference type, the argument is passed as a reference, and
the no &quot;reference to reference&quot; occurs.</p>
<h4><a name="ex3"></a>Example 3 (the make_pair problem):</h4>
<p>If we pass the name of an array as one (or both) arguments to <code>std::make_pair</code>,
then template argument deduction deduces the passed parameter as
&quot;const reference to array of T&quot;, this also applies to
string literals (which are really array literals). Consequently
instead of returning a pair of pointers, it tries to return a
pair of arrays, and since an array type is not copy-constructible
the code fails to compile. One solution is to explicitly cast the
arguments to make_pair to pointers, but call_traits provides a
better (i.e. automatic) solution (and one that works safely even
in generic code where the cast might do the wrong thing):</p>
<pre>template &lt;class T1, class T2&gt;
std::pair&lt;
typename boost::call_traits&lt;T1&gt;::value_type,
typename boost::call_traits&lt;T2&gt;::value_type&gt;
make_pair(const T1&amp; t1, const T2&amp; t2)
{
return std::pair&lt;
typename boost::call_traits&lt;T1&gt;::value_type,
typename boost::call_traits&lt;T2&gt;::value_type&gt;(t1, t2);
}</pre>
<p>Here, the deduced argument types will be automatically
degraded to pointers if the deduced types are arrays, similar
situations occur in the standard binders and adapters: in
principle in any function that &quot;wraps&quot; a temporary
whose type is deduced. Note that the function arguments to
make_pair are not expressed in terms of call_traits: doing so
would prevent template argument deduction from functioning.</p>
<h4><a name="ex4"></a>Example 4 (optimising fill):</h4>
<p>The call_traits template will &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>),
a version of std::fill is optimized in two ways: if the type
passed is a single byte built-in type then std::memset is used to
effect the fill, otherwise a conventional C++ implemention is
used, but with the passed parameter &quot;optimized&quot; using
call_traits:</p>
<pre>namespace detail{
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);
{
while(first != last)
{
*first = val;
++first;
}
}
};
template &lt;&gt;
struct filler&lt;true&gt;
{
template &lt;typename I, typename T&gt;
static void do_fill(I first, I last, T val)
{
memset(first, val, last-first);
}
};
}
template &lt;class I, class T&gt;
inline void fill(I first, I last, const T&amp; val)
{
enum{ can_opt = boost::is_pointer&lt;I&gt;::value
&amp;&amp; boost::is_arithmetic&lt;T&gt;::value
&amp;&amp; (sizeof(T) == 1) };
typedef detail::filler&lt;can_opt&gt; filler_t;
filler_t::template do_fill&lt;I,T&gt;(first, last, val);
}</pre>
<p>Footnote: the reason that this is &quot;optimal&quot; for
small built-in types is that with the value passed as &quot;T
const&quot; instead of &quot;const T&amp;&quot; the compiler is
able to tell both that the value is constant and that it is free
of aliases. With this information the compiler is able to cache
the passed value in a register, unroll the loop, or use
explicitly parallel instructions: if any of these are supported.
Exactly how much mileage you will get from this depends upon your
compiler - we could really use some accurate benchmarking
software as part of boost for cases like this.</p>
<p>Note that the function arguments to fill are not expressed in
terms of call_traits: doing so would prevent template argument
deduction from functioning. Instead fill acts as a &quot;thin
wrapper&quot; that is there to perform template argument
deduction, the compiler will optimise away the call to fill all
together, replacing it with the call to filler&lt;&gt;::do_fill,
which does use call_traits.</p>
<h3>Rationale</h3>
<p>The following notes are intended to briefly describe the
rational behind choices made in call_traits.</p>
<p>All user-defined types follow &quot;existing practice&quot;
and need no comment.</p>
<p>Small built-in types (what the standard calls fundamental
types [3.9.1]) differ from existing practice only in the <i>param_type</i>
typedef. In this case passing &quot;T const&quot; is compatible
with existing practice, but may improve performance in some cases
(see <a href="#ex4">Example 4</a>), in any case this should never
be any worse than existing practice.</p>
<p>Pointers follow the same rational as small built-in types.</p>
<p>For reference types the rational follows <a href="#refs">Example
2</a> - references to references are not allowed, so the
call_traits members must be defined such that these problems do
not occur. There is a proposal to modify the language such that
&quot;a reference to a reference is a reference&quot; (issue #106,
submitted by Bjarne Stroustrup), call_traits&lt;T&gt;::value_type
and call_traits&lt;T&gt;::param_type both provide the same effect
as that proposal, without the need for a language change (in
other words it's a workaround).</p>
<p>For array types, a function that takes an array as an argument
will degrade the array type to a pointer type: this means that
the type of the actual parameter is different from its declared
type, something that can cause endless problems in template code
that relies on the declared type of a parameter. For example:</p>
<pre>template &lt;class T&gt;
struct A
{
void foo(T t);
};</pre>
<p><font face="Times New Roman">In this case if we instantiate
A&lt;int[2]&gt; then the declared type of the parameter passed to
member function foo is int[2], but it's actual type is const int*,
if we try to use the type T within the function body, then there
is a strong likelyhood that our code will not compile:</font></p>
<pre>template &lt;class T&gt;
void A&lt;T&gt;::foo(T t)
{
T dup(t); // doesn't compile for case that T is an array.
}</pre>
<p>By using call_traits the degradation from array to pointer is
explicit, and the type of the parameter is the same as it's
declared type:</p>
<pre>template &lt;class T&gt;
struct A
{
void foo(typename call_traits&lt;T&gt;::value_type t);
};
template &lt;class T&gt;
void A&lt;T&gt;::foo(typename call_traits&lt;T&gt;::value_type t)
{
typename call_traits&lt;T&gt;::value_type dup(t); // OK even if T is an array type.
}</pre>
<p>For value_type (return by value), again only a pointer may be
returned, not a copy of the whole array, and again call_traits
makes the degradation explicit. The value_type member is useful
whenever an array must be explicitly degraded to a pointer - <a
href="#ex3">Example 3</a> provides the test case (Footnote: the
array specialisation for call_traits is the least well understood
of all the call_traits specialisations, if the given semantics
cause specific problems for you, or don't solve a particular
array-related problem, then I would be interested to hear about
it. Most people though will probably never need to use this
specialisation).</p>
<hr>
<p>Revised 01 September 2000</p>
<p><EFBFBD> Copyright boost.org 2000. Permission to copy, use, modify,
sell and distribute this document is granted provided this
copyright notice appears in all copies. This document is provided
&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>.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
</body>
</html>

View File

@ -1,430 +0,0 @@
// boost::compressed_pair test program
// (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:
// Changed some names to prevent conflicts with some new type_traits additions.
// 03 Oct 2000:
// Enabled extra tests for VC6.
#include <cassert>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <typeinfo>
#include <boost/call_traits.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&) {}
//
// struct contained models a type that contains a type (for example std::pair)
// arrays are contained by value, and have to be treated as a special case:
//
template <class T>
struct contained
{
// define our typedefs first, arrays are stored by value
// so value_type is not the same as result_type:
typedef typename boost::call_traits<T>::param_type param_type;
typedef typename boost::call_traits<T>::reference reference;
typedef typename boost::call_traits<T>::const_reference const_reference;
typedef T value_type;
typedef typename boost::call_traits<T>::value_type result_type;
// stored value:
value_type v_;
// constructors:
contained() {}
contained(param_type p) : v_(p){}
// return byval:
result_type value()const { return v_; }
// return by_ref:
reference get() { return v_; }
const_reference const_get()const { return v_; }
// pass value:
void call(param_type){}
};
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T, std::size_t N>
struct contained<T[N]>
{
typedef typename boost::call_traits<T[N]>::param_type param_type;
typedef typename boost::call_traits<T[N]>::reference reference;
typedef typename boost::call_traits<T[N]>::const_reference const_reference;
typedef T value_type[N];
typedef typename boost::call_traits<T[N]>::value_type result_type;
value_type v_;
contained(param_type p)
{
std::copy(p, p+N, v_);
}
// return byval:
result_type value()const { return v_; }
// return by_ref:
reference get() { return v_; }
const_reference const_get()const { return v_; }
void call(param_type){}
};
#endif
template <class T>
contained<typename boost::call_traits<T>::value_type> test_wrap_type(const T& t)
{
typedef typename boost::call_traits<T>::value_type ct;
return contained<ct>(t);
}
namespace test{
template <class T1, class T2>
std::pair<
typename boost::call_traits<T1>::value_type,
typename boost::call_traits<T2>::value_type>
make_pair(const T1& t1, const T2& t2)
{
return std::pair<
typename boost::call_traits<T1>::value_type,
typename boost::call_traits<T2>::value_type>(t1, t2);
}
} // namespace test
using namespace std;
//
// struct call_traits_checker:
// verifies behaviour of contained example:
//
template <class T>
struct call_traits_checker
{
typedef typename boost::call_traits<T>::param_type param_type;
void operator()(param_type);
};
template <class T>
void call_traits_checker<T>::operator()(param_type p)
{
T t(p);
contained<T> c(t);
cout << "checking contained<" << typeid(T).name() << ">..." << endl;
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;
cout << "typeof contained<" << typeid(T).name() << ">::get() is: " << typeid(&contained<T>::get).name() << endl;
cout << "typeof contained<" << typeid(T).name() << ">::const_get() is: " << typeid(&contained<T>::const_get).name() << endl;
cout << "typeof contained<" << typeid(T).name() << ">::call() is: " << typeid(&contained<T>::call).name() << endl;
cout << endl;
#endif
}
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T, std::size_t N>
struct call_traits_checker<T[N]>
{
typedef typename boost::call_traits<T[N]>::param_type param_type;
void operator()(param_type t)
{
contained<T[N]> c(t);
cout << "checking contained<" << typeid(T[N]).name() << ">..." << endl;
unsigned int i = 0;
for(i = 0; i < N; ++i)
assert(t[i] == c.value()[i]);
for(i = 0; i < N; ++i)
assert(t[i] == c.get()[i]);
for(i = 0; i < N; ++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;
cout << "typeof contained<" << typeid(T[N]).name() << ">::get is: " << typeid(&contained<T[N]>::get).name() << endl;
cout << "typeof contained<" << typeid(T[N]).name() << ">::const_get is: " << typeid(&contained<T[N]>::const_get).name() << endl;
cout << "typeof contained<" << typeid(T[N]).name() << ">::call is: " << typeid(&contained<T[N]>::call).name() << endl;
cout << endl;
}
};
#endif
//
// check_wrap:
template <class W, class U>
void check_wrap(const W& w, const U& u)
{
cout << "checking " << typeid(W).name() << "..." << endl;
assert(w.value() == u);
}
//
// check_make_pair:
// verifies behaviour of "make_pair":
//
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;
assert(c.first == u);
assert(c.second == v);
cout << endl;
}
struct comparible_UDT
{
int i_;
comparible_UDT() : i_(2){}
comparible_UDT(const comparible_UDT& other) : i_(other.i_){}
comparible_UDT& operator=(const comparible_UDT& other)
{
i_ = other.i_;
return *this;
}
bool operator == (const comparible_UDT& v){ return v.i_ == i_; }
};
int main(int argc, char *argv[ ])
{
call_traits_checker<comparible_UDT> c1;
comparible_UDT u;
c1(u);
call_traits_checker<int> c2;
int i = 2;
c2(i);
int* pi = &i;
int a[2] = {1,2};
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) && !defined(__ICL)
call_traits_checker<int*> c3;
c3(pi);
call_traits_checker<int&> c4;
c4(i);
call_traits_checker<const int&> c5;
c5(i);
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__) && !defined(__SUNPRO_CC)
call_traits_checker<int[2]> c6;
c6(a);
#endif
#endif
check_wrap(test_wrap_type(2), 2);
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
check_wrap(test_wrap_type(a), a);
check_make_pair(test::make_pair(a, a), a, a);
#endif
// cv-qualifiers applied to reference types should have no effect
// declare these here for later use with is_reference and remove_reference:
typedef int& r_type;
typedef const r_type cr_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)
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)))
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
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
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:
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:
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 check_result(argc, argv);
}
//
// define call_traits tests to check that the assertions in the docs do actually work
// this is an instantiate only set of tests:
//
template <typename T, bool isarray = false>
struct call_traits_test
{
typedef ::boost::call_traits<T> ct;
typedef typename ct::param_type param_type;
typedef typename ct::reference reference;
typedef typename ct::const_reference const_reference;
typedef typename ct::value_type value_type;
static void assert_construct(param_type val);
};
template <typename T, bool isarray>
void call_traits_test<T, isarray>::assert_construct(typename call_traits_test<T, isarray>::param_type val)
{
//
// this is to check that the call_traits assertions are valid:
T t(val);
value_type v(t);
reference r(t);
const_reference cr(t);
param_type p(t);
value_type v2(v);
value_type v3(r);
value_type v4(p);
reference r2(v);
reference r3(r);
const_reference cr2(v);
const_reference cr3(r);
const_reference cr4(cr);
const_reference cr5(p);
param_type p2(v);
param_type p3(r);
param_type p4(p);
unused_variable(v2);
unused_variable(v3);
unused_variable(v4);
unused_variable(r2);
unused_variable(r3);
unused_variable(cr2);
unused_variable(cr3);
unused_variable(cr4);
unused_variable(cr5);
unused_variable(p2);
unused_variable(p3);
unused_variable(p4);
}
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <typename T>
struct call_traits_test<T, true>
{
typedef ::boost::call_traits<T> ct;
typedef typename ct::param_type param_type;
typedef typename ct::reference reference;
typedef typename ct::const_reference const_reference;
typedef typename ct::value_type value_type;
static void assert_construct(param_type val);
};
template <typename T>
void call_traits_test<T, true>::assert_construct(typename boost::call_traits<T>::param_type val)
{
//
// this is to check that the call_traits assertions are valid:
T t;
value_type v(t);
value_type v5(val);
reference r = t;
const_reference cr = t;
reference r2 = r;
#ifndef __BORLANDC__
// C++ Builder buglet:
const_reference cr2 = r;
#endif
param_type p(t);
value_type v2(v);
const_reference cr3 = cr;
value_type v3(r);
value_type v4(p);
param_type p2(v);
param_type p3(r);
param_type p4(p);
unused_variable(v2);
unused_variable(v3);
unused_variable(v4);
unused_variable(v5);
#ifndef __BORLANDC__
unused_variable(r2);
unused_variable(cr2);
#endif
unused_variable(cr3);
unused_variable(p2);
unused_variable(p3);
unused_variable(p4);
}
#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
//
// now check call_traits assertions by instantiating call_traits_test:
template struct call_traits_test<int>;
template struct call_traits_test<const int>;
template struct call_traits_test<int*>;
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES)
template struct call_traits_test<int&>;
template struct call_traits_test<const int&>;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
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,31 +0,0 @@
// Boost checked_delete test program ---------------------------------------//
// (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 for most recent version including documentation.
// Revision History
// 21 May 01 Initial version (Beman Dawes)
#include <boost/utility.hpp> // for checked_delete
// This program demonstrates compiler errors when trying to delete an
// incomplete type.
namespace
{
class Incomplete;
}
int main()
{
Incomplete * p;
boost::checked_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,98 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=iso-8859-1">
<meta name="Template"
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
<title>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:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits&lt;first_type&gt;::param_type first_param_type;
typedef typename call_traits&lt;second_type&gt;::param_type second_param_type;
typedef typename call_traits&lt;first_type&gt;::reference first_reference;
typedef typename call_traits&lt;second_type&gt;::reference second_reference;
typedef typename call_traits&lt;first_type&gt;::const_reference first_const_reference;
typedef typename call_traits&lt;second_type&gt;::const_reference second_const_reference;
compressed_pair() : base() {}
compressed_pair(first_param_type x, second_param_type y);
explicit compressed_pair(first_param_type x);
explicit compressed_pair(second_param_type y);
compressed_pair&amp; operator=(const compressed_pair&amp;);
first_reference first();
first_const_reference first() const;
second_reference second();
second_const_reference second() const;
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 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,401 +0,0 @@
// boost::compressed_pair test program
// (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:
// Enabled tests for VC6.
#include <iostream>
#include <typeinfo>
#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;
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
{
int i;
non_empty1() : i(1){}
non_empty1(int v) : i(v){}
friend bool operator==(const non_empty1& a, const non_empty1& b)
{ return a.i == b.i; }
};
struct non_empty2
{
int i;
non_empty2() : i(3){}
non_empty2(int v) : i(v){}
friend bool operator==(const non_empty2& a, const non_empty2& b)
{ return a.i == b.i; }
};
#ifdef __GNUC__
using std::swap;
#endif
template <class T1, class T2>
struct compressed_pair_tester
{
// define the types we need:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
// define our test proc:
static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
};
template <class T1, class T2>
void compressed_pair_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
{
#ifndef __GNUC__
// gcc 2.90 can't cope with function scope using
// declarations, and generates an internal compiler error...
using std::swap;
#endif
// default construct:
boost::compressed_pair<T1,T2> cp1;
// first param construct:
boost::compressed_pair<T1,T2> cp2(p1);
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_TEST(cp3.second() == p2);
BOOST_TEST(cp3.first() == p1);
// both param construct:
boost::compressed_pair<T1,T2> cp4(p1, p2);
BOOST_TEST(cp4.first() == p1);
BOOST_TEST(cp4.second() == p2);
boost::compressed_pair<T1,T2> cp5(p3, p4);
BOOST_TEST(cp5.first() == p3);
BOOST_TEST(cp5.second() == p4);
// check const members:
const boost::compressed_pair<T1,T2>& cpr1 = cp4;
BOOST_TEST(cpr1.first() == p1);
BOOST_TEST(cpr1.second() == p2);
// copy construct:
boost::compressed_pair<T1,T2> cp6(cp4);
BOOST_TEST(cp6.first() == p1);
BOOST_TEST(cp6.second() == p2);
// assignment:
cp1 = cp4;
BOOST_TEST(cp1.first() == p1);
BOOST_TEST(cp1.second() == p2);
cp1 = cp5;
BOOST_TEST(cp1.first() == p3);
BOOST_TEST(cp1.second() == p4);
// swap:
cp4.swap(cp5);
BOOST_TEST(cp4.first() == p3);
BOOST_TEST(cp4.second() == p4);
BOOST_TEST(cp5.first() == p1);
BOOST_TEST(cp5.second() == p2);
swap(cp4,cp5);
BOOST_TEST(cp4.first() == p1);
BOOST_TEST(cp4.second() == p2);
BOOST_TEST(cp5.first() == p3);
BOOST_TEST(cp5.second() == p4);
}
//
// tests for case where one or both
// parameters are reference types:
//
template <class T1, class T2>
struct compressed_pair_reference_tester
{
// define the types we need:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
// define our test proc:
static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
};
template <class T1, class T2>
void compressed_pair_reference_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
{
#ifndef __GNUC__
// gcc 2.90 can't cope with function scope using
// declarations, and generates an internal compiler error...
using std::swap;
#endif
// both param construct:
boost::compressed_pair<T1,T2> cp4(p1, p2);
BOOST_TEST(cp4.first() == p1);
BOOST_TEST(cp4.second() == p2);
boost::compressed_pair<T1,T2> cp5(p3, p4);
BOOST_TEST(cp5.first() == p3);
BOOST_TEST(cp5.second() == p4);
// check const members:
const boost::compressed_pair<T1,T2>& cpr1 = cp4;
BOOST_TEST(cpr1.first() == p1);
BOOST_TEST(cpr1.second() == p2);
// copy construct:
boost::compressed_pair<T1,T2> cp6(cp4);
BOOST_TEST(cp6.first() == p1);
BOOST_TEST(cp6.second() == p2);
// assignment:
// VC6 bug:
// When second() is an empty class, VC6 performs the
// assignment by doing a memcpy - even though the empty
// class is really a zero sized base class, the result
// is that the memory of first() gets trampled over.
// Similar arguments apply to the case that first() is
// an empty base class.
// Strangely the problem is dependent upon the compiler
// settings - some generate the problem others do not.
cp4.first() = p3;
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:
//
template <class T1, class T2>
struct compressed_pair_reference1_tester
{
// define the types we need:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
// define our test proc:
static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
};
template <class T1, class T2>
void compressed_pair_reference1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
{
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// first param construct:
boost::compressed_pair<T1,T2> cp2(p1);
cp2.second() = p2;
BOOST_TEST(cp2.first() == p1);
BOOST_TEST(cp2.second() == p2);
#endif
}
//
// supplimentary tests for case where second arg only is a reference type:
//
template <class T1, class T2>
struct compressed_pair_reference2_tester
{
// define the types we need:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
// define our test proc:
static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
};
template <class T1, class T2>
void compressed_pair_reference2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
{
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// second param construct:
boost::compressed_pair<T1,T2> cp3(p2);
cp3.first() = p1;
BOOST_TEST(cp3.second() == p2);
BOOST_TEST(cp3.first() == p1);
#endif
}
//
// tests for where one or the other parameter is an array:
//
template <class T1, class T2>
struct compressed_pair_array1_tester
{
// define the types we need:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
// define our test proc:
static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
};
template <class T1, class T2>
void compressed_pair_array1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
{
// default construct:
boost::compressed_pair<T1,T2> cp1;
// second param construct:
boost::compressed_pair<T1,T2> cp3(p2);
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_TEST(cpr1.first()[0] == p1[0]);
BOOST_TEST(cpr1.second() == p2);
BOOST_TEST(sizeof(T1) == sizeof(cp1.first()));
}
template <class T1, class T2>
struct compressed_pair_array2_tester
{
// define the types we need:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
// define our test proc:
static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
};
template <class T1, class T2>
void compressed_pair_array2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
{
// default construct:
boost::compressed_pair<T1,T2> cp1;
// first param construct:
boost::compressed_pair<T1,T2> cp2(p1);
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_TEST(cpr1.first() == p1);
BOOST_TEST(cpr1.second()[0] == p2[0]);
BOOST_TEST(sizeof(T2) == sizeof(cp1.second()));
}
template <class T1, class T2>
struct compressed_pair_array_tester
{
// define the types we need:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
// define our test proc:
static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
};
template <class T1, class T2>
void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
{
// default construct:
boost::compressed_pair<T1,T2> cp1;
cp1.first()[0] = p1[0];
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_TEST(cpr1.first()[0] == p1[0]);
BOOST_TEST(cpr1.second()[0] == p2[0]);
BOOST_TEST(sizeof(T1) == sizeof(cp1.first()));
BOOST_TEST(sizeof(T2) == sizeof(cp1.second()));
}
int test_main(int, char *[])
{
// declare some variables to pass to the tester:
non_empty1 ne1(2);
non_empty1 ne2(3);
non_empty2 ne3(4);
non_empty2 ne4(5);
empty_POD_UDT e1;
empty_UDT e2;
// T1 != T2, both non-empty
compressed_pair_tester<non_empty1,non_empty2>::test(ne1, ne3, ne2, ne4);
// T1 != T2, T2 empty
compressed_pair_tester<non_empty1,empty_POD_UDT>::test(ne1, e1, ne2, e1);
// T1 != T2, T1 empty
compressed_pair_tester<empty_POD_UDT,non_empty2>::test(e1, ne3, e1, ne4);
// T1 != T2, both empty
compressed_pair_tester<empty_POD_UDT,empty_UDT>::test(e1, e2, e1, e2);
// T1 == T2, both non-empty
compressed_pair_tester<non_empty1,non_empty1>::test(ne1, ne1, ne2, ne2);
// T1 == T2, both empty
compressed_pair_tester<empty_UDT,empty_UDT>::test(e2, e2, e2, e2);
// test references:
// T1 != T2, both non-empty
compressed_pair_reference_tester<non_empty1&,non_empty2>::test(ne1, ne3, ne2, ne4);
compressed_pair_reference_tester<non_empty1,non_empty2&>::test(ne1, ne3, ne2, ne4);
compressed_pair_reference1_tester<non_empty1&,non_empty2>::test(ne1, ne3, ne2, ne4);
compressed_pair_reference2_tester<non_empty1,non_empty2&>::test(ne1, ne3, ne2, ne4);
// T1 != T2, T2 empty
compressed_pair_reference_tester<non_empty1&,empty_POD_UDT>::test(ne1, e1, ne2, e1);
compressed_pair_reference1_tester<non_empty1&,empty_POD_UDT>::test(ne1, e1, ne2, e1);
// T1 != T2, T1 empty
compressed_pair_reference_tester<empty_POD_UDT,non_empty2&>::test(e1, ne3, e1, ne4);
compressed_pair_reference2_tester<empty_POD_UDT,non_empty2&>::test(e1, ne3, e1, ne4);
// T1 == T2, both non-empty
compressed_pair_reference_tester<non_empty1&,non_empty1&>::test(ne1, ne1, ne2, ne2);
// tests arrays:
non_empty1 nea1[2];
non_empty1 nea2[2];
non_empty2 nea3[2];
non_empty2 nea4[2];
nea1[0] = non_empty1(5);
nea2[0] = non_empty1(6);
nea3[0] = non_empty2(7);
nea4[0] = non_empty2(8);
// T1 != T2, both non-empty
compressed_pair_array1_tester<non_empty1[2],non_empty2>::test(nea1, ne3, nea2, ne4);
compressed_pair_array2_tester<non_empty1,non_empty2[2]>::test(ne1, nea3, ne2, nea4);
compressed_pair_array_tester<non_empty1[2],non_empty2[2]>::test(nea1, nea3, nea2, nea4);
// T1 != T2, T2 empty
compressed_pair_array1_tester<non_empty1[2],empty_POD_UDT>::test(nea1, e1, nea2, e1);
// T1 != T2, T1 empty
compressed_pair_array2_tester<empty_POD_UDT,non_empty2[2]>::test(e1, nea3, e1, nea4);
// T1 == T2, both non-empty
compressed_pair_array_tester<non_empty1[2],non_empty1[2]>::test(nea1, nea1, nea2, nea2);
return 0;
}
unsigned int expected_failures = 0;

View File

@ -1,325 +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>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

@ -1,57 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
#include <boost/config.hpp>
#include <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;
// Use counting iterator to fill in the array of pointers.
// causes an ICE with MSVC6
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
std::copy(boost::make_counting_iterator(numbers.begin()),
boost::make_counting_iterator(numbers.end()),
std::back_inserter(pointers));
#endif
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1300)
// 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;
}

View File

@ -1,269 +0,0 @@
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears in
// all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org for most recent version including documentation.
//
// Revision History
// 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(BOOST_HAS_LONG_LONG)
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) || BOOST_MSVC > 1200 || 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,32 +0,0 @@
#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
//
// current_function_test.cpp - a test for boost/current_function.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
#include <boost/current_function.hpp>
#include <cstdio>
void message(char const * file, long line, char const * func, char const * msg)
{
std::printf("%s(%ld): %s in function '%s'\n", file, line, msg, func);
}
#define MESSAGE(msg) message(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, msg)
int main()
{
MESSAGE("assertion failed");
}

View File

@ -1,273 +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>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

@ -1,61 +0,0 @@
// 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_STD_ITERATOR_TRAITS
// 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;
}

View File

@ -1,41 +0,0 @@
// (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

@ -1,169 +0,0 @@
<!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,150 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>
<head>
<title>Generator 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>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.
<h2>Synopsis</h2>
<blockquote>
<pre>
namespace boost {
template &lt;class Generator&gt;
class generator_iterator_policies;
template &lt;class Generator&gt;
class generator_iterator_generator;
template &lt;class Generator&gt;
typename generator_iterator_generator&lt;Generator&gt;::type
make_generator_iterator(Generator &amp; gen);
}
</pre>
</blockquote>
<hr>
<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 <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>
<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>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>
<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>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.
<br>
<hr>
<h2><a name="make_generator_iterator">The Generator Iterator Object Generator</a></h2>
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.
<blockquote>
<pre>
template &lt;class Generator&gt;
typename generator_iterator_generator&lt;Generator&gt;::type
make_function_output_iterator(Generator &amp; gen);
</pre>
</blockquote>
<hr>
<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
{
public:
typedef int result_type;
my_generator() : state(0) { }
int operator()() { return ++state; }
private:
int state;
};
int main()
{
my_generator gen;
boost::generator_iterator_generator&lt;my_generator&gt;::type it = boost::make_generator_iterator(gen);
for(int i = 0; i &lt; 10; ++i, ++it)
std::cout &lt;&lt; *it &lt;&lt; std::endl;
}
</pre>
</blockquote>
<hr>
Written by Jens Maurer.
</body>
</html>

View File

@ -1,366 +0,0 @@
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears in
// all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org for most recent version including documentation.
//
// Revision History
// 11 Feb 2001 Compile with Borland, re-enable failing tests (David Abrahams)
// 29 Jan 2001 Initial revision (David Abrahams)
#include <boost/half_open_range.hpp>
#include <boost/utility.hpp>
#include <iterator>
#include <stdlib.h>
#include <vector>
#include <list>
#include <cassert>
#include <stdexcept>
#ifndef BOOST_NO_LIMITS
# include <limits>
#endif
#ifndef BOOST_NO_SLIST
# include <slist>
#endif
inline unsigned unsigned_random(unsigned max)
{
return (max > 0) ? (unsigned)rand() % max : 0;
}
// Special tests for ranges supporting random access
template <class T>
void category_test_1(
const boost::half_open_range<T>& r, std::random_access_iterator_tag)
{
typedef boost::half_open_range<T> range;
typedef typename range::size_type size_type;
size_type size = r.size();
// pick a random offset
size_type offset = unsigned_random(size);
typename range::value_type x = *(r.begin() + offset);
// test contains(value_type)
assert(r.contains(r.start()) == !r.empty());
assert(!r.contains(r.finish()));
assert(r.contains(x) == (offset != size));
range::const_iterator p = r.find(x);
assert((p == r.end()) == (x == r.finish()));
assert(r.find(r.finish()) == r.end());
if (offset != size)
{
assert(x == r[offset]);
assert(x == r.at(offset));
}
bool caught_out_of_range = false;
try {
bool never_initialized = x == r.at(size);
(void)never_initialized;
}
catch(std::out_of_range&)
{
caught_out_of_range = true;
}
catch(...)
{
}
assert(caught_out_of_range);
}
// Those tests must be skipped for other ranges
template <class T>
void category_test_1(
const boost::half_open_range<T>&, std::forward_iterator_tag)
{
}
unsigned indices[][2] = { {0,0},{0,1},{0,2},{0,3},
{1,1},{1,2},{1,3},
{2,2},{2,3},
{3,3}};
template <class Range>
void category_test_2(
const std::vector<Range>& ranges, unsigned i, unsigned j, std::random_access_iterator_tag)
{
typedef Range range;
const range& ri = ranges[i];
const range& rj = ranges[j];
if (indices[i][0] <= indices[j][0] && indices[i][1] >= indices[j][1])
assert(ri.contains(rj));
if (ri.contains(rj))
assert((ri & rj) == rj);
assert(boost::intersects(ri, rj) == !(ri & rj).empty());
range t1(ri);
t1 &= rj;
assert(t1 == range(indices[i][0] > indices[j][0] ? ri.start() : rj.start(),
indices[i][1] < indices[j][1] ? ri.finish() : rj.finish()));
assert(t1 == (ri & rj));
range t2(ri);
t2 |= rj;
if (ri.empty())
assert(t2 == rj);
else if (rj.empty())
assert(t2 == ri);
else
assert(t2 == range(indices[i][0] < indices[j][0] ? ri.start() : rj.start(),
indices[i][1] > indices[j][1] ? ri.finish() : rj.finish()));
assert(t2 == (ri | rj));
if (i == j)
assert(ri == rj);
if (ri.empty() || rj.empty())
assert((ri == rj) == (ri.empty() && rj.empty()));
else
assert((ri == rj) == (ri.start() == rj.start() && ri.finish() == rj.finish()));
assert((ri == rj) == !(ri != rj));
bool same = ri == rj;
bool one_empty = ri.empty() != rj.empty();
std::less<range> less;
std::less_equal<range> less_equal;
std::greater<range> greater;
std::greater_equal<range> greater_equal;
if (same)
{
assert(greater_equal(ri,rj));
assert(less_equal(ri,rj));
assert(!greater(ri,rj));
assert(!less(ri,rj));
}
else if (one_empty)
{
const range& empty = ri.empty() ? ri : rj;
const range& non_empty = rj.empty() ? ri : rj;
assert(less(empty,non_empty));
assert(less_equal(empty,non_empty));
assert(!greater(empty,non_empty));
assert(!greater_equal(empty,non_empty));
assert(!less(non_empty,empty));
assert(!less_equal(non_empty,empty));
assert(greater(non_empty,empty));
assert(greater_equal(non_empty,empty));
}
else {
if (indices[i][0] < indices[j][0] ||
indices[i][0] == indices[j][0] && indices[i][1] < indices[j][1])
{
assert(!greater_equal(ri,rj));
assert(less(ri,rj));
}
if (indices[i][0] < indices[j][0] ||
indices[i][0] == indices[j][0] && indices[i][1] <= indices[j][1])
{
assert(!greater(ri,rj));
assert(less_equal(ri,rj));
}
if (indices[i][0] > indices[j][0] ||
indices[i][0] == indices[j][0] && indices[i][1] > indices[j][1])
{
assert(!less_equal(ri,rj));
assert(greater(ri,rj));
}
if (indices[i][0] > indices[j][0] ||
indices[i][0] == indices[j][0] && indices[i][1] >= indices[j][1])
{
assert(!less(ri,rj));
assert(greater_equal(ri,rj));
}
}
}
template <class Range>
void category_test_2(
const std::vector<Range>&, unsigned, unsigned, std::forward_iterator_tag)
{
}
template <class T>
void category_test_2(
const std::vector<boost::half_open_range<T> >&, unsigned, unsigned, std::bidirectional_iterator_tag)
{
}
template <class Range>
void test_back(Range& x, std::bidirectional_iterator_tag)
{
assert(x.back() == boost::prior(x.finish()));
}
template <class Range>
void test_back(Range& x, std::forward_iterator_tag)
{
}
template <class T>
boost::half_open_range<T> range_identity(const boost::half_open_range<T>& x)
{
return x;
}
template <class T>
void test(T x0, T x1, T x2, T x3)
{
std::vector<boost::half_open_range<T> > ranges;
typedef boost::half_open_range<T> range;
T bounds[4] = { x0, x1, x2, x3 };
const std::size_t num_ranges = sizeof(indices)/sizeof(*indices);
// test construction
for (std::size_t n = 0; n < num_ranges;++n)
{
T start = bounds[indices[n][0]];
T finish = bounds[indices[n][1]];
boost::half_open_range<T> r(start, finish);
ranges.push_back(r);
}
// test implicit conversion from std::pair<T,T>
range converted = std::pair<T,T>(x0,x0);
(void)converted;
// test assignment, equality and inequality
range r00 = range(x0, x0);
assert(r00 == range(x0,x0));
assert(r00 == range(x1,x1)); // empty ranges are all equal
if (x3 != x0)
assert(r00 != range(x0, x3));
r00 = range(x0, x3);
assert(r00 == range(x0, x3));
if (x3 != x0)
assert(r00 != range(x0, x0));
typedef typename range::iterator iterator;
typedef typename iterator::iterator_category category;
for (unsigned i = 0; i < num_ranges; ++i)
{
const range& r = ranges[i];
// test begin(), end(), basic iteration.
unsigned count = 0;
for (range::const_iterator p = r.begin(), finish = r.end();
p != finish;
++p, ++count)
{
assert(count < 2100);
}
// test size(), empty(), front(), back()
assert((unsigned)r.size() == count);
if (indices[i][0] == indices[i][1])
assert(r.empty());
if (r.empty())
assert(r.size() == 0);
if (!r.empty())
{
assert(r.front() == r.start());
test_back(r, category());
}
// test swap
range r1(r);
range r2(x0,x3);
const bool same = r1 == r2;
r1.swap(r2);
assert(r1 == range(x0,x3));
assert(r2 == r);
if (!same) {
assert(r1 != r);
assert(r2 != range(x0,x3));
}
// do individual tests for random-access iterators
category_test_1(r, category());
}
for (unsigned j = 0; j < num_ranges; ++j) {
for (unsigned k = 0; k < num_ranges; ++k) {
category_test_2(ranges, j, k, category());
}
}
}
template <class Integer>
void test_integer(Integer* = 0) // default arg works around MSVC bug
{
Integer a = 0;
Integer b = a + unsigned_random(128 - a);
Integer c = b + unsigned_random(128 - b);
Integer d = c + unsigned_random(128 - c);
test(a, b, c, d);
}
template <class Container>
void test_container(Container* = 0) // default arg works around MSVC bug
{
Container c(unsigned_random(1673));
const typename Container::size_type offset1 = unsigned_random(c.size());
const typename Container::size_type offset2 = unsigned_random(c.size() - offset1);
typename Container::iterator internal1 = c.begin();
std::advance(internal1, offset1);
typename Container::iterator internal2 = internal1;
std::advance(internal2, offset2);
test(c.begin(), internal1, internal2, c.end());
typedef typename Container::const_iterator const_iterator;
test(const_iterator(c.begin()),
const_iterator(internal1),
const_iterator(internal2),
const_iterator(c.end()));
}
int main()
{
// Test the built-in integer types.
test_integer<char>();
test_integer<unsigned char>();
test_integer<signed char>();
test_integer<wchar_t>();
test_integer<short>();
test_integer<unsigned short>();
test_integer<int>();
test_integer<unsigned int>();
test_integer<long>();
test_integer<unsigned long>();
#if defined(BOOST_HAS_LONG_LONG)
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,12 +1,5 @@
#ifndef BOOST_ASSERT_HPP_INCLUDED
#define BOOST_ASSERT_HPP_INCLUDED
#if _MSC_VER >= 1020
#pragma once
#endif
//
// boost/assert.hpp
// boost/assert.hpp - BOOST_ASSERT(expr)
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
//
@ -15,38 +8,31 @@
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// Note: There are no include guards. This is intentional.
//
// 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.
// See http://www.boost.org/libs/utility/assert.html for documentation.
//
#ifndef BOOST_DEBUG
#define BOOST_DEBUG 0
#endif
#undef BOOST_ASSERT
#if BOOST_DEBUG
#if defined(BOOST_DISABLE_ASSERTS)
#include <assert.h>
# define BOOST_ASSERT(expr) ((void)0)
#ifndef BOOST_ASSERT
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
#include <boost/current_function.hpp>
bool boost_error(char const * expr, char const * func, char const * file, long line);
namespace boost
{
# define BOOST_ASSERT(expr) ((expr) || !boost_error(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__) || (assert(expr), true))
void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
#endif // #ifndef BOOST_ASSERT
} // namespace boost
#else // #if BOOST_DEBUG
#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#undef BOOST_ASSERT
#define BOOST_ASSERT(expr) ((void)0)
#endif // #if BOOST_DEBUG
#endif // #ifndef BOOST_ASSERT_HPP_INCLUDED
#else
# include <assert.h>
# define BOOST_ASSERT(expr) assert(expr)
#endif

View File

@ -3,7 +3,7 @@
// 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 http://www.boost.org/libs/utility/call_traits.htm for Documentation.
// See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp
// for full copyright notices.

View File

@ -9,25 +9,28 @@
// boost/checked_delete.hpp
//
// Copyright (c) 1999, 2000, 2001, 2002 boost.org
// Copyright (c) 2002, 2003 Peter Dimov
//
// Permission to copy, use, modify, sell and distribute this software
// is granted provided this copyright notice appears in all copies.
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// See http://www.boost.org/libs/utility/checked_delete.html for documentation.
//
namespace boost
{
// verify that types are complete for increased safety
template< typename T > inline void checked_delete(T * x)
template<class T> inline void checked_delete(T * x)
{
typedef char type_must_be_complete[sizeof(T)];
delete x;
}
template< typename T > inline void checked_array_delete(T * x)
template<class T> inline void checked_array_delete(T * x)
{
typedef char type_must_be_complete[sizeof(T)];
delete [] x;
@ -38,9 +41,9 @@ template<class T> struct checked_deleter
typedef void result_type;
typedef T * argument_type;
void operator()(T * x)
void operator()(T * x) const
{
checked_delete(x);
boost::checked_delete(x);
}
};
@ -49,9 +52,9 @@ template<class T> struct checked_array_deleter
typedef void result_type;
typedef T * argument_type;
void operator()(T * x)
void operator()(T * x) const
{
checked_array_delete(x);
boost::checked_array_delete(x);
}
};

View File

@ -15,6 +15,8 @@
// This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
//
// http://www.boost.org/libs/utility/current_function.html
//
namespace boost
{
@ -25,7 +27,7 @@ namespace detail
inline void current_function_helper()
{
#if defined(__GNUC__)
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600))
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
@ -33,7 +35,11 @@ inline void current_function_helper()
# define BOOST_CURRENT_FUNCTION __FUNCSIG__
#elif defined(__BORLANDC__)
#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
# define BOOST_CURRENT_FUNCTION __FUNCTION__
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
# define BOOST_CURRENT_FUNCTION __FUNC__

View File

@ -1,158 +0,0 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & 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.
// See http://www.boost.org for most recent version including documentation.
// call_traits: defines typedefs for function usage
// (see libs/utility/call_traits.htm)
/* Release notes:
23rd July 2000:
Fixed array specialization. (JM)
Added Borland specific fixes for reference types
(issue raised by Steve Cleary).
*/
#ifndef BOOST_DETAIL_CALL_TRAITS_HPP
#define BOOST_DETAIL_CALL_TRAITS_HPP
#ifndef BOOST_CONFIG_HPP
#include <boost/config.hpp>
#endif
#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{
namespace detail{
template <typename T, bool small_>
struct ct_imp2
{
typedef const T& param_type;
};
template <typename T>
struct ct_imp2<T, true>
{
typedef const T param_type;
};
template <typename T, bool isp, bool b1>
struct ct_imp
{
typedef const T& param_type;
};
template <typename T, bool isp>
struct ct_imp<T, isp, true>
{
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
};
template <typename T, bool b1>
struct ct_imp<T, true, b1>
{
typedef T const param_type;
};
}
template <typename T>
struct call_traits
{
public:
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
//
// C++ Builder workaround: we should be able to define a compile time
// constant and pass that as a single template parameter to ct_imp<T,bool>,
// 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 detail::ct_imp<
T,
::boost::is_pointer<T>::value,
::boost::is_arithmetic<T>::value
>::param_type param_type;
};
template <typename T>
struct call_traits<T&>
{
typedef T& value_type;
typedef T& reference;
typedef const T& const_reference;
typedef T& param_type; // hh removed const
};
#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
// 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
// references as distinct types...
template <typename T>
struct call_traits<T&const>
{
typedef T& value_type;
typedef T& reference;
typedef const T& const_reference;
typedef T& param_type; // hh removed const
};
template <typename T>
struct call_traits<T&volatile>
{
typedef T& value_type;
typedef T& reference;
typedef const T& const_reference;
typedef T& param_type; // hh removed const
};
template <typename T>
struct call_traits<T&const volatile>
{
typedef T& value_type;
typedef T& reference;
typedef const T& const_reference;
typedef T& param_type; // hh removed const
};
#endif
#ifndef __SUNPRO_CC
template <typename T, std::size_t N>
struct call_traits<T [N]>
{
private:
typedef T array_type[N];
public:
// degrades array to pointer:
typedef const T* value_type;
typedef array_type& reference;
typedef const array_type& const_reference;
typedef const T* const param_type;
};
template <typename T, std::size_t N>
struct call_traits<const T [N]>
{
private:
typedef const T array_type[N];
public:
// degrades array to pointer:
typedef const T* value_type;
typedef array_type& reference;
typedef const array_type& const_reference;
typedef const T* const param_type;
};
#endif
}
#endif // BOOST_DETAIL_CALL_TRAITS_HPP

View File

@ -1,435 +0,0 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & 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.
// 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 2000:
// Removed default arguments from compressed_pair_switch to get
// C++ Builder 4 to accept them
// rewriten swap to get gcc and C++ builder to compile.
// added partial specialisations for case T1 == T2 to avoid duplicate constructor defs.
#ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP
#define BOOST_DETAIL_COMPRESSED_PAIR_HPP
#include <algorithm>
#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
namespace boost
{
template <class T1, class T2>
class compressed_pair;
// compressed_pair
namespace details
{
// JM altered 26 Jan 2000:
template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
struct compressed_pair_switch;
template <class T1, class T2>
struct compressed_pair_switch<T1, T2, false, false, false>
{static const int value = 0;};
template <class T1, class T2>
struct compressed_pair_switch<T1, T2, false, true, true>
{static const int value = 3;};
template <class T1, class T2>
struct compressed_pair_switch<T1, T2, false, true, false>
{static const int value = 1;};
template <class T1, class T2>
struct compressed_pair_switch<T1, T2, false, false, true>
{static const int value = 2;};
template <class T1, class T2>
struct compressed_pair_switch<T1, T2, true, true, true>
{static const int value = 4;};
template <class T1, class T2>
struct compressed_pair_switch<T1, T2, true, false, false>
{static const int value = 5;};
template <class T1, class T2, int Version> class compressed_pair_imp;
#ifdef __GNUC__
// workaround for GCC (JM):
using std::swap;
#endif
//
// can't call unqualified swap from within classname::swap
// as Koenig lookup rules will find only the classname::swap
// member function not the global declaration, so use cp_swap
// as a forwarding function (JM):
template <typename T>
inline void cp_swap(T& t1, T& t2)
{
#ifndef __GNUC__
using std::swap;
#endif
swap(t1, t2);
}
// 0 derive from neither
template <class T1, class T2>
class compressed_pair_imp<T1, T2, 0>
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_imp() {}
compressed_pair_imp(first_param_type x, second_param_type y)
: first_(x), second_(y) {}
compressed_pair_imp(first_param_type x)
: first_(x) {}
compressed_pair_imp(second_param_type y)
: second_(y) {}
first_reference first() {return first_;}
first_const_reference first() const {return first_;}
second_reference second() {return second_;}
second_const_reference second() const {return second_;}
void swap(::boost::compressed_pair<T1, T2>& y)
{
cp_swap(first_, y.first());
cp_swap(second_, y.second());
}
private:
first_type first_;
second_type second_;
};
// 1 derive from T1
template <class T1, class T2>
class compressed_pair_imp<T1, T2, 1>
: private T1
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_imp() {}
compressed_pair_imp(first_param_type x, second_param_type y)
: first_type(x), second_(y) {}
compressed_pair_imp(first_param_type x)
: first_type(x) {}
compressed_pair_imp(second_param_type y)
: second_(y) {}
first_reference first() {return *this;}
first_const_reference first() const {return *this;}
second_reference second() {return second_;}
second_const_reference second() const {return second_;}
void swap(::boost::compressed_pair<T1,T2>& y)
{
// no need to swap empty base class:
cp_swap(second_, y.second());
}
private:
second_type second_;
};
// 2 derive from T2
template <class T1, class T2>
class compressed_pair_imp<T1, T2, 2>
: private T2
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_imp() {}
compressed_pair_imp(first_param_type x, second_param_type y)
: second_type(y), first_(x) {}
compressed_pair_imp(first_param_type x)
: first_(x) {}
compressed_pair_imp(second_param_type y)
: second_type(y) {}
first_reference first() {return first_;}
first_const_reference first() const {return first_;}
second_reference second() {return *this;}
second_const_reference second() const {return *this;}
void swap(::boost::compressed_pair<T1,T2>& y)
{
// no need to swap empty base class:
cp_swap(first_, y.first());
}
private:
first_type first_;
};
// 3 derive from T1 and T2
template <class T1, class T2>
class compressed_pair_imp<T1, T2, 3>
: private T1,
private T2
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_imp() {}
compressed_pair_imp(first_param_type x, second_param_type y)
: first_type(x), second_type(y) {}
compressed_pair_imp(first_param_type x)
: first_type(x) {}
compressed_pair_imp(second_param_type y)
: second_type(y) {}
first_reference first() {return *this;}
first_const_reference first() const {return *this;}
second_reference second() {return *this;}
second_const_reference second() const {return *this;}
//
// no need to swap empty bases:
void swap(::boost::compressed_pair<T1,T2>&) {}
};
// JM
// 4 T1 == T2, T1 and T2 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>
: private T1
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_imp() {}
compressed_pair_imp(first_param_type x, second_param_type)
: first_type(x) {}
compressed_pair_imp(first_param_type x)
: first_type(x) {}
first_reference first() {return *this;}
first_const_reference first() const {return *this;}
second_reference second() {return *this;}
second_const_reference second() const {return *this;}
void swap(::boost::compressed_pair<T1,T2>&) {}
private:
};
// 5 T1 == T2 and are not empty: //JM
template <class T1, class T2>
class compressed_pair_imp<T1, T2, 5>
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_imp() {}
compressed_pair_imp(first_param_type x, second_param_type y)
: first_(x), second_(y) {}
compressed_pair_imp(first_param_type x)
: first_(x), second_(x) {}
first_reference first() {return first_;}
first_const_reference first() const {return first_;}
second_reference second() {return second_;}
second_const_reference second() const {return second_;}
void swap(::boost::compressed_pair<T1, T2>& y)
{
cp_swap(first_, y.first());
cp_swap(second_, y.second());
}
private:
first_type first_;
second_type second_;
};
} // details
template <class T1, class T2>
class compressed_pair
: private ::boost::details::compressed_pair_imp<T1, T2,
::boost::details::compressed_pair_switch<
T1,
T2,
::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
::boost::is_empty<T1>::value,
::boost::is_empty<T2>::value>::value>
{
private:
typedef details::compressed_pair_imp<T1, T2,
::boost::details::compressed_pair_switch<
T1,
T2,
::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
::boost::is_empty<T1>::value,
::boost::is_empty<T2>::value>::value> base;
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair() : base() {}
compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
explicit compressed_pair(first_param_type x) : base(x) {}
explicit compressed_pair(second_param_type y) : base(y) {}
first_reference first() {return base::first();}
first_const_reference first() const {return base::first();}
second_reference second() {return base::second();}
second_const_reference second() const {return base::second();}
void swap(compressed_pair& y) { base::swap(y); }
};
// JM
// Partial specialisation for case where T1 == T2:
//
template <class T>
class compressed_pair<T, T>
: private details::compressed_pair_imp<T, T,
::boost::details::compressed_pair_switch<
T,
T,
::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
::boost::is_empty<T>::value,
::boost::is_empty<T>::value>::value>
{
private:
typedef details::compressed_pair_imp<T, T,
::boost::details::compressed_pair_switch<
T,
T,
::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
::boost::is_empty<T>::value,
::boost::is_empty<T>::value>::value> base;
public:
typedef T first_type;
typedef T second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair() : base() {}
compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
#if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
explicit
#endif
compressed_pair(first_param_type x) : base(x) {}
first_reference first() {return base::first();}
first_const_reference first() const {return base::first();}
second_reference second() {return base::second();}
second_const_reference second() const {return base::second();}
void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
};
template <class T1, class T2>
inline
void
swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
{
x.swap(y);
}
} // boost
#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP

View File

@ -1,169 +0,0 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & 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.
// See http://www.boost.org for most recent version including documentation.
//
// Crippled version for crippled compilers:
// see libs/utility/call_traits.htm
//
/* Release notes:
01st October 2000:
Fixed call_traits on VC6, using "poor man's partial specialisation",
using ideas taken from "Generative programming" by Krzysztof Czarnecki
& Ulrich Eisenecker.
*/
#ifndef BOOST_OB_CALL_TRAITS_HPP
#define BOOST_OB_CALL_TRAITS_HPP
#ifndef BOOST_CONFIG_HPP
#include <boost/config.hpp>
#endif
#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{
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
//
// use member templates to emulate
// partial specialisation:
//
namespace detail{
template <class T>
struct standard_call_traits
{
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef const T& param_type;
};
template <class T>
struct simple_call_traits
{
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef const T param_type;
};
template <class T>
struct reference_call_traits
{
typedef T value_type;
typedef T reference;
typedef T const_reference;
typedef T param_type;
};
template <bool pointer, bool arithmetic, bool reference>
struct call_traits_chooser
{
template <class T>
struct rebind
{
typedef standard_call_traits<T> type;
};
};
template <>
struct call_traits_chooser<true, false, false>
{
template <class T>
struct rebind
{
typedef simple_call_traits<T> type;
};
};
template <>
struct call_traits_chooser<false, false, true>
{
template <class T>
struct rebind
{
typedef reference_call_traits<T> type;
};
};
template <bool size_is_small>
struct call_traits_sizeof_chooser2
{
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 <>
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;
};
};
} // namespace detail
template <typename T>
struct call_traits
{
private:
typedef detail::call_traits_chooser<
::boost::is_pointer<T>::value,
::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;
public:
typedef typename call_traits_type::value_type value_type;
typedef typename call_traits_type::reference reference;
typedef typename call_traits_type::const_reference const_reference;
typedef typename call_traits_type::param_type param_type;
};
#else
//
// sorry call_traits is completely non-functional
// blame your broken compiler:
//
template <typename T>
struct call_traits
{
typedef T value_type;
typedef T& reference;
typedef const T& const_reference;
typedef const T& param_type;
};
#endif // member templates
}
#endif // BOOST_OB_CALL_TRAITS_HPP

View File

@ -1,509 +0,0 @@
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & 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.
// See http://www.boost.org for most recent version including documentation.
// see libs/utility/compressed_pair.hpp
//
/* Release notes:
20 Jan 2001:
Fixed obvious bugs (David Abrahams)
07 Oct 2000:
Added better single argument constructor support.
03 Oct 2000:
Added VC6 support (JM).
23rd July 2000:
Additional comments added. (JM)
Jan 2000:
Original version: this version crippled for use with crippled compilers
- John Maddock Jan 2000.
*/
#ifndef BOOST_OB_COMPRESSED_PAIR_HPP
#define BOOST_OB_COMPRESSED_PAIR_HPP
#include <algorithm>
#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
namespace boost
{
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
//
// use member templates to emulate
// partial specialisation. Note that due to
// problems with overload resolution with VC6
// each of the compressed_pair versions that follow
// have one template single-argument constructor
// in place of two specific constructors:
//
template <class T1, class T2>
class compressed_pair;
namespace detail{
template <class A, class T1, class T2>
struct best_conversion_traits
{
typedef char one;
typedef char (&two)[2];
static A a;
static one test(T1);
static two test(T2);
enum { value = sizeof(test(a)) };
};
template <int>
struct init_one;
template <>
struct init_one<1>
{
template <class A, class T1, class T2>
static void init(const A& a, T1* p1, T2*)
{
*p1 = a;
}
};
template <>
struct init_one<2>
{
template <class A, class T1, class T2>
static void init(const A& a, T1*, T2* p2)
{
*p2 = a;
}
};
// T1 != T2, both non-empty
template <class T1, class T2>
class compressed_pair_0
{
private:
T1 _first;
T2 _second;
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_0() : _first(), _second() {}
compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {}
template <class A>
explicit compressed_pair_0(const A& val)
{
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
}
compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x)
: _first(x.first()), _second(x.second()) {}
#if 0
compressed_pair_0& operator=(const compressed_pair_0& x) {
cout << "assigning compressed pair 0" << endl;
_first = x._first;
_second = x._second;
cout << "finished assigning compressed pair 0" << endl;
return *this;
}
#endif
first_reference first() { return _first; }
first_const_reference first() const { return _first; }
second_reference second() { return _second; }
second_const_reference second() const { return _second; }
void swap(compressed_pair_0& y)
{
using std::swap;
swap(_first, y._first);
swap(_second, y._second);
}
};
// T1 != T2, T2 empty
template <class T1, class T2>
class compressed_pair_1 : T2
{
private:
T1 _first;
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_1() : T2(), _first() {}
compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
template <class A>
explicit compressed_pair_1(const A& val)
{
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
}
compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
: T2(x.second()), _first(x.first()) {}
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
// 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.
compressed_pair_1& operator=(const compressed_pair_1& x) {
_first = x._first;
T2::operator=(x);
return *this;
}
#endif
first_reference first() { return _first; }
first_const_reference first() const { return _first; }
second_reference second() { return *this; }
second_const_reference second() const { return *this; }
void swap(compressed_pair_1& y)
{
// no need to swap empty base class:
using std::swap;
swap(_first, y._first);
}
};
// T1 != T2, T1 empty
template <class T1, class T2>
class compressed_pair_2 : T1
{
private:
T2 _second;
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_2() : T1(), _second() {}
compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {}
template <class A>
explicit compressed_pair_2(const A& val)
{
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
}
compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x)
: T1(x.first()), _second(x.second()) {}
#if 0
compressed_pair_2& operator=(const compressed_pair_2& x) {
cout << "assigning compressed pair 2" << endl;
T1::operator=(x);
_second = x._second;
cout << "finished assigning compressed pair 2" << endl;
return *this;
}
#endif
first_reference first() { return *this; }
first_const_reference first() const { return *this; }
second_reference second() { return _second; }
second_const_reference second() const { return _second; }
void swap(compressed_pair_2& y)
{
// no need to swap empty base class:
using std::swap;
swap(_second, y._second);
}
};
// T1 != T2, both empty
template <class T1, class T2>
class compressed_pair_3 : T1, T2
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_3() : T1(), T2() {}
compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {}
template <class A>
explicit compressed_pair_3(const A& val)
{
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
}
compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x)
: T1(x.first()), T2(x.second()) {}
first_reference first() { return *this; }
first_const_reference first() const { return *this; }
second_reference second() { return *this; }
second_const_reference second() const { return *this; }
void swap(compressed_pair_3& y)
{
// no need to swap empty base classes:
}
};
// T1 == T2, and empty
template <class T1, class T2>
class compressed_pair_4 : T1
{
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_4() : T1() {}
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) {}
compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
: T1(x.first()){}
first_reference first() { return *this; }
first_const_reference first() const { return *this; }
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:
}
};
// T1 == T2, not empty
template <class T1, class T2>
class compressed_pair_5
{
private:
T1 _first;
T2 _second;
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair_5() : _first(), _second() {}
compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
// only one single argument constructor since T1 == T2
explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c)
: _first(c.first()), _second(c.second()) {}
first_reference first() { return _first; }
first_const_reference first() const { return _first; }
second_reference second() { return _second; }
second_const_reference second() const { return _second; }
void swap(compressed_pair_5& y)
{
using std::swap;
swap(_first, y._first);
swap(_second, y._second);
}
};
template <bool e1, bool e2, bool same>
struct compressed_pair_chooser
{
template <class T1, class T2>
struct rebind
{
typedef compressed_pair_0<T1, T2> type;
};
};
template <>
struct compressed_pair_chooser<false, true, false>
{
template <class T1, class T2>
struct rebind
{
typedef compressed_pair_1<T1, T2> type;
};
};
template <>
struct compressed_pair_chooser<true, false, false>
{
template <class T1, class T2>
struct rebind
{
typedef compressed_pair_2<T1, T2> type;
};
};
template <>
struct compressed_pair_chooser<true, true, false>
{
template <class T1, class T2>
struct rebind
{
typedef compressed_pair_3<T1, T2> type;
};
};
template <>
struct compressed_pair_chooser<true, true, true>
{
template <class T1, class T2>
struct rebind
{
typedef compressed_pair_4<T1, T2> type;
};
};
template <>
struct compressed_pair_chooser<false, false, true>
{
template <class T1, class T2>
struct rebind
{
typedef compressed_pair_5<T1, T2> type;
};
};
template <class T1, class T2>
struct compressed_pair_traits
{
private:
typedef compressed_pair_chooser<is_empty<T1>::value, is_empty<T2>::value, is_same<T1,T2>::value> chooser;
typedef typename chooser::template rebind<T1, T2> bound_type;
public:
typedef typename bound_type::type type;
};
} // namespace detail
template <class T1, class T2>
class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
{
private:
typedef typename detail::compressed_pair_traits<T1, T2>::type base_type;
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair() : base_type() {}
compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {}
template <class A>
explicit compressed_pair(const A& x) : base_type(x){}
first_reference first() { return base_type::first(); }
first_const_reference first() const { return base_type::first(); }
second_reference second() { return base_type::second(); }
second_const_reference second() const { return base_type::second(); }
};
template <class T1, class T2>
inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
{
x.swap(y);
}
#else
// no partial specialisation, no member templates:
template <class T1, class T2>
class compressed_pair
{
private:
T1 _first;
T2 _second;
public:
typedef T1 first_type;
typedef T2 second_type;
typedef typename call_traits<first_type>::param_type first_param_type;
typedef typename call_traits<second_type>::param_type second_param_type;
typedef typename call_traits<first_type>::reference first_reference;
typedef typename call_traits<second_type>::reference second_reference;
typedef typename call_traits<first_type>::const_reference first_const_reference;
typedef typename call_traits<second_type>::const_reference second_const_reference;
compressed_pair() : _first(), _second() {}
compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {}
explicit compressed_pair(first_param_type x) : _first(x), _second() {}
// can't define this in case T1 == T2:
// explicit compressed_pair(second_param_type y) : _first(), _second(y) {}
first_reference first() { return _first; }
first_const_reference first() const { return _first; }
second_reference second() { return _second; }
second_const_reference second() const { return _second; }
void swap(compressed_pair& y)
{
using std::swap;
swap(_first, y._first);
swap(_second, y._second);
}
};
template <class T1, class T2>
inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
{
x.swap(y);
}
#endif
} // boost
#endif // BOOST_OB_COMPRESSED_PAIR_HPP

View File

@ -9,6 +9,8 @@
// 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

View File

@ -0,0 +1,33 @@
// Boost next_prior.hpp header file ---------------------------------------//
// (C) Copyright Boost.org 1999-2003. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org/libs/utility for documentation.
#ifndef BOOST_NEXT_PRIOR_HPP_INCLUDED
#define BOOST_NEXT_PRIOR_HPP_INCLUDED
namespace boost {
// Helper functions for classes like bidirectional iterators not supporting
// operator+ and operator-
//
// Usage:
// const std::list<T>::iterator p = get_some_iterator();
// const std::list<T>::iterator prev = boost::prior(p);
// Contributed by Dave Abrahams
template <class T>
inline T next(T x) { return ++x; }
template <class T>
inline T prior(T x) { return --x; }
} // namespace boost
#endif // BOOST_NEXT_PRIOR_HPP_INCLUDED

View File

@ -0,0 +1,33 @@
// Boost noncopyable.hpp header file --------------------------------------//
// (C) Copyright Boost.org 1999-2003. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org/libs/utility for documentation.
#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
#define BOOST_NONCOPYABLE_HPP_INCLUDED
namespace boost {
// Private copy constructor and copy assignment ensure classes derived from
// class noncopyable cannot be copied.
// Contributed by Dave Abrahams
class noncopyable
{
protected:
noncopyable() {}
~noncopyable() {}
private: // emphasize the following members are private
noncopyable( const noncopyable& );
const noncopyable& operator=( const noncopyable& );
};
} // namespace boost
#endif // BOOST_NONCOPYABLE_HPP_INCLUDED

View File

@ -6,9 +6,13 @@
// 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 http://www.boost.org/libs/utility/operators.htm for documentation.
// Revision History
// 04 May 05 Added operator class bool_testable. (Sam Partington)
// 21 Oct 02 Modified implementation of operators to allow compilers with a
// correct named return value optimization (NRVO) to produce optimal
// code. (Daniel Frey)
// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
// 27 Aug 01 'left' form for non commutative operators added;
@ -75,9 +79,10 @@
#include <boost/config.hpp>
#include <boost/iterator.hpp>
#include <boost/preprocessor/seq/cat.hpp>
#if defined(__sgi) && !defined(__GNUC__)
#pragma set woff 1234
# pragma set woff 1234
#endif
#if defined(BOOST_MSVC)
@ -149,127 +154,112 @@ struct equality_comparable1 : B
friend bool operator!=(const T& x, const T& y) { return !(x == y); }
};
template <class T, class U, class B = ::boost::detail::empty_base>
struct multipliable2 : B
{
friend T operator*(T x, const U& y) { return x *= y; }
friend T operator*(const U& y, T x) { return x *= y; }
// A macro which produces "name_2left" from "name".
#define BOOST_OPERATOR2_LEFT(name) BOOST_PP_SEQ_CAT_S(1,(name)(2)(_)(left))
// NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
// This is the optimal implementation for ISO/ANSI C++,
// but it requires the compiler to implement the NRVO.
// If the compiler has no NRVO, this is the best symmetric
// implementation available.
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base> \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
friend T operator OP( const U& lhs, const T& rhs ) \
{ T nrv( rhs ); nrv OP##= lhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base> \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
};
template <class T, class B = ::boost::detail::empty_base>
struct multipliable1 : B
{
friend T operator*(T x, const T& y) { return x *= y; }
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base> \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class U, class B = ::boost::detail::empty_base> \
struct BOOST_OPERATOR2_LEFT(NAME) : B \
{ \
friend T operator OP( const U& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base> \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
};
template <class T, class 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; }
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
// For compilers without NRVO the following code is optimal, but not
// symmetric! Note that the implementation of
// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
// optimization opportunities to the compiler :)
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base> \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base> \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
};
template <class T, class B = ::boost::detail::empty_base>
struct addable1 : B
{
friend T operator+(T x, const T& y) { return x += y; }
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base> \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
}; \
\
template <class T, class U, class B = ::boost::detail::empty_base> \
struct BOOST_OPERATOR2_LEFT(NAME) : B \
{ \
friend T operator OP( const U& lhs, const T& rhs ) \
{ return T( lhs ) OP##= rhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base> \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
};
template <class T, class U, class B = ::boost::detail::empty_base>
struct subtractable2 : B
{
friend T operator-(T x, const U& 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_left : B
{
friend T operator-(const U& x, const T& y)
{ T result(x); return result -= y; }
};
BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
template <class T, class B = ::boost::detail::empty_base>
struct subtractable1 : B
{
friend T operator-(T x, const T& y) { return x -= y; }
};
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; }
};
#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
#undef BOOST_OPERATOR2_LEFT
// incrementable and decrementable contributed by Jeremy Siek
@ -278,9 +268,9 @@ struct incrementable : B
{
friend T operator++(T& x, int)
{
incrementable_type tmp(x);
incrementable_type nrv(x);
++x;
return tmp;
return nrv;
}
private: // The use of this typedef works around a Borland bug
typedef T incrementable_type;
@ -291,9 +281,9 @@ struct decrementable : B
{
friend T operator--(T& x, int)
{
decrementable_type tmp(x);
decrementable_type nrv(x);
--x;
return tmp;
return nrv;
}
private: // The use of this typedef works around a Borland bug
typedef T decrementable_type;
@ -319,31 +309,59 @@ struct indexable : B
}
};
// bool_testable -----------------------------------------------------------//
// (contributed by Sam Partington, David Abrahams and Daniel Frey) ---------//
template <class T, class B = ::boost::detail::empty_base>
struct bool_testable : B
{
friend bool operator!(const T& t) { return !static_cast<bool>(t); }
private:
typedef signed char private_number_type;
operator private_number_type() const;
};
// More operator classes (contributed by Daryle Walker) --------------------//
// (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
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; }
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
#define BOOST_BINARY_OPERATOR( NAME, OP ) \
template <class T, class U, class B = ::boost::detail::empty_base> \
struct NAME##2 : B \
{ \
friend T operator OP( const T& lhs, const U& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base> \
struct NAME##1 : B \
{ \
friend T operator OP( const T& lhs, const T& rhs ) \
{ T nrv( lhs ); nrv OP##= rhs; return nrv; } \
};
template <class T, class B = ::boost::detail::empty_base>
struct left_shiftable1 : B
{
friend T operator<<(T x, const T& 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> \
struct NAME##2 : B \
{ \
friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
}; \
\
template <class T, class B = ::boost::detail::empty_base> \
struct NAME##1 : B \
{ \
friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
};
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; }
};
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
template <class T, class B = ::boost::detail::empty_base>
struct right_shiftable1 : B
{
friend T operator>>(T x, const T& y) { return x >>= y; }
};
BOOST_BINARY_OPERATOR( left_shiftable, << )
BOOST_BINARY_OPERATOR( right_shiftable, >> )
#undef BOOST_BINARY_OPERATOR
template <class T, class U, class B = ::boost::detail::empty_base>
struct equivalent2 : B
@ -811,6 +829,8 @@ BOOST_OPERATOR_TEMPLATE1(decrementable)
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
BOOST_OPERATOR_TEMPLATE3(indexable)
BOOST_OPERATOR_TEMPLATE1(bool_testable)
BOOST_OPERATOR_TEMPLATE(left_shiftable)
BOOST_OPERATOR_TEMPLATE(right_shiftable)
BOOST_OPERATOR_TEMPLATE(equivalent)

View File

@ -7,6 +7,7 @@
# include <boost/config.hpp>
# include <boost/utility/addressof.hpp>
# include <boost/mpl/bool.hpp>
//
// ref.hpp - ref/cref, useful helper functions
@ -52,7 +53,7 @@ private:
T* t_;
};
# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x570)
# define BOOST_REF_CONST
# else
# define BOOST_REF_CONST const
@ -73,16 +74,14 @@ template<class T> inline reference_wrapper<T const> BOOST_REF_CONST cref(T 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 mpl::true_
{
public:
BOOST_STATIC_CONSTANT(bool, value = true);
};
template<typename T>
@ -144,8 +143,10 @@ 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,63 +1,21 @@
// boost utility.hpp header file -------------------------------------------//
// Boost utility.hpp header file -------------------------------------------//
// (C) Copyright boost.org 1999. Permission to copy, use, modify, sell
// (C) Copyright Boost.org 1999-2003. Permission to copy, use, modify, sell
// and distribute this software is granted provided this copyright
// notice appears in all copies. This software is provided "as is" without
// express or implied warranty, and with no claim as to its suitability for
// any purpose.
// See http://www.boost.org for most recent version including documentation.
// Classes appear in alphabetical order
// See http://www.boost.org/libs/utility for documentation.
#ifndef BOOST_UTILITY_HPP
#define BOOST_UTILITY_HPP
// certain headers are part of the <utility.hpp> interface
#include <boost/checked_delete.hpp>
#include <boost/utility/base_from_member.hpp>
#include <boost/utility/addressof.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
#include <boost/utility/base_from_member.hpp>
#include <boost/checked_delete.hpp>
#include <boost/next_prior.hpp>
#include <boost/noncopyable.hpp>
#endif // BOOST_UTILITY_HPP

View File

@ -1,31 +0,0 @@
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
// Doug Gregor (gregod@cs.rpi.edu)
// Peter Dimov
//
// Permission to copy, use, sell and distribute this software is granted
// provided this copyright notice appears in all copies.
// Permission to modify the code and to distribute modified code is granted
// provided this copyright notice appears in all copies, and a notice
// that the code was modified is included with the copyright notice.
//
// 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
#ifndef BOOST_UTILITY_ADDRESSOF_HPP
#define BOOST_UTILITY_ADDRESSOF_HPP
namespace boost {
// Do not make addressof() inline. Breaks MSVC 7. (Peter Dimov)
template <typename T> T* addressof(T& v)
{
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
}
#endif // BOOST_UTILITY_ADDRESSOF_HPP

View File

@ -1,59 +0,0 @@
// boost utility/base_from_member.hpp header file --------------------------//
// (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 for most recent version including documentation.
#ifndef BOOST_UTILITY_BASE_FROM_MEMBER_HPP
#define BOOST_UTILITY_BASE_FROM_MEMBER_HPP
#include <boost/utility_fwd.hpp> // required for parameter defaults
namespace boost
{
// Base-from-member class template -----------------------------------------//
// Helper to initialize a base object so a derived class can use this
// object in the initialization of another base class. Used by
// Dietmar Kuehl from ideas by Ron Klatcho to solve the problem of a
// base class needing to be initialized by a member.
// Contributed by Daryle Walker
template < typename MemberType, int UniqueID >
class base_from_member
{
protected:
MemberType member;
explicit base_from_member()
: member()
{}
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
#endif // BOOST_UTILITY_BASE_FROM_MEMBER_HPP

View File

@ -6,7 +6,7 @@
// 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 http://www.boost.org/libs/utility for documentation.
#ifndef BOOST_UTILITY_FWD_HPP
#define BOOST_UTILITY_FWD_HPP

View File

@ -1,34 +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="../../c++boost.gif" WIDTH="276" HEIGHT="86" align="center">Boost
Utility Library</h1>
<p>The Boost Utility Library isn't really a single library at all.&nbsp; 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.&nbsp; Take a look:</p>
<blockquote>
<p><a href="base_from_member.html">base_from_member</a><br>
<a href="call_traits.htm">call_traits.htm</a><br>
<a href="compressed_pair.htm">compressed_pair.htm</a><br>
<a href="operators.htm">operators.htm</a><br>
<a href="tie.html">tie</a><br>
<a href="utility.htm">utility.htm</a></p>
</blockquote>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->07 May, 2002<!--webbot bot="Timestamp" endspan i-checksum="13976" --></p>
<p>&nbsp;</p>
</body>
</html>

View File

@ -1,444 +0,0 @@
<!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

@ -1,62 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
#include <boost/config.hpp>
#include <vector>
#include <iostream>
#include <iterator>
#include <functional>
#include <boost/iterator_adaptors.hpp>
int main(int, char*[])
{
char characters[] = "abcdefg";
const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
char* pointers_to_chars[N]; // at the end.
for (int i = 0; i < N; ++i)
pointers_to_chars[i] = &characters[i];
// Example of using indirect_iterator_generator
boost::indirect_iterator_generator<char**, char>::type
indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
std::cout << std::endl;
// Example of using indirect_iterator_pair_generator
typedef boost::indirect_iterator_pair_generator<char**, char> 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()
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
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;
}

View File

@ -1,151 +0,0 @@
// (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) || BOOST_MSVC > 1200 || !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_STD_ITERATOR_TRAITS
, 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_STD_ITERATOR_TRAITS
, 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_STD_ITERATOR_TRAITS
, 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_STD_ITERATOR_TRAITS
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_STD_ITERATOR_TRAITS
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

@ -1,27 +0,0 @@
// 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

@ -1,28 +0,0 @@
// 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;
}

View File

@ -1,61 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// 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

@ -1,46 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
#include <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;
}

View File

@ -1,449 +0,0 @@
// 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<storage::iterator, 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) && BOOST_MSVC <= 1300
// 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*
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
, dummyT
#endif
>::type reverse_iterator;
reverse_iterator i(reversed + N);
boost::random_access_iterator_test(i, N, array);
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
#endif
typedef boost::reverse_iterator_generator<const dummyT*
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
, 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;
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
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_MSVC > 1200)
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*
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
, 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) || BOOST_MSVC > 1200 || 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) || BOOST_MSVC > 1200 // 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
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
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,995 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//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>Boost Iterator Adaptor Library</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>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>Base</tt> is an
iterator.
<table border="1" summary="iterator_adaptor template parameters">
<tr>
<th>Parameter
<th>Description
<th>Requirements
<tr>
<td><tt>Base</tt>
<td>The data type on which the resulting iterator is based. Do
not be misled by the name &quot;Base&quot;: this is not a base
class.
<td>
<a href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>,
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default&nbsp;Constructible</a>
<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.
<td>See table <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;Base&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;Base&gt;::reference</tt> is used. <a href="#7">[7]</a>
<td><a
href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterators</a>,
<a
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterators</a>,
and <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterators</a>
require that Reference is a true reference type (e.g. not a proxy).
<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 not supplied, <tt>std::iterator_traits&lt;Base&gt;::pointer</tt>. <a
href="#7">[7]</a> Otherwise, if <code>iterator_category</code> is
<code>input_iterator</code>, then a class yielding
<tt>Value*</tt> when <code>operator-&gt;()</code> is applied.
Otherwise, <tt>Value*</tt>.
<td><code>value_type*</code> or a
class which yields <code>value_type*</code> when
<code>operator-&gt;()</code> is applied.
<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;Base&gt;::iterator_category</tt>
<td>One of
<code>std::input_iterator_tag</code>,
<code>std::output_iterator_tag</code>,
<code>std::forward_iterator_tag</code>,
<code>std::bidirectional_iterator_tag</code>, or
<code>std::random_access_iterator_tag</code>.
<tr>
<td><tt>Distance</tt>
<td>The <tt>difference_type</tt> for the resulting iterator.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;Base&gt;::difference_type</tt>
<td>A signed integral type
<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>++x</tt>, <tt>x++</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>
<tr>
<td><tt>const Policies& policies() const;</tt>
<br><br>
Return a const reference to the policies object.
<tr> <td><tt>Policies& policies();</tt>
<br><br>
Return a reference to the policies object.
</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/tech/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>

Binary file not shown.

Binary file not shown.

View File

@ -1,215 +0,0 @@
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 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 :(
typedef typename boost::detail::iterator_traits<Iterator>::pointer test_pt;
typedef typename boost::detail::iterator_traits<Iterator>::reference test_rt;
BOOST_STATIC_ASSERT((
::boost::is_same<
test_pt,
pointer
>::value));
BOOST_STATIC_ASSERT((
::boost::is_same<
test_rt,
reference
>::value));
};
template <class Iterator,
class value_type, class difference_type, class pointer, class reference, class category>
struct portable_tests
{
typedef typename boost::detail::iterator_traits<Iterator>::difference_type test_dt;
typedef typename boost::detail::iterator_traits<Iterator>::iterator_category test_cat;
BOOST_STATIC_ASSERT((
::boost::is_same<
test_dt,
difference_type
>::value));
BOOST_STATIC_ASSERT((
::boost::is_same<
test_cat,
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>
{
typedef typename boost::detail::iterator_traits<Iterator>::value_type test_vt;
BOOST_STATIC_ASSERT((
::boost::is_same<
test_vt,
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,342 +0,0 @@
// Demonstrate and test boost/operators.hpp on std::iterators --------------//
// (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
// 29 May 01 Factored implementation, added comparison tests, use Test Tools
// library (Daryle Walker)
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp> // for main
#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT
#include <boost/cstdlib.hpp> // for boost::exit_success
#include <boost/operators.hpp> // for boost::random_access_iterator_helper
#include <cstddef> // for std::ptrdiff_t, std::size_t
#include <cstring> // for std::strcmp
#include <iostream> // for std::cout (std::endl, ends, and flush indirectly)
#include <string> // for std::string
#include <strstream> // for std::ostrstream
# ifdef BOOST_NO_STDC_NAMESPACE
namespace std { using ::strcmp; }
# endif
// Iterator test class
template <class T, class R, class P>
struct test_iter
: public boost::random_access_iterator_helper<
test_iter<T,R,P>, T, std::ptrdiff_t, P, R>
{
typedef test_iter self;
typedef R Reference;
typedef std::ptrdiff_t Distance;
public:
explicit test_iter(T* i =0) : _i(i) { }
test_iter(const self& x) : _i(x._i) { }
self& operator=(const self& x) { _i = x._i; return *this; }
Reference operator*() const { return *_i; }
self& operator++() { ++_i; return *this; }
self& operator--() { --_i; return *this; }
self& operator+=(Distance n) { _i += n; return *this; }
self& operator-=(Distance n) { _i -= n; return *this; }
bool operator==(const self& x) const { return _i == x._i; }
bool operator<(const self& x) const { return _i < x._i; }
friend Distance operator-(const self& x, const self& y) {
return x._i - y._i;
}
protected:
P _i;
};
// Iterator operator testing classes
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*>
class test_opr
: public test_opr_base
{
typedef test_opr<T, R, P> self_type;
public:
// Types
typedef T value_type;
typedef R reference;
typedef P pointer;
typedef test_iter<T, R, P> iter_type;
// Test controller
static void master_test( char const name[] );
private:
// Test data
static iter_type const fruit_begin;
static iter_type const fruit_end;
// Test parts
static void post_increment_test();
static void post_decrement_test();
static void indirect_referral_test();
static void offset_addition_test();
static void reverse_offset_addition_test();
static void offset_subtraction_test();
static void comparison_test();
static void indexing_test();
}; // test_opr
// Class-static data definitions
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 );
template <typename T, typename R, typename P>
typename test_opr<T, R, P>::iter_type const
test_opr<T, R, P>::fruit_end = test_iter<T,R,P>( fruit + fruit_length );
// Main testing function
int
test_main( int , char * [] )
{
using std::string;
typedef test_opr<string, string &, string *> test1_type;
typedef test_opr<string, string const &, string const *> test2_type;
test1_type::master_test( "non-const string" );
test2_type::master_test( "const string" );
return boost::exit_success;
}
// Tests for all of the operators added by random_access_iterator_helper
template <typename T, typename R, typename P>
void
test_opr<T, R, P>::master_test
(
char const name[]
)
{
std::cout << "Doing test run for " << name << '.' << std::endl;
post_increment_test();
post_decrement_test();
indirect_referral_test();
offset_addition_test();
reverse_offset_addition_test();
offset_subtraction_test();
comparison_test();
indexing_test();
}
// Test post-increment
template <typename T, typename R, typename P>
void
test_opr<T, R, P>::post_increment_test
(
)
{
std::cout << "\tDoing post-increment test." << std::endl;
std::ostrstream oss( scratch, scratch_length );
for ( iter_type i = fruit_begin ; i != fruit_end ; )
{
oss << *i++ << ' ';
}
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ")
== 0 );
}
// Test post-decrement
template <typename T, typename R, typename P>
void
test_opr<T, R, P>::post_decrement_test
(
)
{
std::cout << "\tDoing post-decrement test." << std::endl;
std::ostrstream oss( scratch, scratch_length );
for ( iter_type i = fruit_end ; i != fruit_begin ; )
{
i--;
oss << *i << ' ';
}
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "plum grape peach pear orange apple ")
== 0 );
}
// Test indirect structure referral
template <typename T, typename R, typename P>
void
test_opr<T, R, P>::indirect_referral_test
(
)
{
std::cout << "\tDoing indirect reference test." << std::endl;
std::ostrstream oss( scratch, scratch_length );
for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
{
oss << i->size() << ' ';
}
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "5 6 4 5 5 4 ") == 0 );
}
// Test offset addition
template <typename T, typename R, typename P>
void
test_opr<T, R, P>::offset_addition_test
(
)
{
std::cout << "\tDoing offset addition test." << std::endl;
std::ptrdiff_t const two = 2;
std::ostrstream oss( scratch, scratch_length );
for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two )
{
oss << *i << ' ';
}
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 );
}
// Test offset addition, in reverse order
template <typename T, typename R, typename P>
void
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::ostrstream oss( scratch, scratch_length );
for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i )
{
oss << *i << ' ';
}
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 );
}
// Test offset subtraction
template <typename T, typename R, typename P>
void
test_opr<T, R, P>::offset_subtraction_test
(
)
{
std::cout << "\tDoing offset subtraction test." << std::endl;
std::ptrdiff_t const two = 2;
std::ostrstream oss( scratch, scratch_length );
for ( iter_type i = fruit_end ; fruit_begin < i ; )
{
i = i - two;
if ( (fruit_begin < i) || (fruit_begin == i) )
{
oss << *i << ' ';
}
}
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "grape pear apple ") == 0 );
}
// Test comparisons
template <typename T, typename R, typename P>
void
test_opr<T, R, P>::comparison_test
(
)
{
using std::cout;
using std::ptrdiff_t;
cout << "\tDoing comparison tests.\n\t\tPass:";
for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
{
ptrdiff_t const i_offset = i - fruit_begin;
cout << ' ' << *i << std::flush;
for ( iter_type j = fruit_begin ; j != fruit_end ; ++j )
{
ptrdiff_t const j_offset = j - fruit_begin;
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;
}
// Test indexing
template <typename T, typename R, typename P>
void
test_opr<T, R, P>::indexing_test
(
)
{
std::cout << "\tDoing indexing test." << std::endl;
std::ostrstream oss( scratch, scratch_length );
for ( std::size_t k = 0u ; k < fruit_length ; ++k )
{
oss << fruit_begin[ k ] << ' ';
}
oss << std::ends;
BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ")
== 0 );
}

View File

@ -1,38 +0,0 @@
// boost class noncopyable test program ------------------------------------//
// (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.
// Revision History
// 9 Jun 99 Add unnamed namespace
// 2 Jun 99 Initial Version
#include <boost/utility.hpp>
#include <iostream>
// This program demonstrates compiler errors resulting from trying to copy
// construct or copy assign a class object derived from class noncopyable.
namespace
{
class DontTreadOnMe : private boost::noncopyable
{
public:
DontTreadOnMe() { std::cout << "defanged!" << std::endl; }
}; // DontTreadOnMe
} // unnamed namespace
int main()
{
DontTreadOnMe object1;
DontTreadOnMe object2(object1);
object1 = object2;
return 0;
} // main

View File

@ -1,387 +0,0 @@
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 1 Apr 2001 Fixes for ICL; use BOOST_STATIC_CONSTANT
// 11 Feb 2001 Fixes for Borland (David Abrahams)
// 23 Jan 2001 Added test for wchar_t (David Abrahams)
// 23 Jan 2001 Now statically selecting a test for signed numbers to avoid
// warnings with fancy compilers. Added commentary and
// additional dumping of traits data for tested types (David
// Abrahams).
// 21 Jan 2001 Initial version (David Abrahams)
#include <boost/detail/numeric_traits.hpp>
#include <cassert>
#include <boost/type_traits.hpp>
#include <boost/static_assert.hpp>
#include <boost/cstdint.hpp>
#include <boost/utility.hpp>
#include <boost/lexical_cast.hpp>
#include <climits>
#include <typeinfo>
#include <iostream>
#include <string>
#ifndef BOOST_NO_LIMITS
# include <limits>
#endif
// =================================================================================
// template class complement_traits<Number> --
//
// statically computes the max and min for 1s and 2s-complement binary
// numbers. This helps on platforms without <limits> support. It also shows
// an example of a recursive template that works with MSVC!
//
template <unsigned size> struct complement; // forward
// The template complement, below, does all the real work, using "poor man's
// partial specialization". We need complement_traits_aux<> so that MSVC doesn't
// complain about undefined min/max as we're trying to recursively define them.
template <class Number, unsigned size>
struct complement_traits_aux
{
BOOST_STATIC_CONSTANT(Number, max = complement<size>::template traits<Number>::max);
BOOST_STATIC_CONSTANT(Number, min = complement<size>::template traits<Number>::min);
};
template <unsigned size>
struct complement
{
template <class Number>
struct traits
{
private:
// indirection through complement_traits_aux neccessary to keep MSVC happy
typedef complement_traits_aux<Number, size - 1> prev;
public:
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));
};
};
// Template class complement_base<> -- defines values for min and max for
// complement<1>, at the deepest level of recursion. Uses "poor man's partial
// specialization" again.
template <bool is_signed> struct complement_base;
template <> struct complement_base<false>
{
template <class Number>
struct values
{
BOOST_STATIC_CONSTANT(Number, min = 0);
BOOST_STATIC_CONSTANT(Number, max = UCHAR_MAX);
};
};
template <> struct complement_base<true>
{
template <class Number>
struct values
{
BOOST_STATIC_CONSTANT(Number, min = SCHAR_MIN);
BOOST_STATIC_CONSTANT(Number, max = SCHAR_MAX);
};
};
// Base specialization of complement, puts an end to the recursion.
template <>
struct complement<1>
{
template <class Number>
struct traits
{
BOOST_STATIC_CONSTANT(bool, is_signed = boost::detail::is_signed<Number>::value);
BOOST_STATIC_CONSTANT(Number, min =
complement_base<is_signed>::template values<Number>::min);
BOOST_STATIC_CONSTANT(Number, max =
complement_base<is_signed>::template values<Number>::max);
};
};
// Now here's the "pretty" template you're intended to actually use.
// complement_traits<Number>::min, complement_traits<Number>::max are the
// minimum and maximum values of Number if Number is a built-in integer type.
template <class Number>
struct complement_traits
{
BOOST_STATIC_CONSTANT(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max));
BOOST_STATIC_CONSTANT(Number, min = (complement_traits_aux<Number, sizeof(Number)>::min));
};
// =================================================================================
// Support for streaming various numeric types in exactly the format I want. I
// needed this in addition to all the assertions so that I could see exactly
// what was going on.
//
// Numbers go through a 2-stage conversion process (by default, though, no real
// conversion).
//
template <class T> struct stream_as {
typedef T t1;
typedef T t2;
};
// char types first get converted to unsigned char, then to unsigned.
template <> struct stream_as<char> {
typedef unsigned char t1;
typedef unsigned t2;
};
template <> struct stream_as<unsigned char> {
typedef unsigned char t1; typedef unsigned t2;
};
template <> struct stream_as<signed char> {
typedef unsigned char t1; typedef unsigned t2;
};
#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in
// With this library implementation, __int64 and __uint64 get streamed as strings
template <> struct stream_as<boost::uintmax_t> {
typedef std::string t1;
typedef std::string t2;
};
template <> struct stream_as<boost::intmax_t> {
typedef std::string t1;
typedef std::string t2;
};
#endif
// Standard promotion process for streaming
template <class T> struct promote
{
static typename stream_as<T>::t1 from(T x) {
typedef typename stream_as<T>::t1 t1;
return t1(x);
}
};
#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in
// On this platform, stream them as long/unsigned long if they fit.
// Otherwise, write a string.
template <> struct promote<boost::uintmax_t> {
std::string static from(const boost::uintmax_t x) {
if (x > ULONG_MAX)
return std::string("large unsigned value");
else
return boost::lexical_cast<std::string>((unsigned long)x);
}
};
template <> struct promote<boost::intmax_t> {
std::string static from(const boost::intmax_t x) {
if (x > boost::intmax_t(ULONG_MAX))
return std::string("large positive signed value");
else if (x >= 0)
return boost::lexical_cast<std::string>((unsigned long)x);
if (x < boost::intmax_t(LONG_MIN))
return std::string("large negative signed value");
else
return boost::lexical_cast<std::string>((long)x);
}
};
#endif
// This is the function which converts types to the form I want to stream them in.
template <class T>
typename stream_as<T>::t2 stream_number(T x)
{
return promote<T>::from(x);
}
// =================================================================================
//
// Tests for built-in signed and unsigned types
//
// Tag types for selecting tests
struct unsigned_tag {};
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* = 0)
{
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
BOOST_STATIC_ASSERT(!boost::detail::is_signed<Number>::value);
BOOST_STATIC_ASSERT(
(sizeof(Number) < sizeof(boost::intmax_t))
| (boost::is_same<difference_type, boost::intmax_t>::value));
// 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));
const Number max = complement_traits<Number>::max;
const Number min = complement_traits<Number>::min;
const Number test_max = (sizeof(Number) < sizeof(boost::intmax_t))
? max
: max / 2 - 1;
std::cout << std::hex << "(unsigned) min = " << stream_number(min) << ", max = "
<< stream_number(max) << "..." << std::flush;
std::cout << "difference_type = " << typeid(difference_type).name() << "..."
<< std::flush;
difference_type d1 = boost::detail::numeric_distance(Number(0), test_max);
difference_type d2 = boost::detail::numeric_distance(test_max, Number(0));
std::cout << "0->" << stream_number(test_max) << "==" << std::dec << stream_number(d1) << "; "
<< std::hex << stream_number(test_max) << "->0==" << std::dec << stream_number(d2) << "..." << std::flush;
assert(d1 == difference_type(test_max));
assert(d2 == -difference_type(test_max));
}
// Tests for signed numbers. The extra default Number parameter works around an
// MSVC bug.
struct out_of_range_tag {};
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* = 0)
{
BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
const Number max = complement_traits<Number>::max;
const Number min = complement_traits<Number>::min;
difference_type d1 = boost::detail::numeric_distance(min, max);
difference_type d2 = boost::detail::numeric_distance(max, min);
std::cout << stream_number(min) << "->" << stream_number(max) << "==";
std::cout << std::dec << stream_number(d1) << "; ";
std::cout << std::hex << stream_number(max) << "->" << stream_number(min)
<< "==" << std::dec << stream_number(d2) << "..." << std::flush;
assert(d1 == difference_type(max) - difference_type(min));
assert(d2 == difference_type(min) - difference_type(max));
}
// 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* = 0)
{
BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
const Number max = complement_traits<Number>::max;
const Number min = complement_traits<Number>::min;
difference_type min_distance = complement_traits<difference_type>::min;
difference_type max_distance = complement_traits<difference_type>::max;
const Number n1 = Number(min + max_distance);
const Number n2 = Number(max + min_distance);
difference_type d1 = boost::detail::numeric_distance(min, n1);
difference_type d2 = boost::detail::numeric_distance(max, n2);
std::cout << stream_number(min) << "->" << stream_number(n1) << "==";
std::cout << std::dec << stream_number(d1) << "; ";
std::cout << std::hex << stream_number(max) << "->" << stream_number(n2)
<< "==" << std::dec << stream_number(d2) << "..." << std::flush;
assert(d1 == max_distance);
assert(d2 == min_distance);
}
template <class 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);
BOOST_STATIC_ASSERT(
(sizeof(Number) < sizeof(boost::intmax_t))
| (boost::is_same<difference_type, Number>::value));
// 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));
const Number max = complement_traits<Number>::max;
const Number min = complement_traits<Number>::min;
std::cout << std::hex << "min = " << stream_number(min) << ", max = "
<< stream_number(max) << "..." << std::flush;
std::cout << "difference_type = " << typeid(difference_type).name() << "..."
<< std::flush;
typedef typename boost::detail::if_true<
(sizeof(Number) < sizeof(boost::intmax_t))>
::template then<
in_range_tag,
out_of_range_tag
>::type
range_tag;
signed_test<Number>(range_tag());
}
// Test for all numbers. The extra default Number parameter works around an MSVC
// bug.
template <class Number>
void test(Number* = 0)
{
std::cout << "testing " << typeid(Number).name() << ":\n"
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
<< "is_signed: " << (std::numeric_limits<Number>::is_signed ? "true\n" : "false\n")
<< "is_bounded: " << (std::numeric_limits<Number>::is_bounded ? "true\n" : "false\n")
<< "digits: " << std::numeric_limits<Number>::digits << "\n"
#endif
<< "..." << std::flush;
// factoring out difference_type for the assert below confused Borland :(
typedef boost::detail::is_signed<
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
typename
#endif
boost::detail::numeric_traits<Number>::difference_type
> is_signed;
BOOST_STATIC_ASSERT(is_signed::value);
typedef typename boost::detail::if_true<
boost::detail::is_signed<Number>::value
>::template then<signed_tag, unsigned_tag>::type signedness;
test_aux<Number>(signedness());
std::cout << "passed" << std::endl;
}
int main()
{
test<char>();
test<unsigned char>();
test<signed char>();
test<wchar_t>();
test<short>();
test<unsigned short>();
test<int>();
test<unsigned int>();
test<long>();
test<unsigned long>();
#if defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_INTEGRAL_INT64_T)
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.
// test<boost::uintmax_t>();
// test<boost::intmax_t>();
#endif
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,890 +0,0 @@
// Demonstrate and test boost/operators.hpp -------------------------------//
// (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 for most recent version including documentation.
// Revision History
// 01 Oct 01 Added tests for "left" operators
// and new grouped operators. (Helmut Zeisel)
// 20 May 01 Output progress messages. Added tests for new operator
// templates. Updated random number generator. Changed tests to
// use Boost Test Tools library. (Daryle Walker)
// 04 Jun 00 Added regression test for a bug I found (David Abrahams)
// 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy)
// ?? ??? 00 Major update to randomly test all one- and two- argument forms by
// wrapping integral types and comparing the results of operations
// to the results for the raw types (David Abrahams)
// 12 Dec 99 Minor update, output confirmation message.
// 15 Nov 99 Initial version
#define BOOST_INCLUDE_MAIN
#include <boost/config.hpp> // for BOOST_MSVC
#include <boost/cstdlib.hpp> // for boost::exit_success
#include <boost/operators.hpp> // for the tested items
#include <boost/random/linear_congruential.hpp> // for boost::minstd_rand
#include <boost/test/test_tools.hpp> // for main
#include <iostream> // for std::cout (std::endl indirectly)
namespace
{
// avoiding a template version of true_value so as to not confuse VC++
int true_value(int x) { return x; }
long true_value(long x) { return x; }
signed char true_value(signed char x) { return x; }
short true_value(short x) { return x; }
unsigned int true_value(unsigned int x) { return x; }
unsigned long true_value(unsigned long x) { return x; }
unsigned char true_value(unsigned char x) { return x; }
unsigned short true_value(unsigned short x) { return x; }
// The use of operators<> here tended to obscure
// interactions with certain compiler bugs
template <class T>
class Wrapped1
: boost::operators<Wrapped1<T> >
, boost::shiftable<Wrapped1<T> >
{
public:
explicit Wrapped1( T v = T() ) : _value(v) {}
T value() const { return _value; }
bool operator<(const Wrapped1& x) const { return _value < x._value; }
bool operator==(const Wrapped1& x) const { return _value == x._value; }
Wrapped1& operator+=(const Wrapped1& x)
{ _value += x._value; return *this; }
Wrapped1& operator-=(const Wrapped1& x)
{ _value -= x._value; return *this; }
Wrapped1& operator*=(const Wrapped1& x)
{ _value *= x._value; return *this; }
Wrapped1& operator/=(const Wrapped1& x)
{ _value /= x._value; return *this; }
Wrapped1& operator%=(const Wrapped1& x)
{ _value %= x._value; return *this; }
Wrapped1& operator|=(const Wrapped1& x)
{ _value |= x._value; return *this; }
Wrapped1& operator&=(const Wrapped1& x)
{ _value &= x._value; return *this; }
Wrapped1& operator^=(const Wrapped1& x)
{ _value ^= x._value; return *this; }
Wrapped1& operator<<=(const Wrapped1& x)
{ _value <<= x._value; return *this; }
Wrapped1& operator>>=(const Wrapped1& x)
{ _value >>= x._value; return *this; }
Wrapped1& operator++() { ++_value; return *this; }
Wrapped1& operator--() { --_value; return *this; }
private:
T _value;
};
template <class T>
T true_value(Wrapped1<T> x) { return x.value(); }
template <class T, class U>
class Wrapped2
: boost::operators<Wrapped2<T, U> >
, boost::operators2<Wrapped2<T, U>, U>
, boost::shiftable1<Wrapped2<T, U>
, boost::shiftable2<Wrapped2<T, U>, U > >
{
public:
explicit Wrapped2( T v = T() ) : _value(v) {}
T value() const { return _value; }
bool operator<(const Wrapped2& x) const { return _value < x._value; }
bool operator==(const Wrapped2& x) const { return _value == x._value; }
Wrapped2& operator+=(const Wrapped2& x)
{ _value += x._value; return *this; }
Wrapped2& operator-=(const Wrapped2& x)
{ _value -= x._value; return *this; }
Wrapped2& operator*=(const Wrapped2& x)
{ _value *= x._value; return *this; }
Wrapped2& operator/=(const Wrapped2& x)
{ _value /= x._value; return *this; }
Wrapped2& operator%=(const Wrapped2& x)
{ _value %= x._value; return *this; }
Wrapped2& operator|=(const Wrapped2& x)
{ _value |= x._value; return *this; }
Wrapped2& operator&=(const Wrapped2& x)
{ _value &= x._value; return *this; }
Wrapped2& operator^=(const Wrapped2& x)
{ _value ^= x._value; return *this; }
Wrapped2& operator<<=(const Wrapped2& x)
{ _value <<= x._value; return *this; }
Wrapped2& operator>>=(const Wrapped2& x)
{ _value >>= x._value; return *this; }
Wrapped2& operator++() { ++_value; return *this; }
Wrapped2& operator--() { --_value; return *this; }
bool operator<(U u) const { return _value < u; }
bool operator>(U u) const { return _value > u; }
bool operator==(U u) const { return _value == u; }
Wrapped2& operator+=(U u) { _value += u; return *this; }
Wrapped2& operator-=(U u) { _value -= u; return *this; }
Wrapped2& operator*=(U u) { _value *= u; return *this; }
Wrapped2& operator/=(U u) { _value /= u; return *this; }
Wrapped2& operator%=(U u) { _value %= u; return *this; }
Wrapped2& operator|=(U u) { _value |= u; return *this; }
Wrapped2& operator&=(U u) { _value &= u; return *this; }
Wrapped2& operator^=(U u) { _value ^= u; return *this; }
Wrapped2& operator<<=(U u) { _value <<= u; return *this; }
Wrapped2& operator>>=(U u) { _value >>= u; return *this; }
private:
T _value;
};
template <class T, class U>
T true_value(Wrapped2<T,U> x) { return x.value(); }
template <class T>
class Wrapped3
: boost::equivalent<Wrapped3<T> >
, boost::partially_ordered<Wrapped3<T> >
, boost::equality_comparable<Wrapped3<T> >
{
public:
explicit Wrapped3( T v = T() ) : _value(v) {}
T value() const { return _value; }
bool operator<(const Wrapped3& x) const { return _value < x._value; }
private:
T _value;
};
template <class T>
T true_value(Wrapped3<T> x) { return x.value(); }
template <class T, class U>
class Wrapped4
: boost::equality_comparable1<Wrapped4<T, U>
, boost::equivalent1<Wrapped4<T, U>
, boost::partially_ordered1<Wrapped4<T, U> > > >
, boost::partially_ordered2<Wrapped4<T, U>, U
, boost::equivalent2<Wrapped4<T, U>, U
, boost::equality_comparable2<Wrapped4<T, U>, U> > >
{
public:
explicit Wrapped4( T v = T() ) : _value(v) {}
T value() const { return _value; }
bool operator<(const Wrapped4& x) const { return _value < x._value; }
bool operator<(U u) const { return _value < u; }
bool operator>(U u) const { return _value > u; }
private:
T _value;
};
template <class T, class U>
T true_value(Wrapped4<T,U> x) { return x.value(); }
// U must be convertible to T
template <class T, class U>
class Wrapped5
: boost::ordered_field_operators2<Wrapped5<T, U>, U>
, boost::ordered_field_operators1<Wrapped5<T, U> >
{
public:
explicit Wrapped5( T v = T() ) : _value(v) {}
// Conversion from U to Wrapped5<T,U>
Wrapped5(U u) : _value(u) {}
T value() const { return _value; }
bool operator<(const Wrapped5& x) const { return _value < x._value; }
bool operator<(U u) const { return _value < u; }
bool operator>(U u) const { return _value > u; }
bool operator==(const Wrapped5& u) const { return _value == u._value; }
bool operator==(U u) const { return _value == u; }
Wrapped5& operator/=(const Wrapped5& u) { _value /= u._value; return *this;}
Wrapped5& operator/=(U u) { _value /= u; return *this;}
Wrapped5& operator*=(const Wrapped5& u) { _value *= u._value; return *this;}
Wrapped5& operator*=(U u) { _value *= u; return *this;}
Wrapped5& operator-=(const Wrapped5& u) { _value -= u._value; return *this;}
Wrapped5& operator-=(U u) { _value -= u; return *this;}
Wrapped5& operator+=(const Wrapped5& u) { _value += u._value; return *this;}
Wrapped5& operator+=(U u) { _value += u; return *this;}
private:
T _value;
};
template <class T, class U>
T true_value(Wrapped5<T,U> x) { return x.value(); }
// U must be convertible to T
template <class T, class U>
class Wrapped6
: boost::ordered_euclidian_ring_operators2<Wrapped6<T, U>, U>
, boost::ordered_euclidian_ring_operators1<Wrapped6<T, U> >
{
public:
explicit Wrapped6( T v = T() ) : _value(v) {}
// Conversion from U to Wrapped6<T,U>
Wrapped6(U u) : _value(u) {}
T value() const { return _value; }
bool operator<(const Wrapped6& x) const { return _value < x._value; }
bool operator<(U u) const { return _value < u; }
bool operator>(U u) const { return _value > u; }
bool operator==(const Wrapped6& u) const { return _value == u._value; }
bool operator==(U u) const { return _value == u; }
Wrapped6& operator%=(const Wrapped6& u) { _value %= u._value; return *this;}
Wrapped6& operator%=(U u) { _value %= u; return *this;}
Wrapped6& operator/=(const Wrapped6& u) { _value /= u._value; return *this;}
Wrapped6& operator/=(U u) { _value /= u; return *this;}
Wrapped6& operator*=(const Wrapped6& u) { _value *= u._value; return *this;}
Wrapped6& operator*=(U u) { _value *= u; return *this;}
Wrapped6& operator-=(const Wrapped6& u) { _value -= u._value; return *this;}
Wrapped6& operator-=(U u) { _value -= u; return *this;}
Wrapped6& operator+=(const Wrapped6& u) { _value += u._value; return *this;}
Wrapped6& operator+=(U u) { _value += u; return *this;}
private:
T _value;
};
template <class T, class U>
T true_value(Wrapped6<T,U> x) { return x.value(); }
// MyInt uses only the single template-argument form of all_operators<>
typedef Wrapped1<int> MyInt;
typedef Wrapped2<long, long> MyLong;
typedef Wrapped3<signed char> MyChar;
typedef Wrapped4<short, short> MyShort;
typedef Wrapped5<double, int> MyDoubleInt;
typedef Wrapped6<long, int> MyLongInt;
template <class X1, class Y1, class X2, class Y2>
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
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_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>
void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
test_less_than_comparable_aux( x1, y1, x2, y2 );
test_less_than_comparable_aux( y1, x1, y2, x2 );
}
template <class X1, class Y1, class X2, class Y2>
void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
BOOST_TEST( (x1 == y1) == (x2 == y2) );
BOOST_TEST( (x1 != y1) == (x2 != y2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
test_equality_comparable_aux( x1, y1, x2, y2 );
test_equality_comparable_aux( y1, x1, y2, x2 );
}
template <class X1, class Y1, class X2, class Y2>
void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
BOOST_TEST( (x1 * y1).value() == (x2 * y2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
test_multipliable_aux( x1, y1, x2, y2 );
test_multipliable_aux( y1, x1, y2, x2 );
}
template <class X1, class Y1, class X2, class Y2>
void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
BOOST_TEST( (x1 + y1).value() == (x2 + y2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
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 );
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 );
BOOST_TEST( (y1 - x1).value() == (y2 - x2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
if ( y2 != 0 )
BOOST_TEST( (x1 / y1).value() == (x2 / y2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_dividable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
if ( x2 != 0 )
BOOST_TEST( (y1 / x1).value() == (y2 / x2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
if ( y2 != 0 )
BOOST_TEST( (x1 % y1).value() == (x2 % y2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_modable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
if ( x2 != 0 )
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)
{
BOOST_TEST( (x1 ^ y1).value() == (x2 ^ y2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
test_xorable_aux( x1, y1, x2, y2 );
test_xorable_aux( y1, x1, y2, x2 );
}
template <class X1, class Y1, class X2, class Y2>
void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
BOOST_TEST( (x1 & y1).value() == (x2 & y2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
test_andable_aux( x1, y1, x2, y2 );
test_andable_aux( y1, x1, y2, x2 );
}
template <class X1, class Y1, class X2, class Y2>
void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
BOOST_TEST( (x1 | y1).value() == (x2 | y2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
test_orable_aux( x1, y1, x2, y2 );
test_orable_aux( y1, x1, y2, x2 );
}
template <class X1, class Y1, class X2, class Y2>
void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check( x1, y1, x2, y2 );
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 );
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_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_TEST( (x1--).value() == x2-- );
BOOST_TEST( x1.value() == x2 );
}
template <class X1, class Y1, class X2, class Y2>
void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
test_less_than_comparable( x1, y1, x2, y2 );
test_equality_comparable( x1, y1, x2, y2 );
test_multipliable( x1, y1, x2, y2 );
test_addable( x1, y1, x2, y2 );
test_subtractable( x1, y1, x2, y2 );
test_dividable( x1, y1, x2, y2 );
test_modable( x1, y1, x2, y2 );
test_xorable( x1, y1, x2, y2 );
test_andable( x1, y1, x2, y2 );
test_orable( x1, y1, x2, y2 );
test_left_shiftable( x1, y1, x2, y2 );
test_right_shiftable( x1, y1, x2, y2 );
test_incrementable( x1, x2 );
test_decrementable( x1, x2 );
}
template <class X1, class Y1, class X2, class Y2>
void test_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
test_subtractable_left( x1, y1, x2, y2 );
test_dividable_left( x1, y1, x2, y2 );
test_modable_left( x1, y1, x2, y2 );
}
template <class Big, class Small>
struct tester
{
void operator()(boost::minstd_rand& randomizer) const
{
Big b1 = Big( randomizer() );
Big b2 = Big( randomizer() );
Small s = Small( randomizer() );
test_all( Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2 );
test_all( Wrapped2<Big, Small>(b1), s, b1, s );
}
};
template <class Big, class Small>
struct tester_left
{
void operator()(boost::minstd_rand& randomizer) const
{
Big b1 = Big( randomizer() );
Small s = Small( randomizer() );
test_left( Wrapped6<Big, Small>(b1), s, b1, s );
}
};
// added as a regression test. We had a bug which this uncovered.
struct Point
: boost::addable<Point
, boost::subtractable<Point> >
{
Point( int h, int v ) : h(h), v(v) {}
Point() :h(0), v(0) {}
const Point& operator+=( const Point& rhs )
{ h += rhs.h; v += rhs.v; return *this; }
const Point& operator-=( const Point& rhs )
{ h -= rhs.h; v -= rhs.v; return *this; }
int h;
int v;
};
} // unnamed namespace
// workaround for MSVC bug; for some reasons the compiler doesn't instantiate
// inherited operator templates at the moment it must, so the following
// explicit instantiations force it to do that.
#if defined(BOOST_MSVC) && (_MSC_VER <= 1200)
template Wrapped1<int>;
template Wrapped1<long>;
template Wrapped1<unsigned int>;
template Wrapped1<unsigned long>;
template Wrapped2<int, int>;
template Wrapped2<int, signed char>;
template Wrapped2<long, signed char>;
template Wrapped2<long, int>;
template Wrapped2<long, long>;
template Wrapped2<unsigned int, unsigned int>;
template Wrapped2<unsigned int, unsigned char>;
template Wrapped2<unsigned long, unsigned int>;
template Wrapped2<unsigned long, unsigned char>;
template Wrapped2<unsigned long, unsigned long>;
template Wrapped6<long, int>;
template Wrapped6<long, signed char>;
template Wrapped6<int, signed char>;
template Wrapped6<unsigned long, unsigned int>;
template Wrapped6<unsigned long, unsigned char>;
template Wrapped6<unsigned int, unsigned char>;
#endif
#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) )
int
test_main( int , char * [] )
{
using std::cout;
using std::endl;
// Regression test.
Point x;
x = x + Point(3, 4);
x = x - Point(3, 4);
cout << "Created point, and operated on it." << endl;
for (int n = 0; n < 10000; ++n)
{
boost::minstd_rand r;
tester<long, int>()(r);
tester<long, signed char>()(r);
tester<long, long>()(r);
tester<int, int>()(r);
tester<int, signed char>()(r);
tester<unsigned long, unsigned int>()(r);
tester<unsigned long, unsigned char>()(r);
tester<unsigned long, unsigned long>()(r);
tester<unsigned int, unsigned int>()(r);
tester<unsigned int, unsigned char>()(r);
tester_left<long, int>()(r);
tester_left<long, signed char>()(r);
tester_left<int, signed char>()(r);
tester_left<unsigned long, unsigned int>()(r);
tester_left<unsigned long, unsigned char>()(r);
tester_left<unsigned int, unsigned char>()(r);
}
cout << "Did random tester loop." << endl;
MyInt i1(1);
MyInt i2(2);
MyInt i;
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_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) );
PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) );
PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) );
PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) );
PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) );
PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) );
PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) );
PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) );
PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) );
PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) );
PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) );
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_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_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_TEST( (j1 + 2) == 3 );
BOOST_TEST( (1 + j2) == 3 );
PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) );
BOOST_TEST( (j + 2) == 5 );
BOOST_TEST( (3 + j2) == 5 );
PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) );
BOOST_TEST( (j - 1) == 4 );
PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) );
BOOST_TEST( (j * 2) == 8 );
BOOST_TEST( (4 * j2) == 8 );
PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) );
BOOST_TEST( (j / 2) == 4 );
PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) );
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_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_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_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_TEST( (j1 << 2) == 4 );
BOOST_TEST( (j2 << 1) == 4 );
PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) );
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";
MyChar k1(1);
MyChar k2(2);
MyChar k;
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_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";
MyShort l1(1);
MyShort l2(2);
MyShort l;
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_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";
MyDoubleInt di1(1);
MyDoubleInt di2(2.);
MyDoubleInt half(0.5);
MyDoubleInt di;
MyDoubleInt tmp;
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_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_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_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_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) );
cout << "Performed tests on MyDoubleInt objects.\n";
MyLongInt li1(1);
MyLongInt li2(2);
MyLongInt li;
MyLongInt tmp2;
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_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_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_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_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_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) );
cout << "Performed tests on MyLongInt objects.\n";
return boost::exit_success;
}

View File

@ -1,177 +0,0 @@
<!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>

View File

@ -1,391 +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>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

@ -1,96 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
#include <boost/config.hpp>
#include <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,115 +0,0 @@
// 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/same_traits.hpp>
#include <boost/static_assert.hpp>
namespace {
template< typename T, typename U >
void ref_test(boost::reference_wrapper<U>)
{
typedef typename boost::reference_wrapper<U>::type type;
BOOST_STATIC_ASSERT((boost::is_same<U,type>::value));
BOOST_STATIC_ASSERT((boost::is_same<T,type>::value));
}
template< typename T >
void assignable_test(T x)
{
x = x;
}
template< bool R, typename T >
void is_reference_wrapper_test(T)
{
BOOST_STATIC_ASSERT(boost::is_reference_wrapper<T>::value == R);
}
template< typename R, typename Ref >
void cxx_reference_test(Ref)
{
BOOST_STATIC_ASSERT((boost::is_same<R,Ref>::value));
}
template< typename R, typename Ref >
void unwrap_reference_test(Ref)
{
typedef typename boost::unwrap_reference<Ref>::type type;
BOOST_STATIC_ASSERT((boost::is_same<R,type>::value));
}
} // namespace
int main()
{
int i = 0;
int& ri = i;
int const ci = 0;
int const& rci = ci;
// 'ref/cref' functions test
ref_test<int>(boost::ref(i));
ref_test<int>(boost::ref(ri));
ref_test<int const>(boost::ref(ci));
ref_test<int const>(boost::ref(rci));
ref_test<int const>(boost::cref(i));
ref_test<int const>(boost::cref(ri));
ref_test<int const>(boost::cref(ci));
ref_test<int const>(boost::cref(rci));
// test 'assignable' requirement
assignable_test(boost::ref(i));
assignable_test(boost::ref(ri));
assignable_test(boost::cref(i));
assignable_test(boost::cref(ci));
assignable_test(boost::cref(rci));
// 'is_reference_wrapper' test
is_reference_wrapper_test<true>(boost::ref(i));
is_reference_wrapper_test<true>(boost::ref(ri));
is_reference_wrapper_test<true>(boost::cref(i));
is_reference_wrapper_test<true>(boost::cref(ci));
is_reference_wrapper_test<true>(boost::cref(rci));
is_reference_wrapper_test<false>(i);
is_reference_wrapper_test<false, int&>(ri);
is_reference_wrapper_test<false>(ci);
is_reference_wrapper_test<false, int const&>(rci);
// ordinary references/function template arguments deduction test
cxx_reference_test<int>(i);
cxx_reference_test<int>(ri);
cxx_reference_test<int>(ci);
cxx_reference_test<int>(rci);
cxx_reference_test<int&, int&>(i);
cxx_reference_test<int&, int&>(ri);
cxx_reference_test<int const&, int const&>(i);
cxx_reference_test<int const&, int const&>(ri);
cxx_reference_test<int const&, int const&>(ci);
cxx_reference_test<int const&, int const&>(rci);
// 'unwrap_reference' test
unwrap_reference_test<int>(boost::ref(i));
unwrap_reference_test<int>(boost::ref(ri));
unwrap_reference_test<int const>(boost::cref(i));
unwrap_reference_test<int const>(boost::cref(ci));
unwrap_reference_test<int const>(boost::cref(rci));
unwrap_reference_test<int>(i);
unwrap_reference_test<int>(ri);
unwrap_reference_test<int>(ci);
unwrap_reference_test<int>(rci);
unwrap_reference_test<int&, int&>(i);
unwrap_reference_test<int&, int&>(ri);
unwrap_reference_test<int const&, int const&>(i);
unwrap_reference_test<int const&, int const&>(ri);
unwrap_reference_test<int const&, int const&>(ci);
unwrap_reference_test<int const&, int const&>(rci);
return 0;
}

View File

@ -1,74 +0,0 @@
// run-time test for "boost/ref.hpp" header content
// see 'ref_ct_test.cpp' for compile-time part
#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
#include <boost/ref.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
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
namespace {
using namespace boost;
template <class T>
struct ref_wrapper
{
// Used to verify implicit conversion
static T* get_pointer(T& x)
{
return &x;
}
static T const* get_const_pointer(T const& x)
{
return &x;
}
template <class Arg>
static T* passthru(Arg x)
{
return get_pointer(x);
}
template <class Arg>
static T const* cref_passthru(Arg x)
{
return get_const_pointer(x);
}
static void test(T x)
{
BOOST_TEST(passthru(ref(x)) == &x);
BOOST_TEST(&ref(x).get() == &x);
BOOST_TEST(cref_passthru(cref(x)) == &x);
BOOST_TEST(&cref(x).get() == &x);
}
};
} // namespace unnamed
int test_main(int, char * [])
{
ref_wrapper<int>::test(1);
ref_wrapper<int const>::test(1);
return 0;
}

View File

@ -1,331 +0,0 @@
<!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

@ -1,51 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
#include <boost/config.hpp>
#include <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_STD_ITERATOR_TRAITS
// 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;
}

143
tie.html
View File

@ -1,143 +0,0 @@
<HTML>
<!--
-- Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine 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. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Boost Tie</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<H1><A NAME="sec:tie"></A>
<TT>tie</TT>
</H1>
<h3>
[This version of tie has been removed from the utility.hpp
header.&nbsp; There is a new, more general version of <a
href="../tuple/doc/tuple_users_guide.html#tiers">tie</a> in the Boost
Tuples Library. The more general version handles an (almost) arbitrary
number of arguments, instead of just two. The version in utility.hpp
had to be removed to avoid name clashes.]</h3>
<PRE>
template &lt;class A, class B&gt;
tied&lt;A,B&gt; tie(A&amp; a, B&amp; b);
</PRE>
<P>
This is a utility function that makes it more convenient to work with
a function which returns a std::pair&lt;&gt;. The effect of the <TT>tie()</TT>
function is to allow the assignment of the two values of the pair to
two separate variables. The idea for this comes from Jaakko
J&#228;rvi's Binders&nbsp;[<A
HREF="../graph/doc/bibliography.html#jaakko_tuple_assign">1</A>].
<P>
<H3>Where Defined</H3>
<P>
<a href="../../boost/utility.hpp"><TT>boost/utility.hpp</TT></a>
<P>
<H3>Example</H3>
<P>
An example of using the <TT>tie()</TT> function with the
<TT>vertices()</TT> function, which returns a pair of
type <TT>std::pair&lt;vertex_iterator,vertex_iterator&gt;</TT>. The
pair of iterators is assigned to the iterator variables <TT>i</TT> and
<TT>end</TT>.
<P>
<PRE>
graph_traits&lt; adjacency_list&lt;&gt; &gt;::vertex_iterator i, end;
for(tie(i,end) = vertices(G); i != end; ++i)
// ...
</PRE>
<P>
Here is another example that uses <TT>tie()</TT> for handling operations with <a
href="http://www.sgi.com/tech/stl/set.html"><TT>std::set</TT></a>.
<P>
<PRE>
#include &lt;set&gt;
#include &lt;algorithm&gt;
#include &lt;iostream&gt;
#include &lt;boost/utility.hpp&gt;
int
main(int, char*[])
{
{
typedef std::set&lt;int&gt; SetT;
SetT::iterator i, end;
bool inserted;
int vals[5] = { 5, 2, 4, 9, 1 };
SetT s(vals, vals + 5);
// Using tie() with a return value of pair&lt;iterator,bool&gt;
int new_vals[2] = { 3, 9 };
for (int k = 0; k &lt; 2; ++k) {
boost::tie(i,inserted) = s.insert(new_vals[k]);
if (!inserted)
std::cout &lt;&lt; *i &lt;&lt; &quot; was already in the set.&quot; &lt;&lt; std::endl;
else
std::cout &lt;&lt; *i &lt;&lt; &quot; successfully inserted.&quot; &lt;&lt; std::endl;
}
}
{
int* i, *end;
int vals[6] = { 5, 2, 4, 4, 9, 1 };
std::sort(vals, vals + 6);
// Using tie() with a return value of pair&lt;iterator,iterator&gt;
boost::tie(i,end) = std::equal_range(vals, vals + 6, 4);
std::cout &lt;&lt; &quot;There were &quot; &lt;&lt; std::distance(i,end)
&lt;&lt; &quot; occurrences of &quot; &lt;&lt; *i &lt;&lt; &quot;.&quot; &lt;&lt; std::endl;
// Footnote: of course one would normally just use std::count()
// to get this information, but that would spoil the example :)
}
return 0;
}
</PRE>
The output is:
<PRE>
3 successfully inserted.
9 was already in the set.
There were 2 occurrences of 4.
</PRE>
<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>)<br>
<A HREF=http://www.lsc.nd.edu/~llee1>Lie-Quan Lee</A>, Univ.of Notre Dame (<A HREF="mailto:llee1@lsc.nd.edu">llee1@lsc.nd.edu</A>)<br>
<A HREF=http://www.lsc.nd.edu/~lums>Andrew Lumsdaine</A>,
Univ.of Notre Dame (<A
HREF="mailto:lums@lsc.nd.edu">lums@lsc.nd.edu</A>)
</TD></TR></TABLE>
</BODY>
</HTML>

View File

@ -1,64 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
//
// This is an example demonstrating how to use the tie() function.
// The purpose of tie() is to make it easiery to deal with std::pair
// return values.
//
// Contributed by Jeremy Siek
//
// Sample output
//
// 3 successfully inserted.
// 9 was already in the set.
// There were 2 occurrences of 4.
#include <set>
#include <algorithm>
#include <iostream>
#include <iterator> // std::distance
// Note: tie() use to live in boost/utility.hpp, but
// not it is part of the more general Boost Tuple Library.
#include <boost/tuple/tuple.hpp>
int
main(int, char*[])
{
{
typedef std::set<int> SetT;
SetT::iterator i;
bool inserted;
int vals[5] = { 5, 2, 4, 9, 1 };
SetT s(vals, vals + 5);
// Using tie() with a return value of pair<iterator,bool>
int new_vals[2] = { 3, 9 };
for (int k = 0; k < 2; ++k) {
boost::tie(i,inserted) = s.insert(new_vals[k]);
if (!inserted)
std::cout << *i << " was already in the set." << std::endl;
else
std::cout << *i << " successfully inserted." << std::endl;
}
}
{
int* i, *end;
int vals[6] = { 5, 2, 4, 4, 9, 1 };
std::sort(vals, vals + 6);
// Using tie() with a return value of pair<iterator,iterator>
boost::tie(i,end) = std::equal_range(vals, vals + 6, 4);
std::cout << "There were " << std::distance(i,end)
<< " occurrences of " << *i << "." << std::endl;
// Footnote: of course one would normally just use std::count()
// to get this information, but that would spoil the example :)
}
return 0;
}

View File

@ -1,223 +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>Transform 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>Transform Iterator Adaptor</h1>
Defined in header
<a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
<p>
The transform iterator adaptor augments an iterator by applying some
function object to the result of dereferencing the iterator. Another
words, the <tt>operator*</tt> of the transform iterator first
dereferences the base iterator, passes the result of this to the
function object, and then returns the result. The following
<b>pseudo-code</b> shows the basic idea:
<pre>
value_type transform_iterator::operator*() const {
return this->f(*this->base_iterator);
}
</pre>
All of the other operators of the transform iterator behave in the
same fashion as those of the base iterator.
<h2>Synopsis</h2>
<pre>
namespace boost {
template &lt;class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator&gt;
class transform_iterator_generator;
template &lt;class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator&gt;
typename transform_iterator_generator&lt;AdaptableUnaryFunction,Iterator&gt;::type
make_transform_iterator(BaseIterator base, const AdaptableUnaryFunction&amp; f = AdaptableUnaryFunction());
}
</pre>
<hr>
<h2><a name="transform_iterator_generator">The Transform Iterator Type
Generator</a></h2>
The class <tt>transform_iterator_generator</tt> is a helper class whose
purpose is to construct a transform iterator type. The template
parameters for this class are the <tt>AdaptableUnaryFunction</tt> function object
type and the <tt>BaseIterator</tt> type that is being wrapped.
<pre>
template &lt;class AdaptableUnaryFunction, class Iterator&gt;
class transform_iterator_generator
{
public:
typedef <a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a>&lt;...&gt; type;
};
</pre>
<h3>Example</h3>
<p>
The following is an example of how to use the
<tt>transform_iterator_generator</tt> class to iterate through a range
of numbers, multiplying each of them by 2 when they are dereferenced.
The <tt>boost::binder1st</tt> class is used instead of the standard
one because tranform iterator requires the function object to be
Default Constructible.
<p>
<PRE>
#include &lt;functional&gt;
#include &lt;iostream&gt;
#include &lt;boost/iterator_adaptors.hpp&gt;
// definition of class boost::binder1st and function boost::bind1st() ...
int
main(int, char*[])
{
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
typedef boost::binder1st&lt; std::multiplies&lt;int&gt; &gt; Function;
typedef boost::transform_iterator_generator&lt;Function, int*&gt;::type doubling_iterator;
doubling_iterator i(x, boost::bind1st(std::multiplies&lt;int&gt;(), 2)),
i_end(x + sizeof(x)/sizeof(int), boost::bind1st(std::multiplies&lt;int&gt;(), 2));
std::cout &lt;&lt; "multiplying the array by 2:" &lt;&lt; std::endl;
while (i != i_end)
std::cout &lt;&lt; *i++ &lt;&lt; " ";
std::cout &lt;&lt; std::endl;
// to be continued...
</PRE>
The output from this part is:
<pre>
2 4 6 8 10 12 14 16
</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 function object that transforms each element in the iterator
range. The <tt>argument_type</tt> of the function object must match
the value type of the base iterator. The <tt>result_type</tt> of the
function object will be the resulting iterator's
<tt>value_type</tt>. If you want the resulting iterator to behave as
an iterator, the result of the function should be solely a function of
its argument. Also, the function object must be <a
href="http://www.sgi.com/tech/stl/DefaultConstructible.html"> Default
Constructible</a> (which many of the standard function objects are not).</TD>
</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>
</Table>
<h3>Model of</h3>
The transform iterator adaptor (the type
<tt>transform_iterator_generator<...>::type</tt>) is a model of <a
href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a><a href="#1">[1]</a>.
<h3>Members</h3>
The transform 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, except that the <tt>reference</tt> type is the same as the <tt>value_type</tt>
so <tt>operator*()</tt> returns by-value. In addition it has the following constructor:
<pre>
transform_iterator_generator::type(const BaseIterator&amp; it,
const AdaptableUnaryFunction&amp; f = AdaptableUnaryFunction())
</pre>
<p>
<hr>
<p>
<h2><a name="make_transform_iterator">The Transform Iterator Object Generator</a></h2>
<pre>
template &lt;class AdaptableUnaryFunction, class BaseIterator&gt;
typename transform_iterator_generator&lt;AdaptableUnaryFunction,BaseIterator&gt;::type
make_transform_iterator(BaseIterator base,
const AdaptableUnaryFunction&amp; f = AdaptableUnaryFunction());
</pre>
This function provides a convenient way to create transform iterators.
<h3>Example</h3>
Continuing from the previous example, we use the <tt>make_transform_iterator()</tt>
function to add four to each element of the array.
<pre>
std::cout << "adding 4 to each element in the array:" << std::endl;
std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)),
boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}
</pre>
The output from this part is:
<pre>
5 6 7 8 9 10 11 12
</pre>
<h3>Notes</h3>
<a name="1">[1]</a> If the base iterator is a model of <a
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterator</a>
then the transform iterator will also suppport most of the
functionality required by the Random Access Iterator concept. However, a
transform iterator can never completely satisfy the requirements for
<a
href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterator</a>
(or of any concepts that refine Forward Iterator, which includes
Random Access Iterator and Bidirectional Iterator) since the <tt>operator*</tt> of the transform
iterator always returns by-value.
<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>

View File

@ -1,76 +0,0 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
// distribute this software is granted provided this copyright notice appears
// in all copies. This software is provided "as is" without express or implied
// warranty, and with no claim as to its suitability for any purpose.
#include <functional>
#include <algorithm>
#include <iostream>
#include <boost/iterator_adaptors.hpp>
// What a bummer. We can't use std::binder1st with transform iterator
// because it does not have a default constructor. Here's a version
// that does.
namespace boost {
template <class Operation>
class binder1st
: public std::unary_function<typename Operation::second_argument_type,
typename Operation::result_type> {
protected:
Operation op;
typename Operation::first_argument_type value;
public:
binder1st() { } // this had to be added!
binder1st(const Operation& x,
const typename Operation::first_argument_type& y)
: op(x), value(y) {}
typename Operation::result_type
operator()(const typename Operation::second_argument_type& x) const {
return op(value, x);
}
};
template <class Operation, class T>
inline binder1st<Operation> bind1st(const Operation& op, const T& x) {
typedef typename Operation::first_argument_type arg1_type;
return binder1st<Operation>(op, arg1_type(x));
}
} // namespace boost
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 };
const int N = sizeof(x)/sizeof(int);
typedef boost::binder1st< std::multiplies<int> > Function;
typedef boost::transform_iterator_generator<Function, int*>::type doubling_iterator;
doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)),
i_end(x + N, boost::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;
std::cout << "adding 4 to each element in the array:" << std::endl;
std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)),
boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
return 0;
}

View File

@ -1,54 +0,0 @@
// (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 transform 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>
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;
};
int
main()
{
const int N = 10;
// Borland is getting confused about typedef's and constructors here
// Test transform_iterator
{
int x[N], y[N];
for (int k = 0; k < N; ++k)
x[k] = k;
std::copy(x, x + N, y);
for (int k2 = 0; k2 < N; ++k2)
x[k2] = x[k2] * 2;
boost::transform_iterator_generator<mult_functor, int*>::type i(y, mult_functor(2));
boost::input_iterator_test(i, x[0], x[1]);
boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_functor(2)), x[0], x[1]);
}
std::cout << "test successful " << std::endl;
return 0;
}

View File

@ -1,193 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Header boost/utility.hpp Documentation</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" WIDTH="277" HEIGHT="86">Header
<a href="../../boost/utility.hpp">boost/utility.hpp</a></h1>
<p>The entire contents of the header <code><a href="../../boost/utility.hpp">&lt;boost/utility.hpp&gt;</a></code>
are in <code>namespace boost</code>.</p>
<h2>Contents</h2>
<ul>
<li>Class templates supporting the <a href="base_from_member.html">base-from-member
idiom</a></li>
<li>Function templates <a href="#checked_delete">checked_delete() and
checked_array_delete()</a></li>
<li>Function templates <a href="#functions next">next() and prior()</a></li>
<li>Class <a href="#Class noncopyable">noncopyable</a></li>
<li>Function template <a href="#addressof">addressof()</a></li>
<li>Function template <a href="tie.html">tie()</a> and supporting class tied.</li>
</ul>
<h2> Function templates <a name="checked_delete">checked_delete</a>() and
checked_array_delete()</h2>
<p>Deletion of a pointer to an incomplete type is an unsafe programming practice
because there is no way for the compiler to verify that the destructor is indeed
trivial.&nbsp; The checked_delete() and checked_array_delete() function
templates simply <b>delete</b> or <b>delete[]</b> their argument, but also
require that their argument be a complete type.&nbsp; They issue an appropriate
compiler error diagnostic if that requirement is not met.&nbsp; A typical
implementation is shown; other implementations may vary:</p>
<pre> template&lt; typename T &gt;
inline void checked_delete(T const volatile * x)
{
BOOST_STATIC_ASSERT( sizeof(T) ); // assert type complete at point
// of instantiation
delete x;
}
template&lt; typename T &gt;
inline void checked_array_delete(T const volatile * x)
{
BOOST_STATIC_ASSERT( sizeof(T) ); // assert type complete at point
// of instantiation
delete [] x;
}</pre>
<p>Contributed by Beman Dawes, based on a suggestion from Dave Abrahams,
generalizing an idea from Vladimir Prus, with comments from Rainer Deyke, John
Maddock, and others.</p>
<h3>Background</h3>
<p>The C++ Standard specifies that delete on a pointer to an incomplete types is
undefined behavior if the type has a non-trivial destructor in&nbsp; [expr.delete]
5.3.5 paragraph.&nbsp; No diagnostic is required.&nbsp; Some but not all
compilers issue warnings if the type is incomplete at point of deletion.</p>
<h2> <a name="functions next">Function</a> templates next() and prior()</h2>
<p>Certain data types, such as the C++ Standard Library's forward and
bidirectional iterators, do not provide addition and subtraction via operator+()
or operator-().&nbsp; This means that non-modifying computation of the next or
prior value requires a temporary, even though operator++() or operator--() is
provided.&nbsp; It also means that writing code like <code>itr+1</code> inside a
template restricts the iterator category to random access iterators.</p>
<p>The next() and prior() functions provide a simple way around these problems:</p>
<blockquote>
<pre>template &lt;class T&gt;
T next(T x) { return ++x; }
template &lt;class X&gt;
T prior(T x) { return --x; }</pre>
</blockquote>
<p>Usage is simple:</p>
<blockquote>
<pre>const std::list&lt;T&gt;::iterator p = get_some_iterator();
const std::list&lt;T&gt;::iterator prev = boost::prior(p);</pre>
</blockquote>
<p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.</p>
<h2><a name="Class noncopyable">Class noncopyable</a></h2>
<p>Class <strong>noncopyable</strong> is a base class.&nbsp; Derive your own class from <strong>noncopyable</strong>
when you want to prohibit copy construction and copy assignment.</p>
<p>Some objects, particularly those which hold complex resources like files or
network connections, have no sensible copy semantics.&nbsp; Sometimes there are
possible copy semantics, but these would be of very limited usefulness and be
very difficult to implement correctly.&nbsp; Sometimes you're implementing a class that doesn't need to be copied
just yet and you don't want to take the time to write the appropriate functions.&nbsp;
Deriving from <b> noncopyable</b> will prevent the otherwise implicitly-generated
functions (which don't have the proper semantics) from becoming a trap for other programmers.</p>
<p>The traditional way to deal with these is to declare a private copy constructor and copy assignment, and then
document why this is done.&nbsp; But deriving from <b>noncopyable</b> is simpler
and clearer, and doesn't require additional documentation.</p>
<p>The program <a href="noncopyable_test.cpp">noncopyable_test.cpp</a> can be
used to verify class <b>noncopyable</b> works as expected. It has have been run successfully under
GCC 2.95, Metrowerks
CodeWarrior 5.0, and Microsoft Visual C++ 6.0 sp 3.</p>
<p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.</p>
<h3>Example</h3>
<blockquote>
<pre>// inside one of your own headers ...
#include &lt;boost/utility.hpp&gt;
class ResourceLadenFileSystem : boost::noncopyable {
...</pre>
</blockquote>
<h3>Rationale</h3>
<p>Class noncopyable has protected constructor and destructor members to
emphasize that it is to be used only as a base class.&nbsp; Dave Abrahams notes
concern about the effect on compiler optimization of adding (even trivial inline)
destructor declarations. He says &quot;Probably this concern is misplaced, because
noncopyable will be used mostly for classes which own resources and thus have non-trivial destruction semantics.&quot;</p>
<h2><a name="addressof">Function template addressof()</a></h2>
<p>Function <strong>addressof()</strong> returns the address of an object.</p>
<blockquote>
<pre>
template &lt;typename T&gt; inline T* addressof(T& v);
template &lt;typename T&gt; inline const T* addressof(const T& v);
template &lt;typename T&gt; inline volatile T* addressof(volatile T& v);
template &lt;typename T&gt; inline const volatile T* addressof(const volatile T& v);
</pre>
</blockquote>
<p>C++ allows programmers to replace the unary
<strong>operator&()</strong> class member used to get the address of
an object. Getting the real address of an object requires ugly
casting tricks to avoid invoking the overloaded
<strong>operator&()</strong>. Function <strong>addressof()</strong>
provides a wrapper around the necessary code to make it easy to get an
object's real address.
</p>
<p>The program <a href="addressof_test.cpp">addressof_test.cpp</a> can be
used to verify that <b>addressof()</b> works as expected.</p>
<p>Contributed by Brad King based on ideas from discussion with Doug Gregor.</p>
<h3>Example</h3>
<blockquote>
<pre>#include &lt;boost/utility.hpp&gt;
struct useless_type {};
class nonaddressable {
useless_type operator&() const;
};
void f() {
nonaddressable x;
nonaddressable* xp = boost::addressof(x);
// nonaddressable* xpe = &amp;x; /* error */
}</pre>
</blockquote>
<h2>Class templates for the Base-from-Member Idiom</h2>
<p>See <a href="base_from_member.html">separate documentation</a>.</p>
<h2>Function template tie()</h2>
<p>See <a href="tie.html">separate documentation</a>.</p>
<hr>
<p>Revised&nbsp; <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan
-->10 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39328"
-->
</p>
<p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and
distribute this document is granted provided this copyright notice appears in
all copies. This document is provided &quot;as is&quot; without express or
implied warranty, and with no claim as to its suitability for any purpose.</p>
</body>
</html>