Compare commits

...

57 Commits

Author SHA1 Message Date
d9c9685be2 This commit was manufactured by cvs2svn to create branch 'split-config'.
[SVN r10742]
2001-08-04 14:31:38 +00:00
31d0908b74 Add workaround for BOOST_NO_STDC_NAMESPACE
[SVN r10681]
2001-07-20 21:29:36 +00:00
32c77599f4 Fixes for ICL
[SVN r10613]
2001-07-14 12:51:59 +00:00
812ebf3562 Back out commit made in error
[SVN r10596]
2001-07-12 16:15:30 +00:00
37f476013d Change absolute URL's to relative
[SVN r10594]
2001-07-12 15:31:15 +00:00
9f3104166f output_iterator_helper changes: removed default template parameters, added
support for self-proxying, additional documentation and tests (Aleksey Gurtovoy)


[SVN r10576]
2001-07-09 23:51:49 +00:00
64cc0daf34 Integrate Aleksey's changes
[SVN r10575]
2001-07-09 23:50:55 +00:00
d5d64df124 Fix broken link
[SVN r10553]
2001-07-06 19:19:45 +00:00
0edcfcd5c1 Tuples library causes tie to be deprecated
[SVN r10552]
2001-07-06 19:16:39 +00:00
50ba2d419a Tweeked gcc workaround (gcc 3 still has same problem as gcc 2.9x), added tentative Metrowerks and Intel compiler workarounds.
[SVN r10422]
2001-06-25 11:31:14 +00:00
ff3a77ca5a Fixed problem with VC6 compilers - probably a temporary fix.
[SVN r10361]
2001-06-20 11:43:57 +00:00
4eaed6c23d remove superfluous, illegal "typename" (twice)
[SVN r10314]
2001-06-12 18:50:37 +00:00
4d0dd46471 meant to add as a branch
[SVN r10280]
2001-06-06 19:16:34 +00:00
9c2549bd00 files for the tmpw2001 paper about iterator adaptors
[SVN r10278]
2001-06-06 19:08:51 +00:00
b7c8e0c17f changes from Daryle Walker
[SVN r10264]
2001-06-04 11:57:37 +00:00
dd3cfe1837 removed old arg ordering, use defaults instead
[SVN r10258]
2001-06-03 20:00:24 +00:00
43f525298e Remove compiler workarounds no longer needed due to BOOST_STATIC_ASSERT fix. For stylistic reasons, change sizeof() test to sizeof() != 0
[SVN r10236]
2001-05-28 14:22:30 +00:00
1bb1898ab9 Dave says qualifiers weren't really needed
[SVN r10222]
2001-05-24 19:11:51 +00:00
9578f24be9 Workaround compiler problems while waiting to find out if BOOST_STATIC_ASSERT is broken
[SVN r10218]
2001-05-24 16:02:42 +00:00
46fae3aed2 added check_delete workaround for Sun CC
[SVN r10213]
2001-05-24 09:26:48 +00:00
e35f91a70a Smart pointer and utility changes related to adding checked_delere and checked_array_delete
[SVN r10189]
2001-05-22 18:58:21 +00:00
851052fcca Updated docs - added VC6 bug warning
[SVN r10062]
2001-05-08 11:17:44 +00:00
5ef81b2952 Updated/stricter test program
[SVN r10061]
2001-05-08 11:17:05 +00:00
ef2851c053 Fixes for Sun C++ 5.1
[SVN r10060]
2001-05-08 11:16:35 +00:00
0b4387cff5 reorganised tests to show up VC6 bugs
[SVN r10002]
2001-05-02 10:59:32 +00:00
a40cf11fbf Rewritten compressed_pair regression script to test everything in a more methodical way
[SVN r10000]
2001-05-01 11:17:02 +00:00
5c495cd223 Change all eGroups references to YahooGroups
[SVN r9979]
2001-04-25 00:24:50 +00:00
cf1296dff8 added stuff about Default Constructible needed for the function object
[SVN r9683]
2001-03-29 16:26:42 +00:00
d6d88db6e8 std::bind1st -> boost::bind1st
[SVN r9682]
2001-03-29 16:19:34 +00:00
85c2a35257 std::binder1st -> boost::binder1st
[SVN r9681]
2001-03-29 16:18:41 +00:00
836d8b1c64 added spaces in name
[SVN r9673]
2001-03-29 04:08:38 +00:00
98d8c8ab71 fixed broken link
[SVN r9645]
2001-03-27 10:54:12 +00:00
db45013339 fixed sgi stl link
[SVN r9631]
2001-03-22 16:06:15 +00:00
a55c37e7f6 fixed sgi stl links
[SVN r9630]
2001-03-22 16:05:48 +00:00
46a270fcca fixed link to sgi stl
[SVN r9629]
2001-03-22 16:02:11 +00:00
967856518e updated link to sgi stl
[SVN r9628]
2001-03-22 16:01:18 +00:00
7f93e739fe added documentation for initialize() policy function
[SVN r9592]
2001-03-19 21:46:14 +00:00
2cd1422514 added comment about abstract base classes as value_type
[SVN r9584]
2001-03-19 17:31:27 +00:00
feb370b201 1.21.0 run up including fixing broken links
[SVN r9523]
2001-03-09 14:36:41 +00:00
d1b34e64d8 Fixes for validator.w3.org
[SVN r9518]
2001-03-09 03:28:13 +00:00
b9a1eead40 Mostly clarification. Fix: changed "category" to "iterator_category" in one place.
[SVN r9517]
2001-03-09 03:10:32 +00:00
1e4bfac98c added named template parameter to table of contents
[SVN r9510]
2001-03-08 21:36:09 +00:00
3bb504fbf3 added revision history line
[SVN r9506]
2001-03-08 20:50:14 +00:00
5029791c90 split off indirect and transform tests into separate files
[SVN r9505]
2001-03-08 20:49:05 +00:00
a1a68f0970 1.21.0 run up
[SVN r9502]
2001-03-08 20:35:52 +00:00
f8543d79eb added more static asserts
[SVN r9500]
2001-03-08 20:02:00 +00:00
f353415136 added docs for iterator_traits_generator
[SVN r9498]
2001-03-08 19:19:46 +00:00
26240403b0 added a test to make sure that the type set by the generator is really the
type used


[SVN r9497]
2001-03-08 19:04:29 +00:00
3a39729b58 new file
[SVN r9488]
2001-03-08 16:33:40 +00:00
096c961d9a Patches for Intel C++
[SVN r9425]
2001-03-04 16:08:20 +00:00
01fe04a6a2 Workaround for Borland
[SVN r9424]
2001-03-04 16:07:11 +00:00
7ea4014993 Misc fixes that missed the last commit..
[SVN r9402]
2001-03-04 11:08:29 +00:00
d50b374f88 Boost Test Library initial commit
[SVN r9364]
2001-02-28 21:39:56 +00:00
27dfb25570 added function output iterator adaptor
[SVN r9351]
2001-02-27 05:50:51 +00:00
b5ed77985e added missing typename's to docs
[SVN r9324]
2001-02-25 12:04:48 +00:00
61243bd15f type_traits: more tentative EDG compiler fixes...
[SVN r9321]
2001-02-24 13:04:56 +00:00
368b94d804 Corrected numeric_limits<>::is_integral -> numeric_limits<>::is_integer
[SVN r9299]
2001-02-20 23:15:29 +00:00
33 changed files with 3243 additions and 1294 deletions

View File

@ -100,7 +100,7 @@ Assignment
</UL>
<h3>See also</h3>
<a href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">DefaultConstructible</A>
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</A>
and
<A href="./CopyConstructible.html">CopyConstructible</A>

View File

@ -11,7 +11,7 @@
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>CopyConstructible</Title>
<Title>Copy Constructible</Title>
</HEAD>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
@ -19,10 +19,10 @@
ALT="C++ Boost" width="277" height="86">
<!--end header-->
<BR Clear>
<H1>CopyConstructible</H1>
<H1>Copy Constructible</H1>
<h3>Description</h3>
A type is CopyConstructible if it is possible to copy objects of that
A type is Copy Constructible if it is possible to copy objects of that
type.
<h3>Notation</h3>
@ -32,7 +32,7 @@ type.
<tt>T</tt>
</TD>
<TD VAlign=top>
is type that is a model of CopyConstructible
is type that is a model of Copy Constructible
</TD>
</TR>
@ -194,9 +194,9 @@ denotes the address of <tt>u</tt>
<h3>See also</h3>
<A
href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">DefaultConstructible</A>
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</A>
and
<A href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</A>
<A hrefa="./Assignable.html">Assignable</A>
<br>
<HR>

View File

@ -196,7 +196,7 @@ 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/Technology/STL/EqualityComparable.html">EqualityComparable</A>, <A href="http://www.sgi.com/Technology/STL/StrictWeakOrdering.html">StrictWeakOrdering</A>
<A href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</A>, <A href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">StrictWeakOrdering</A>

View File

@ -21,21 +21,21 @@
<H2>
<A NAME="concept:MultiPassInputIterator"></A>
MultiPassInputIterator
Multi-Pass Input Iterator
</H2>
This concept is a refinement of <a
href="http://www.sgi.com/Technology/STL/InputIterator.html">InputIterator</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
MultiPassInputIterator is very similar to the <a
href="http://www.sgi.com/Technology/STL/ForwardIterator.hmtl">ForwardIterator</a>. 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/Technology/STL/ForwardIterator.hmtl">ForwardIterator</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/Technology/STL/InputIterator.html">InputIterator</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>.
@ -44,29 +44,29 @@ in that the <TT>reference</TT> type merely has to be convertible to
comments by Valentin Bonnard:
<p> I think that introducing MultiPassInputIterator isn't the right
solution. Do you also want to define MultiPassBidirectionnalIterator
and MultiPassRandomAccessIterator ? I don't, definitly. It only
<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 RandomAccess are about
<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 MultiPassInputIterator
is just called a ForwardIterator.
immutabillity. With these clean concepts, your Multi-Pass Input Iterator
is just called a Forward Iterator.
<p>
Other translations are:<br>
std::ForwardIterator -> ForwardIterator & LvalueIterator<br>
std::BidirectionnalIterator -> BidirectionnalIterator & LvalueIterator<br>
std::RandomAccessIterator -> RandomAccessIterator & LvalueIterator<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
ForwardIterator which is allowed on std::ForwardIterator is
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>
@ -75,9 +75,9 @@ 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 ForwardIterator. The right course
of action is to get ForwardIterator, etc. changed in the C++ standard.
Once that is done we can drop MultiPassInputIterator.
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>
@ -85,7 +85,7 @@ Once that is done we can drop MultiPassInputIterator.
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
<A HREF=file:///c:/boost/site/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>

View File

@ -5,7 +5,7 @@
content="text/html; charset=iso-8859-1">
<meta name="Template"
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<title>Call Traits</title>
</head>
@ -34,9 +34,9 @@ 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>
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>
@ -79,7 +79,8 @@ solve the reference to reference problem).</p>
</td>
</tr>
<tr>
<td valign="top" width="17%"><p align="center">const T&amp;<br>
<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>
@ -91,7 +92,8 @@ solve the reference to reference problem).</p>
</td>
</tr>
<tr>
<td valign="top" width="17%"><p align="center">const T&amp;<br>
<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>
@ -332,8 +334,8 @@ possible:</p>
<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>
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>
@ -388,7 +390,8 @@ can not be used with reference or array types.</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 valign="top" width="17%"><p align="center">const
int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">int const</p>
</td>
@ -420,7 +423,8 @@ can not be used with reference or array types.</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 valign="top" width="17%"><p align="center">const
int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">int&amp;</p>
</td>
@ -432,13 +436,17 @@ can not be used with reference or array types.</p>
<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 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 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 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 valign="top" width="17%"><p align="center">const
int&amp;</p>
</td>
<td valign="top" width="17%"><p align="center">All
constant-references.</p>
@ -486,8 +494,8 @@ can not be used with reference or array types.</p>
<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>
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
@ -523,14 +531,14 @@ problem):</h4>
<pre>template &lt;class Operation&gt;
class binder1st :
public unary_function&lt;Operation::second_argument_type, Operation::result_type&gt;
public unary_function&lt;typename Operation::second_argument_type, typename Operation::result_type&gt;
{
protected:
Operation op;
Operation::first_argument_type value;
typename Operation::first_argument_type value;
public:
binder1st(const Operation&amp; x, const Operation::first_argument_type&amp; y);
Operation::result_type operator()(const Operation::second_argument_type&amp; x) const;
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
@ -541,7 +549,7 @@ reference to a reference as an argument, and that is not
currently legal. The solution here is to modify <code>operator()</code>
to use call_traits:</p>
<pre>Operation::result_type operator()(call_traits&lt;Operation::second_argument_type&gt;::param_type x) const;</pre>
<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
@ -575,9 +583,9 @@ std::pair&lt;
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>
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>
@ -666,10 +674,10 @@ 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,
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
@ -687,11 +695,11 @@ 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>
<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)
@ -706,13 +714,13 @@ declared type:</p>
<pre>template &lt;class T&gt;
struct A
{
void foo(call_traits&lt;T&gt;::value_type t);
void foo(typename call_traits&lt;T&gt;::value_type t);
};
template &lt;class T&gt;
void A&lt;T&gt;::foo(call_traits&lt;T&gt;::value_type t)
void A&lt;T&gt;::foo(typename call_traits&lt;T&gt;::value_type t)
{
call_traits&lt;T&gt;::value_type dup(t); // OK even if T is an array type.
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
@ -743,7 +751,7 @@ Hinnant and John Maddock.</p>
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
Maddock</a>, the latest version of this file can be found at <a
href="http://www.boost.org/">www.boost.org</a>, and the boost
discussion list at <a href="http://www.egroups.com/list/boost">www.egroups.com/list/boost</a>.</p>
discussion list at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
<p>.</p>

View File

@ -117,13 +117,14 @@ void call_traits_checker<T>::operator()(param_type p)
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
@ -192,14 +193,14 @@ int main(int argc, char *argv[ ])
int i = 2;
c2(i);
int* pi = &i;
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
#if (defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_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)
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__)
int a[2] = {1,2};
call_traits_checker<int[2]> c6;
c6(a);
@ -237,7 +238,7 @@ int main(int argc, char *argv[ ])
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))
#if !(defined(__GNUC__) && (__GNUC__ < 4))
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)
@ -364,6 +365,8 @@ template struct call_traits_test<int[2], true>;
#ifdef BOOST_MSVC
unsigned int expected_failures = 10;
#elif defined(__SUNPRO_CC)
unsigned int expected_failures = 11;
#elif defined(__BORLANDC__)
unsigned int expected_failures = 2;
#elif defined(__GNUC__)
@ -373,3 +376,5 @@ unsigned int expected_failures = 0;
#endif

31
checked_delete_test.cpp Normal file
View File

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

@ -6,14 +6,15 @@ content="text/html; charset=iso-8859-1">
<meta name="Template"
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
<title>Header <boost/compressed_pair.hpp></title>
<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/call_traits.hpp">boost/compressed_pair.hpp</a>&gt;</h2>
&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>
@ -41,6 +42,8 @@ public:
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;
@ -61,17 +64,19 @@ constructor, and this constructor initialises both values in the
pair to the passed value.</p>
<p>Note that compressed_pair can not be instantiated if either of
the template arguments is an enumerator type, unless there is
compiler support for boost::is_enum, or if boost::is_enum is
specialised for the enumerator type.</p>
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, compressed_pair requires compiler support for partial
specialisation of class templates - without that support
compressed_pair behaves just like std::pair.</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 March 2000</p>
<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
@ -85,7 +90,8 @@ Hinnant and John Maddock.</p>
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
Maddock</a>, the latest version of this file can be found at <a
href="http://www.boost.org">www.boost.org</a>, and the boost
discussion list at <a href="http://www.egroups.com/list/boost">www.egroups.com/list/boost</a>.</p>
discussion list at <a
href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
<p>&nbsp;</p>
</body>

View File

@ -15,6 +15,8 @@
#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;
@ -54,108 +56,345 @@ struct non_empty2
{ return a.i == b.i; }
};
int main(int argc, char *argv[ ])
{
compressed_pair<int, double> cp1(1, 1.3);
assert(cp1.first() == 1);
assert(cp1.second() == 1.3);
compressed_pair<int, double> cp1b(2, 2.3);
assert(cp1b.first() == 2);
assert(cp1b.second() == 2.3);
swap(cp1, cp1b);
assert(cp1b.first() == 1);
assert(cp1b.second() == 1.3);
assert(cp1.first() == 2);
assert(cp1.second() == 2.3);
compressed_pair<non_empty1, non_empty2> cp1c(non_empty1(9));
assert(cp1c.second() == non_empty2());
assert(cp1c.first() == non_empty1(9));
compressed_pair<non_empty1, non_empty2> cp1d(non_empty2(9));
assert(cp1d.second() == non_empty2(9));
assert(cp1d.first() == non_empty1());
compressed_pair<int, double> cp1e(cp1);
compressed_pair<empty_UDT, int> cp2(2);
assert(cp2.second() == 2);
compressed_pair<int, empty_UDT> cp3(1);
assert(cp3.first() ==1);
compressed_pair<empty_UDT, empty_UDT> cp4;
compressed_pair<empty_UDT, empty_POD_UDT> cp5;
compressed_pair<int, empty_UDT> cp9(empty_UDT());
compressed_pair<int, empty_UDT> cp10(1);
assert(cp10.first() == 1);
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) || !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
int i = 0;
compressed_pair<int&, int&> cp6(i,i);
assert(cp6.first() == i);
assert(cp6.second() == i);
assert(&cp6.first() == &i);
assert(&cp6.second() == &i);
compressed_pair<int, double[2]> cp7;
cp7.first();
double* pd = cp7.second();
#ifdef __GNUC__
using std::swap;
#endif
value_test(true, (sizeof(compressed_pair<empty_UDT, int>) < sizeof(std::pair<empty_UDT, int>)))
value_test(true, (sizeof(compressed_pair<int, empty_UDT>) < sizeof(std::pair<int, empty_UDT>)))
value_test(true, (sizeof(compressed_pair<empty_UDT, empty_UDT>) < sizeof(std::pair<empty_UDT, empty_UDT>)))
value_test(true, (sizeof(compressed_pair<empty_UDT, empty_POD_UDT>) < sizeof(std::pair<empty_UDT, empty_POD_UDT>)))
value_test(true, (sizeof(compressed_pair<empty_UDT, compressed_pair<empty_POD_UDT, int> >) < sizeof(std::pair<empty_UDT, std::pair<empty_POD_UDT, int> >)))
return check_result(argc, argv);
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);
}
//
// instanciate some compressed pairs:
#ifdef __MWERKS__
template class compressed_pair<int, double>;
template class compressed_pair<int, int>;
template class compressed_pair<empty_UDT, int>;
template class compressed_pair<int, empty_UDT>;
template class compressed_pair<empty_UDT, empty_UDT>;
template class compressed_pair<empty_UDT, empty_POD_UDT>;
#else
template class boost::compressed_pair<int, double>;
template class boost::compressed_pair<int, int>;
template class boost::compressed_pair<empty_UDT, int>;
template class boost::compressed_pair<int, empty_UDT>;
template class boost::compressed_pair<empty_UDT, empty_UDT>;
template class boost::compressed_pair<empty_UDT, empty_POD_UDT>;
#endif
// 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 p3, second_param_type p4)
{
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
#ifndef __MWERKS__
// first param construct:
boost::compressed_pair<T1,T2> cp2(p1);
cp2.second() = p2;
BOOST_TEST(cp2.first() == p1);
BOOST_TEST(cp2.second() == p2);
#endif
}
//
// now some for which only a few specific members can be instantiated,
// first references:
template double& compressed_pair<double, int&>::first();
template int& compressed_pair<double, int&>::second();
#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95))
template compressed_pair<double, int&>::compressed_pair(int&);
#endif
template compressed_pair<double, int&>::compressed_pair(call_traits<double>::param_type,int&);
// supplimentary tests for case where second arg only is a reference type:
//
// and then arrays:
#ifndef __BORLANDC__
template call_traits<int[2]>::reference compressed_pair<double, int[2]>::second();
#endif
template call_traits<double>::reference compressed_pair<double, int[2]>::first();
#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95))
template compressed_pair<double, int[2]>::compressed_pair(call_traits<double>::param_type);
#endif
template compressed_pair<double, int[2]>::compressed_pair();
#endif // __MWERKS__
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
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 p3, second_param_type p4)
{
#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 p3, second_param_type p4)
{
// 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 p3, second_param_type p4)
{
// 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 p3, second_param_type p4)
{
// 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 argc, char *argv[ ])
{
// 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;
}
#ifdef __BORLANDC__
// can't handle both types empty:
unsigned int expected_failures = 4;
#elif defined(__GNUC__)
// no zero sized base classes:
unsigned int expected_failures = 4;
#else
unsigned int expected_failures = 0;
#endif

View File

@ -282,7 +282,7 @@ template &lt;class Incrementable&gt;
struct counting_iterator_traits
{
if (numeric_limits&lt;Incrementable&gt::is_specialized) {
if (!numeric_limits&lt;Incrementable&gt::is_integral)
if (!numeric_limits&lt;Incrementable&gt::is_integer)
COMPILE_TIME_ERROR;
if (!numeric_limits&lt;Incrementable&gt::is_bounded
@ -308,7 +308,7 @@ 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 -->15 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" --></p>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --></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;

View File

@ -168,8 +168,8 @@ this parameter is the appropriate type.<br>
The filter iterator adaptor (the type
<tt>filter_iterator_generator<...>::type</tt>) may be a model of <a
href="www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> or <a
href="www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</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.
@ -261,7 +261,7 @@ default).
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->10 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" --></p>
<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;

41
fun_out_iter_example.cpp Normal file
View File

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

View File

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

View File

@ -1,20 +1,23 @@
// Boost operators.hpp header file ----------------------------------------//
// (C) Copyright David Abrahams 1999. Permission to copy, use,
// modify, sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-2001.
// Permission to copy, use, modify, sell and distribute this software is
// granted provided this copyright notice appears in all copies. This
// software is provided "as is" without express or implied warranty, and
// with no claim as to its suitability for any purpose.
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 25 Jun 01 output_iterator_helper changes: removed default template
// parameters, added support for self-proxying, additional
// documentation and tests (Aleksey Gurtovoy)
// 29 May 01 Added operator classes for << and >>. Added input and output
// iterator helper classes. Added classes to connect equality and
// relational operators. Added classes for groups of related
// operators. Reimplemented example operator and iterator helper
// classes in terms of the new groups. (Daryle Walker, with help
// from Alexy Gurtovoy)
// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
// supplied arguments from actually being used (Dave Abrahams)
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
@ -282,12 +285,190 @@ struct indexable : B
}
};
// More operator classes (contributed by Daryle Walker) --------------------//
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; }
};
template <class T, class B = ::boost::detail::empty_base>
struct left_shiftable1 : B
{
friend T operator<<(T x, const T& y) { return x <<= y; }
};
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; }
};
template <class T, class B = ::boost::detail::empty_base>
struct right_shiftable1 : B
{
friend T operator>>(T x, const T& y) { return x >>= y; }
};
template <class T, class U, class B = ::boost::detail::empty_base>
struct equivalent2 : B
{
friend bool operator==(const T& x, const U& y)
{
return !(x < y) && !(x > y);
}
};
template <class T, class B = ::boost::detail::empty_base>
struct equivalent1 : B
{
friend bool operator==(const T&x, const T&y)
{
return !(x < y) && !(y < x);
}
};
template <class T, class U, class B = ::boost::detail::empty_base>
struct partially_ordered2 : B
{
friend bool operator<=(const T& x, const U& y)
{ return (x < y) || (x == y); }
friend bool operator>=(const T& x, const U& y)
{ return (x > y) || (x == y); }
friend bool operator>(const U& x, const T& y)
{ return y < x; }
friend bool operator<(const U& x, const T& y)
{ return y > x; }
friend bool operator<=(const U& x, const T& y)
{ return (y > x) || (y == x); }
friend bool operator>=(const U& x, const T& y)
{ return (y < x) || (y == x); }
};
template <class T, class B = ::boost::detail::empty_base>
struct partially_ordered1 : B
{
friend bool operator>(const T& x, const T& y)
{ return y < x; }
friend bool operator<=(const T& x, const T& y)
{ return (x < y) || (x == y); }
friend bool operator>=(const T& x, const T& y)
{ return (y < x) || (x == y); }
};
// Combined operator classes (contributed by Daryle Walker) ----------------//
template <class T, class U, class B = ::boost::detail::empty_base>
struct totally_ordered2
: less_than_comparable2<T, U
, equality_comparable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base>
struct totally_ordered1
: less_than_comparable1<T
, equality_comparable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct additive2
: addable2<T, U
, subtractable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base>
struct additive1
: addable1<T
, subtractable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct multiplicative2
: multipliable2<T, U
, dividable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base>
struct multiplicative1
: multipliable1<T
, dividable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct integer_multiplicative2
: multiplicative2<T, U
, modable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base>
struct integer_multiplicative1
: multiplicative1<T
, modable1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct arithmetic2
: additive2<T, U
, multiplicative2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base>
struct arithmetic1
: additive1<T
, multiplicative1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct integer_arithmetic2
: additive2<T, U
, integer_multiplicative2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base>
struct integer_arithmetic1
: additive1<T
, integer_multiplicative1<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct bitwise2
: xorable2<T, U
, andable2<T, U
, orable2<T, U, B
> > > {};
template <class T, class B = ::boost::detail::empty_base>
struct bitwise1
: xorable1<T
, andable1<T
, orable1<T, B
> > > {};
template <class T, class B = ::boost::detail::empty_base>
struct unit_steppable
: incrementable<T
, decrementable<T, B
> > {};
template <class T, class U, class B = ::boost::detail::empty_base>
struct shiftable2
: left_shiftable2<T, U
, right_shiftable2<T, U, B
> > {};
template <class T, class B = ::boost::detail::empty_base>
struct shiftable1
: left_shiftable1<T
, right_shiftable1<T, B
> > {};
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
} // namespace boost
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
// BOOST_IMPORT_TEMPLATE1/BOOST_IMPORT_TEMPLATE2 -
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE3 -
//
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
@ -295,12 +476,31 @@ struct indexable : B
// two-argument forms. Note that these macros expect to be invoked from within
// boost.
#if defined(BOOST_NO_OPERATORS_IN_NAMESPACE)
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
# if defined(BOOST_NO_USING_TEMPLATE)
// The template is already in boost so we have nothing to do.
# define BOOST_IMPORT_TEMPLATE3(template_name)
# define BOOST_IMPORT_TEMPLATE2(template_name)
# define BOOST_IMPORT_TEMPLATE1(template_name)
#else // BOOST_NO_OPERATORS_IN_NAMESPACE
# ifndef BOOST_NO_USING_TEMPLATE
// Bring the names in with a using-declaration
// to avoid stressing the compiler.
# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
# else
// Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
// from working, we are forced to use inheritance for that compiler.
# define BOOST_IMPORT_TEMPLATE3(template_name) \
template <class T, class U, class V, class B = ::boost::detail::empty_base> \
struct template_name : ::template_name<T, U, V, B> {};
// Because a Borland C++ 5.5 bug prevents a using declaration from working,
// we are forced to use inheritance for that compiler.
# define BOOST_IMPORT_TEMPLATE2(template_name) \
template <class T, class U, class B = ::boost::detail::empty_base> \
struct template_name : ::template_name<T, U, B> {};
@ -309,21 +509,8 @@ struct indexable : B
template <class T, class B = ::boost::detail::empty_base> \
struct template_name : ::template_name<T, B> {};
# else
// Otherwise, bring the names in with a using-declaration to avoid
// stressing the compiler
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
# endif // BOOST_NO_USING_TEMPLATE
#else // !BOOST_NO_OPERATORS_IN_NAMESPACE
// The template is already in boost so we have nothing to do.
# define BOOST_IMPORT_TEMPLATE2(template_name)
# define BOOST_IMPORT_TEMPLATE1(template_name)
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
//
@ -332,7 +519,7 @@ struct indexable : B
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
// neccessary.
//
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
// is_chained_base<> - a traits class used to distinguish whether an operator
// template argument is being used for base class chaining, or is specifying a
@ -355,6 +542,15 @@ template<class T> struct is_chained_base {
} // namespace boost
// Import a 3-type-argument operator template into boost (if neccessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
BOOST_IMPORT_TEMPLATE3(template_name3) \
template<class T, class U, class V, class B> \
struct is_chained_base< ::boost::template_name3<T, U, V, B> > { \
typedef ::boost::detail::true_t value; \
};
// Import a 2-type-argument operator template into boost (if neccessary) and
// provide a specialization of 'is_chained_base<>' for it.
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
@ -414,6 +610,8 @@ BOOST_OPERATOR_TEMPLATE1(template_name##1)
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
BOOST_IMPORT_TEMPLATE3(template_name3)
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
BOOST_IMPORT_TEMPLATE2(template_name2)
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
@ -442,47 +640,41 @@ BOOST_OPERATOR_TEMPLATE(orable)
BOOST_OPERATOR_TEMPLATE1(incrementable)
BOOST_OPERATOR_TEMPLATE1(decrementable)
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
BOOST_OPERATOR_TEMPLATE3(indexable)
// indexable doesn't follow the patterns above (it has 4 template arguments), so
// we just write out the compiler hacks explicitly.
#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
# ifdef BOOST_NO_USING_TEMPLATE
template <class T, class I, class R, class B = ::boost::detail::empty_base>
struct indexable : ::indexable<T,I,R,B> {};
# else
using ::indexable;
# endif
#endif
BOOST_OPERATOR_TEMPLATE(left_shiftable)
BOOST_OPERATOR_TEMPLATE(right_shiftable)
BOOST_OPERATOR_TEMPLATE(equivalent)
BOOST_OPERATOR_TEMPLATE(partially_ordered)
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T, class I, class R, class B>
struct is_chained_base< ::boost::indexable<T, I, R, B> > {
typedef ::boost::detail::true_t operator_template_type;
};
#endif
BOOST_OPERATOR_TEMPLATE(totally_ordered)
BOOST_OPERATOR_TEMPLATE(additive)
BOOST_OPERATOR_TEMPLATE(multiplicative)
BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
BOOST_OPERATOR_TEMPLATE(arithmetic)
BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
BOOST_OPERATOR_TEMPLATE(bitwise)
BOOST_OPERATOR_TEMPLATE1(unit_steppable)
BOOST_OPERATOR_TEMPLATE(shiftable)
#undef BOOST_OPERATOR_TEMPLATE
#undef BOOST_OPERATOR_TEMPLATE3
#undef BOOST_OPERATOR_TEMPLATE2
#undef BOOST_OPERATOR_TEMPLATE1
#undef BOOST_IMPORT_TEMPLATE1
#undef BOOST_IMPORT_TEMPLATE2
#undef BOOST_IMPORT_TEMPLATE3
// The following 'operators' classes can only be used portably if the derived class
// declares ALL of the required member operators.
template <class T, class U>
struct operators2
: less_than_comparable2<T,U
, equality_comparable2<T,U
, addable2<T,U
, subtractable2<T,U
, multipliable2<T,U
, dividable2<T,U
, modable2<T,U
, orable2<T,U
, andable2<T,U
, xorable2<T,U
> > > > > > > > > > {};
: totally_ordered2<T,U
, integer_arithmetic2<T,U
, bitwise2<T,U
> > > {};
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template <class T, class U = T>
@ -492,31 +684,47 @@ template <class T> struct operators<T, T>
#else
template <class T> struct operators
#endif
: less_than_comparable<T
, equality_comparable<T
, addable<T
, subtractable<T
, multipliable<T
, dividable<T
, modable<T
, orable<T
, andable<T
, xorable<T
, incrementable<T
, decrementable<T
> > > > > > > > > > > > {};
: totally_ordered<T
, integer_arithmetic<T
, bitwise<T
, unit_steppable<T
> > > > {};
// Iterator helper classes (contributed by Jeremy Siek) -------------------//
// (Input and output iterator helpers contributed by Daryle Walker) -------//
// (Changed to use combined operator classes by Daryle Walker) ------------//
template <class T,
class V,
class D = std::ptrdiff_t,
class P = V const *,
class R = V const &>
struct input_iterator_helper
: equality_comparable1<T
, incrementable<T
, dereferenceable<T, P
, boost::iterator<std::input_iterator_tag, V, D, P, R
> > > > {};
template<class Derived>
struct output_iterator_helper
: boost::incrementable<Derived
, boost::iterator<std::output_iterator_tag, void, void, void, void
> >
{
Derived& operator*() { return static_cast<Derived&>(*this); }
Derived& operator++() { return static_cast<Derived&>(*this); }
};
template <class T,
class V,
class D = std::ptrdiff_t,
class P = V*,
class R = V&>
struct forward_iterator_helper
: equality_comparable<T
: equality_comparable1<T
, incrementable<T
, dereferenceable<T,P
, boost::iterator<std::forward_iterator_tag,V,D,P,R
, dereferenceable<T, P
, boost::iterator<std::forward_iterator_tag, V, D, P, R
> > > > {};
template <class T,
@ -525,12 +733,11 @@ template <class T,
class P = V*,
class R = V&>
struct bidirectional_iterator_helper
: equality_comparable<T
, incrementable<T
, decrementable<T
, dereferenceable<T,P
, boost::iterator<std::bidirectional_iterator_tag,V,D,P,R
> > > > > {};
: equality_comparable1<T
, unit_steppable<T
, dereferenceable<T, P
, boost::iterator<std::bidirectional_iterator_tag, V, D, P, R
> > > > {};
template <class T,
class V,
@ -538,22 +745,17 @@ template <class T,
class P = V*,
class R = V&>
struct random_access_iterator_helper
: equality_comparable<T
, less_than_comparable<T
, incrementable<T
, decrementable<T
, dereferenceable<T,P
, addable2<T,D
, subtractable2<T,D
, indexable<T,D,R
, boost::iterator<std::random_access_iterator_tag,V,D,P,R
> > > > > > > > >
: totally_ordered1<T
, unit_steppable<T
, dereferenceable<T, P
, additive2<T, D
, indexable<T, D, R
, boost::iterator<std::random_access_iterator_tag, V, D, P, R
> > > > > >
{
#ifndef __BORLANDC__
friend D requires_difference_operator(const T& x, const T& y) {
return x - y;
}
#endif
}; // random_access_iterator_helper
} // namespace boost

View File

@ -11,6 +11,9 @@
// Classes appear in alphabetical order
// Revision History
// 21 May 01 checked_delete() and checked_array_delete() added (Beman Dawes,
// suggested by Dave Abrahams, generalizing idea from Vladimir Prus)
// 21 May 01 made next() and prior() inline (Beman Dawes)
// 26 Jan 00 protected noncopyable destructor added (Miki Jovanovic)
// 10 Dec 99 next() and prior() templates added (Dave Abrahams)
// 30 Aug 99 moved cast templates to cast.hpp (Beman Dawes)
@ -22,12 +25,32 @@
#ifndef BOOST_UTILITY_HPP
#define BOOST_UTILITY_HPP
#include <boost/config.hpp>
#include <cstddef> // for size_t
#include <utility> // for std::pair
#include <boost/config.hpp> // broken compiler workarounds
#include <boost/static_assert.hpp>
#include <cstddef> // for size_t
#include <utility> // for std::pair
namespace boost
{
// checked_delete() and checked_array_delete() -----------------------------//
// verify that types are complete for increased safety
template< typename T >
inline void checked_delete(T * x)
{
BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point
// of instantiation
delete x;
}
template< typename T >
inline void checked_array_delete(T * x)
{
BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point
// of instantiation
delete [] x;
}
// next() and prior() template functions -----------------------------------//
@ -41,10 +64,10 @@ namespace boost
// Contributed by Dave Abrahams
template <class T>
T next(T x) { return ++x; }
inline T next(T x) { return ++x; }
template <class T>
T prior(T x) { return --x; }
inline T prior(T x) { return --x; }
// class noncopyable -------------------------------------------------------//

View File

@ -422,8 +422,7 @@ a,b,c,d,e,f,g,
<hr>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->10
Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" -->
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" -->
<p>&copy; Copyright Jeremy Siek and David Abrahams 2001. Permission to

View File

@ -29,8 +29,7 @@ int main(int, char*[])
// Example of using indirect_iterator_pair_generator
typedef boost::indirect_iterator_pair_generator<char**,
char, char*, char&, const char*, const char&> PairGen;
typedef boost::indirect_iterator_pair_generator<char**, char> PairGen;
char mutable_characters[N];
char* pointers_to_mutable_chars[N];

151
indirect_iterator_test.cpp Normal file
View File

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

61
iter_traits_gen_test.cpp Normal file
View File

@ -0,0 +1,61 @@
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
// copyright notice appears in all copies. This software is provided
// "as is" without express or implied warranty, and with no claim as
// to its suitability for any purpose.
// 8 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::iterator_traits_generator
::reference<dummyT>
::iterator_category<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::iterator_traits_generator
::value_type<dummyT>
::reference<const dummyT&>
::pointer<const dummyT*>
::iterator_category<std::forward_iterator_tag>
::difference_type<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,4 +1,4 @@
// Demonstrate and test boost/operators.hpp on std::iterators -------------//
// Test boost/iterator_adaptors.hpp
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
// sell and distribute this software is granted provided this
@ -9,6 +9,8 @@
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 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)
@ -59,28 +61,6 @@ struct my_iterator_tag : public std::random_access_iterator_tag { };
using boost::dummyT;
struct my_iter_traits {
typedef dummyT value_type;
typedef dummyT* pointer;
typedef dummyT& reference;
typedef my_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
};
struct my_const_iter_traits {
typedef dummyT value_type;
typedef const dummyT* pointer;
typedef const dummyT& reference;
typedef my_iterator_tag iterator_category;
typedef std::ptrdiff_t difference_type;
};
typedef boost::iterator_adaptor<dummyT*,
boost::default_iterator_policies, dummyT> my_iterator;
typedef boost::iterator_adaptor<const dummyT*,
boost::default_iterator_policies, const dummyT> const_my_iterator;
struct mult_functor {
typedef int result_type;
@ -117,78 +97,6 @@ typedef std::deque<int> storage;
typedef std::deque<int*> pointer_deque;
typedef std::set<storage::iterator> iterator_set;
void more_indirect_iterator_tests()
{
// For some reason all heck breaks loose in the compiler under these conditions.
#if !defined(BOOST_MSVC) || !defined(__STL_DEBUG)
storage store(1000);
std::generate(store.begin(), store.end(), rand);
pointer_deque ptr_deque;
iterator_set iter_set;
for (storage::iterator p = store.begin(); p != store.end(); ++p)
{
ptr_deque.push_back(&*p);
iter_set.insert(p);
}
typedef boost::indirect_iterator_pair_generator<
pointer_deque::iterator
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
, int
#endif
> IndirectDeque;
IndirectDeque::iterator db(ptr_deque.begin());
IndirectDeque::iterator de(ptr_deque.end());
assert(static_cast<std::size_t>(de - db) == store.size());
assert(db + store.size() == de);
IndirectDeque::const_iterator dci(db);
assert(db == dci);
assert(dci == db);
assert(dci != de);
assert(dci < de);
assert(dci <= de);
assert(de >= dci);
assert(de > dci);
dci = de;
assert(dci == de);
boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin()));
*db = 999;
assert(store.front() == 999);
typedef boost::indirect_iterator_generator<
iterator_set::iterator
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
, int
#endif
>::type indirect_set_iterator;
typedef boost::indirect_iterator_generator<
iterator_set::iterator,
const int
>::type const_indirect_set_iterator;
indirect_set_iterator sb(iter_set.begin());
indirect_set_iterator se(iter_set.end());
const_indirect_set_iterator sci(iter_set.begin());
assert(sci == sb);
assert(sci != se);
sci = se;
assert(sci == se);
*boost::prior(se) = 888;
assert(store.back() == 888);
assert(std::equal(sb, se, store.begin()));
boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
assert(std::equal(db, de, store.begin()));
#endif
}
int
main()
{
@ -210,67 +118,14 @@ main()
// Test the iterator_adaptor
{
my_iterator i(array);
boost::iterator_adaptor<dummyT*, boost::default_iterator_policies, dummyT> i(array);
boost::random_access_iterator_test(i, N, array);
const_my_iterator j(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 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]);
}
// Test indirect_iterator_generator
{
dummyT* ptr[N];
for (int k = 0; k < N; ++k)
ptr[k] = array + k;
typedef boost::indirect_iterator_generator<dummyT**
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
, dummyT
#endif
>::type indirect_iterator;
typedef boost::indirect_iterator_generator<dummyT**, const dummyT>::type const_indirect_iterator;
indirect_iterator i(ptr);
boost::random_access_iterator_test(i, N, array);
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
#endif
// check operator->
assert((*i).m_x == i->foo());
const_indirect_iterator j(ptr);
boost::random_access_iterator_test(j, N, array);
dummyT*const* const_ptr = ptr;
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
#endif
boost::const_nonconst_iterator_test(i, ++j);
more_indirect_iterator_tests();
}
// Test projection_iterator_pair_generator
{
typedef std::pair<dummyT,dummyT> Pair;
@ -376,23 +231,33 @@ main()
// Test filter iterator
{
// Using typedefs for filter_gen::type and filter_gen::policies_type
// confused Borland terribly.
// 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*
typedef boost::filter_iterator_generator<one_or_four, dummyT*
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
, dummyT
#endif
>::type filter_iter;
#if defined(__BORLANDC__)
// Borland is choking on accessing the policies_type explicitly
// from the filter_iter.
boost::forward_iterator_test(make_filter_iterator(array, array+N,
one_or_four()),
dummyT(1), dummyT(4));
#else
filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N));
boost::forward_iterator_test(i, dummyT(1), dummyT(4));
#endif
#if !defined(__BORLANDC__)
//
enum { is_forward = boost::is_same<
filter_iter::iterator_category,
std::forward_iterator_tag>::value };
BOOST_STATIC_ASSERT(is_forward);
#endif
// On compilers not supporting partial specialization, we can do more type
// deduction with deque iterators than with pointers... unless the library
@ -433,12 +298,24 @@ main()
// 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::iterator_traits_generator
::value_type<dummyT>
::reference<const dummyT&>
::pointer<const dummyT*>
::iterator_category<std::forward_iterator_tag>
::difference_type<std::ptrdiff_t> > adaptor_type;
#endif
adaptor_type i(forward_iter);
if (0) // don't do this, just make sure it compiles
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
@ -449,10 +326,10 @@ main()
dummyT, const dummyT&, const dummyT*,
std::input_iterator_tag, std::ptrdiff_t> adaptor_type;
adaptor_type i(input_iter);
if (0) // don't do this, just make sure it compiles
int zero = 0;
if (zero) // don't do this, just make sure it compiles
assert((*i).m_x == i->foo());
}
std::cout << "test successful " << std::endl;
return 0;
}

View File

@ -44,6 +44,8 @@
<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>
@ -63,7 +65,7 @@
</ul>
<li>
Specialized Iterator Adaptors
<a name="specialized_adaptors">Specialized Iterator Adaptors</a>
<ul>
<li><a href="indirect_iterator.htm">Indirect Iterator Adaptor</a>
@ -84,9 +86,14 @@
"../../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>
</ul>
<p><b><a href="http://www.boost.org/people/dave_abrahams.htm">Dave
<p><b><a href="file:///c:/boost/site/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
@ -95,11 +102,12 @@
<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="http://www.boost.org/people/jeremy_siek.htm">Jeremy
<b><a href="file:///c:/boost/site/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>, and most of
the documentation.<br>
"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=
@ -123,11 +131,11 @@
<p><tt>iterator_adaptor</tt> is declared like this:
<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;
class ValueOrNamedParams = typename std::iterator_traits&lt;Base&gt;::value_type,
class ReferenceOrNamedParams = <i>...(see below)</i>,
class PointerOrNamedParams = <i>...(see below)</i>,
class CategoryOrNamedParams = typename std::iterator_traits&lt;Base&gt;::iterator_category,
class DistanceOrNamedParams = typename std::iterator_traits&lt;Base&gt;::difference_type&gt;
struct iterator_adaptor;
</pre>
@ -162,7 +170,8 @@ struct iterator_adaptor;
<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>.<br>
"#1">[1]</a>. If the <tt>value_type</tt> you wish to use is an abstract
base class see note <a href="#5">[5]</a>.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseType&gt;::value_type</tt> <a href=
"#2">[2]</a>
@ -197,27 +206,99 @@ struct iterator_adaptor;
<td>The <tt>difference_type</tt> for the resulting iterator.<br>
<b>Default:</b>
<tt>std::iterator_traits&lt;BaseType&gt;::difference_type</tt>
<tr>
<td><tt>NamedParams</tt>
<td>A list of named template parameters generated using the
<a href="#iterator_traits_generator">
<tt>iterator_traits_generator</tt></a> class (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 the <tt>iterator_traits_generator</tt> class.
<blockquote>
<pre>
<a name="iterator_traits_generator">class iterator_traits_generator</a>
{
public:
template &lt;class Value&gt;
struct value_type : public <i>recursive magic</i> { };
template &lt;class Reference&gt;
struct reference : public <i>recursive magic</i> { };
template &lt;class Pointer&gt;
struct pointer : public <i>recursive magic</i> { };
template &lt;class Distance&gt;
struct difference_type : public <i>recursive magic</i> { };
template &lt;class Category&gt;
struct iterator_category : public <i>recursive magic</i> { };
};
</pre>
</blockquote>
The <tt>iterator_traits_generator</tt> is used to create a list of
of template arguments. For example, suppose you want to set the
<tt>Reference</tt> and <tt>Category</tt> parameters, and use the
defaults for the rest. Then you can use the traits generator as
follows:
<blockquote>
<pre>
iterator_traits_generator::reference&lt;foo&gt;::category&lt;std::input_iterator_tag&gt;
</pre>
</blockquote>
This generated type can then be passed into the <tt>iterator_adaptor</tt>
class to replace any of the last five parameters. If you use the traits
generator in the <i>i</i>th parameter position, then the parameters <i>i</i>
through 7 will use the types specified in the generator. 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>
iterator_adaptor&lt;foo_iterator, foo_policies,
iterator_traits_generator
::reference&lt;foo&gt;
::iterator_category&lt;std::input_iterator_tag&gt;
&gt;
</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 iterator adaptor, supplying the core
iterator operations that will determine how your new adaptor class will
behave. The <tt>iterator_adaptor</tt> template defines all of the operators
required of a <a href=
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>. Your <tt>Policies</tt> class must implement three, four, or
seven of the core iterator operations below depending on the iterator
categories you want it to support.<br>
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>Core Iterator Operations</b><br>
<tt>T</tt>: iterator type; <tt>p</tt>: object of type T; <tt>n</tt>: <tt>T::size_type</tt>; <tt>x</tt>: <tt>T::difference_type</tt>; <tt>p1</tt>, <tt>p2</tt>: iterators
<tt>T</tt>: adapted iterator type; <tt>p</tt>: object of type T; <tt>n</tt>: <tt>T::size_type</tt>; <tt>x</tt>: <tt>T::difference_type</tt>; <tt>p1</tt>, <tt>p2</tt>: iterators
</caption>
<tr>
@ -230,13 +311,13 @@ struct iterator_adaptor;
<th>Required for Iterator Categories
<tr>
<td><tt>dereference</tt>
<td><tt>initialize</tt>
<td>returns an element of the iterator's <tt>reference</tt> type
<td><tt>*p</tt>, <tt>p[n]</tt>
<td>optionally modify base iterator during iterator construction
<td rowspan="3"><a href=
<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
@ -245,6 +326,15 @@ struct iterator_adaptor;
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
Access</a>
<tr>
<td><tt>dereference</tt>
<td>returns an element of the iterator's <tt>reference</tt> type
<td><tt>*p</tt>, <tt>p[n]</tt>
<tr>
<td><tt>equal</tt>
@ -324,6 +414,10 @@ struct iterator_adaptor;
<pre>
struct <a name="default_iterator_policies">default_iterator_policies</a>
{
template &lt;class BaseType&gt;
void initialize(BaseType&amp;)
{ }
template &lt;class Reference, class BaseType&gt;
Reference dereference(type&lt;Reference&gt;, const BaseType&amp; x) const
{ return *x; }
@ -360,7 +454,8 @@ struct <a name="default_iterator_policies">default_iterator_policies</a>
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 may achieve the same sort of reusability.
<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=
@ -748,11 +843,24 @@ bool operator==(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
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>.
<hr>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->15
Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" -->
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->12 Jul 2001<!--webbot bot="Timestamp" endspan i-checksum="14985" -->
<p>&copy; Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy,
@ -779,6 +887,5 @@ bool operator==(const iterator_adaptor&lt;B1,P,V1,R1,P1,C,D&gt;&amp;,
<!-- LocalWords: iostream hpp sizeof InputIterator constness ConstIterator
David Abrahams
-->
</body>
</html>

View File

@ -7,6 +7,7 @@
// 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)
@ -153,7 +154,7 @@ input_iterator_test<std::istream_iterator<int>, int, std::ptrdiff_t, int*, int&,
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) && !defined(__SGI_STL_PORT)
#elif defined(BOOST_MSVC_STD_ITERATOR)
non_pointer_test<std::ostream_iterator<int>,
int, void, void, void, std::output_iterator_tag>
ostream_iterator_test;

View File

@ -9,16 +9,29 @@
// 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)
#include <string>
#include <iostream>
using namespace std;
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp> // for main
#include <boost/operators.hpp>
using namespace boost;
#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<
@ -29,7 +42,7 @@ struct test_iter
typedef std::ptrdiff_t Distance;
public:
test_iter(T* i) : _i(i) { }
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; }
@ -43,127 +56,280 @@ public:
return x._i - y._i;
}
protected:
T* _i;
P _i;
};
int
main()
// Iterator operator testing classes
class test_opr_base
{
string array[] = { "apple", "orange", "pear", "peach", "grape", "plum" };
{
test_iter<string,string&,string*> i = array,
ie = array + sizeof(array)/sizeof(string);
protected:
// Test data and types
BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u );
BOOST_STATIC_CONSTANT( std::size_t, scratch_length = 40u );
// Tests for all of the operators added by random_access_iterator_helper
typedef std::string fruit_array_type[ fruit_length ];
typedef char scratch_array_type[ scratch_length ];
// test i++
while (i != ie)
cout << *i++ << " ";
cout << endl;
i = array;
static fruit_array_type fruit;
static scratch_array_type scratch;
// test i--
while (ie != i) {
ie--;
cout << *ie << " ";
}
cout << endl;
ie = array + sizeof(array)/sizeof(string);
}; // test_opr_base
// test i->m
while (i != ie) {
cout << i->size() << " ";
++i;
}
cout << endl;
i = array;
template <typename T, typename R = T&, typename P = T*>
class test_opr
: public test_opr_base
{
typedef test_opr<T, R, P> self_type;
// test i + n
while (i < ie) {
cout << *i << " ";
i = i + 2;
}
cout << endl;
i = array;
public:
// Types
typedef T value_type;
typedef R reference;
typedef P pointer;
// test n + i
while (i < ie) {
cout << *i << " ";
i = ptrdiff_t(2) + i;
}
cout << endl;
i = array;
typedef test_iter<T, R, P> iter_type;
// test i - n
while (ie > i) {
ie = ie - 2;
cout << *ie << " ";
}
cout << endl;
ie = array + sizeof(array)/sizeof(string);
// Test controller
static void master_test( char const name[] );
// test i[n]
for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j)
cout << i[j] << " ";
cout << endl;
}
{
test_iter<string, const string&, const string*> i = array,
ie = array + sizeof(array)/sizeof(string);
private:
// Test data
static iter_type const fruit_begin, fruit_end;
// Tests for all of the operators added by random_access_iterator_helper
// 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 i++
while (i != ie)
cout << *i++ << " ";
cout << endl;
i = array;
}; // test_opr
// test i--
while (ie != i) {
ie--;
cout << *ie << " ";
}
cout << endl;
ie = array + sizeof(array)/sizeof(string);
// test i->m
while (i != ie) {
cout << i->size() << " ";
++i;
}
cout << endl;
i = array;
// Class-static data definitions
test_opr_base::fruit_array_type
test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" };
// test i + n
while (i < ie) {
cout << *i << " ";
i = i + 2;
}
cout << endl;
i = array;
test_opr_base::scratch_array_type
test_opr_base::scratch = "";
// test n + i
while (i < ie) {
cout << *i << " ";
i = ptrdiff_t(2) + i;
}
cout << endl;
i = array;
template <typename T, typename R, typename P>
typename test_opr<T, R, P>::iter_type const
test_opr<T, R, P>::fruit_begin( fruit );
// test i - n
while (ie > i) {
ie = ie - 2;
cout << *ie << " ";
}
cout << endl;
ie = array + sizeof(array)/sizeof(string);
template <typename T, typename R, typename P>
typename test_opr<T, R, P>::iter_type const
test_opr<T, R, P>::fruit_end( fruit + fruit_length );
// test i[n]
for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j)
cout << i[j] << " ";
cout << endl;
}
return 0;
// 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

@ -7,6 +7,7 @@
// 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
@ -30,13 +31,6 @@
# include <limits>
#endif
// A macro for declaring class compile-time constants.
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
# define DECLARE_CLASS_CONST(type, init) static const type init
#else
# define DECLARE_CLASS_CONST(type, init) enum { init }
#endif
// =================================================================================
// template class complement_traits<Number> --
//
@ -53,8 +47,8 @@ template <unsigned size> struct complement; // forward
template <class Number, unsigned size>
struct complement_traits_aux
{
DECLARE_CLASS_CONST(Number, max = complement<size>::template traits<Number>::max);
DECLARE_CLASS_CONST(Number, min = complement<size>::template traits<Number>::min);
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>
@ -67,11 +61,11 @@ struct complement
// indirection through complement_traits_aux neccessary to keep MSVC happy
typedef complement_traits_aux<Number, size - 1> prev;
public:
DECLARE_CLASS_CONST(Number, max =
BOOST_STATIC_CONSTANT(Number, max =
Number(Number(prev::max) << CHAR_BIT)
+ Number(UCHAR_MAX));
DECLARE_CLASS_CONST(Number, min = Number(Number(prev::min) << CHAR_BIT));
BOOST_STATIC_CONSTANT(Number, min = Number(Number(prev::min) << CHAR_BIT));
};
};
@ -85,8 +79,8 @@ template <> struct complement_base<false>
template <class Number>
struct values
{
DECLARE_CLASS_CONST(Number, min = 0);
DECLARE_CLASS_CONST(Number, max = UCHAR_MAX);
BOOST_STATIC_CONSTANT(Number, min = 0);
BOOST_STATIC_CONSTANT(Number, max = UCHAR_MAX);
};
};
@ -95,8 +89,8 @@ template <> struct complement_base<true>
template <class Number>
struct values
{
DECLARE_CLASS_CONST(Number, min = SCHAR_MIN);
DECLARE_CLASS_CONST(Number, max = SCHAR_MAX);
BOOST_STATIC_CONSTANT(Number, min = SCHAR_MIN);
BOOST_STATIC_CONSTANT(Number, max = SCHAR_MAX);
};
};
@ -107,10 +101,10 @@ struct complement<1>
template <class Number>
struct traits
{
DECLARE_CLASS_CONST(bool, is_signed = boost::detail::is_signed<Number>::value);
DECLARE_CLASS_CONST(Number, min =
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);
DECLARE_CLASS_CONST(Number, max =
BOOST_STATIC_CONSTANT(Number, max =
complement_base<is_signed>::template values<Number>::max);
};
};
@ -121,8 +115,8 @@ struct complement<1>
template <class Number>
struct complement_traits
{
DECLARE_CLASS_CONST(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max));
DECLARE_CLASS_CONST(Number, min = (complement_traits_aux<Number, sizeof(Number)>::min));
BOOST_STATIC_CONSTANT(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max));
BOOST_STATIC_CONSTANT(Number, min = (complement_traits_aux<Number, sizeof(Number)>::min));
};
// =================================================================================
@ -151,9 +145,9 @@ template <> struct stream_as<signed char> {
typedef unsigned char t1; typedef unsigned t2;
};
#if defined(BOOST_MSVC) // No intmax streaming built-in
#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in
// On this platform, __int64 and __uint64 get streamed as strings
// 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;
@ -174,7 +168,7 @@ template <class T> struct promote
}
};
#if defined(BOOST_MSVC) // No intmax streaming built-in
#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.

File diff suppressed because it is too large Load Diff

View File

@ -8,18 +8,26 @@
// See http://www.boost.org for most recent version including documentation.
// Revision History
// 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)
// 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
#include <boost/operators.hpp>
#include <cassert>
#include <iostream>
#include <boost/min_rand.hpp>
#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
@ -28,14 +36,18 @@ namespace
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
// The use of operators<> here tended to obscure
// interactions with certain compiler bugs
template <class T>
class Wrapped1 : boost::operators<Wrapped1<T> >
class Wrapped1
: boost::operators<Wrapped1<T> >
, boost::shiftable<Wrapped1<T> >
{
public:
explicit Wrapped1( T v = T() ) : _value(v) {}
@ -60,6 +72,10 @@ namespace
{ _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; }
@ -70,9 +86,11 @@ namespace
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>
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) {}
@ -97,6 +115,10 @@ namespace
{ _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; }
@ -111,6 +133,8 @@ namespace
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;
@ -118,203 +142,268 @@ namespace
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(); }
// 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;
template <class X1, class Y1, class X2, class Y2>
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
assert(true_value(y1) == true_value(y2));
assert(true_value(x1) == true_value(x2));
BOOST_TEST( true_value(y1) == true_value(y2) );
BOOST_TEST( true_value(x1) == true_value(x2) );
}
template <class X1, class Y1, class X2, class Y2>
void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
assert((x1 < y1) == (x2 < y2));
assert((x1 <= y1) == (x2 <= y2));
assert((x1 >= y1) == (x2 >= y2));
assert((x1 > y1) == (x2 > y2));
BOOST_TEST( (x1 < y1) == (x2 < y2) );
BOOST_TEST( (x1 <= y1) == (x2 <= y2) );
BOOST_TEST( (x1 >= y1) == (x2 >= y2) );
BOOST_TEST( (x1 > y1) == (x2 > y2) );
}
template <class X1, class Y1, class X2, class Y2>
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);
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)
{
assert((x1 == y1) == (x2 == y2));
assert((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_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);
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)
{
assert((x1 * y1).value() == (x2 * 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);
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)
{
assert((x1 + y1).value() == (x2 + 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);
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);
assert((x1 - y1).value() == x2 - 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_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check(x1, y1, x2, y2);
if (y2 != 0)
assert((x1 / y1).value() == x2 / 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(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
sanity_check(x1, y1, x2, y2);
if (y2 != 0)
assert((x1 / y1).value() == x2 / 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_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
{
assert((x1 ^ y1).value() == (x2 ^ 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);
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)
{
assert((x1 & y1).value() == (x2 & 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);
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)
{
assert((x1 | y1).value() == (x2 | 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);
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);
assert(x1++.value() == x2++);
assert(x1.value() == 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);
assert(x1--.value() == x2--);
assert(x1.value() == 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_incrementable(x1, x2);
test_decrementable(x1, x2);
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 Big, class Small>
struct tester
{
void operator()(boost::min_rand& randomizer) const
void operator()(boost::minstd_rand& randomizer) const
{
Big b1 = Big(randomizer());
Big b2 = Big(randomizer());
Small s = Small(randomizer());
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);
test_all( Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2 );
test_all( Wrapped2<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> >
: 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; }
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
@ -340,20 +429,25 @@ template Wrapped2<unsigned long, unsigned char>;
template Wrapped2<unsigned long, unsigned long>;
#endif
#ifdef NDEBUG
#error This program is pointless when NDEBUG disables assert()!
#endif
#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) )
int main()
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::min_rand r;
boost::minstd_rand r;
tester<long, int>()(r);
tester<long, signed char>()(r);
tester<long, long>()(r);
@ -367,115 +461,197 @@ int main()
tester<unsigned int, unsigned char>()(r);
}
cout << "Did random tester loop." << endl;
MyInt i1(1);
MyInt i2(2);
MyInt i;
assert( i1.value() == 1 );
assert( i2.value() == 2 );
assert( i.value() == 0 );
BOOST_TEST( i1.value() == 1 );
BOOST_TEST( i2.value() == 2 );
BOOST_TEST( i.value() == 0 );
i = i2;
assert( i.value() == 2 );
assert( i2 == i );
assert( i1 != i2 );
assert( i1 < i2 );
assert( i1 <= i2 );
assert( i <= i2 );
assert( i2 > i1 );
assert( i2 >= i1 );
assert( i2 >= i );
cout << "Created MyInt objects.\n";
i = i1 + i2; assert( i.value() == 3 );
i = i + i2; assert( i.value() == 5 );
i = i - i1; assert( i.value() == 4 );
i = i * i2; assert( i.value() == 8 );
i = i / i2; assert( i.value() == 4 );
i = i % (i - i1); assert( i.value() == 1 );
i = i2 + i2; assert( i.value() == 4 );
i = i1 | i2 | i; assert( i.value() == 7 );
i = i & i2; assert( i.value() == 2 );
i = i + i1; assert( i.value() == 3 );
i = i ^ i1; assert( i.value() == 2 );
i = (i+i1)*(i2|i1); assert( i.value() == 9 );
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;
assert( j1.value() == 1 );
assert( j2.value() == 2 );
assert( j.value() == 0 );
BOOST_TEST( j1.value() == 1 );
BOOST_TEST( j2.value() == 2 );
BOOST_TEST( j.value() == 0 );
j = j2;
assert( j.value() == 2 );
assert( j2 == j );
assert( 2 == j );
assert( j2 == 2 );
assert( j == j2 );
assert( j1 != j2 );
assert( j1 != 2 );
assert( 1 != j2 );
assert( j1 < j2 );
assert( 1 < j2 );
assert( j1 < 2 );
assert( j1 <= j2 );
assert( 1 <= j2 );
assert( j1 <= j );
assert( j <= j2 );
assert( 2 <= j2 );
assert( j <= 2 );
assert( j2 > j1 );
assert( 2 > j1 );
assert( j2 > 1 );
assert( j2 >= j1 );
assert( 2 >= j1 );
assert( j2 >= 1 );
assert( j2 >= j );
assert( 2 >= j );
assert( j2 >= 2 );
cout << "Created MyLong objects.\n";
assert( (j1 + 2) == 3 );
assert( (1 + j2) == 3 );
j = j1 + j2; assert( j.value() == 3 );
PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) );
assert( (j + 2) == 5 );
assert( (3 + j2) == 5 );
j = j + j2; assert( j.value() == 5 );
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) );
assert( (j - 1) == 4 );
j = j - j1; assert( j.value() == 4 );
BOOST_TEST( (j + 2) == 5 );
BOOST_TEST( (3 + j2) == 5 );
PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) );
assert( (j * 2) == 8 );
assert( (4 * j2) == 8 );
j = j * j2; assert( j.value() == 8 );
BOOST_TEST( (j - 1) == 4 );
PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) );
assert( (j / 2) == 4 );
j = j / j2; assert( j.value() == 4 );
BOOST_TEST( (j * 2) == 8 );
BOOST_TEST( (4 * j2) == 8 );
PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) );
assert( (j % 3) == 1 );
j = j % (j - j1); assert( j.value() == 1 );
BOOST_TEST( (j / 2) == 4 );
PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) );
j = j2 + j2; assert( j.value() == 4 );
BOOST_TEST( (j % 3) == 1 );
PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) );
assert( (1 | j2 | j) == 7 );
assert( (j1 | 2 | j) == 7 );
assert( (j1 | j2 | 4) == 7 );
j = j1 | j2 | j; assert( j.value() == 7 );
PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) );
assert( (7 & j2) == 2 );
assert( (j & 2) == 2 );
j = j & j2; assert( j.value() == 2 );
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) );
j = j | j1; assert( j.value() == 3 );
BOOST_TEST( (7 & j2) == 2 );
BOOST_TEST( (j & 2) == 2 );
PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) );
assert( (3 ^ j1) == 2 );
assert( (j ^ 1) == 2 );
j = j ^ j1; assert( j.value() == 2 );
PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) );
j = (j+j1)*(j2|j1); assert( j.value() == 9 );
BOOST_TEST( (3 ^ j1) == 2 );
BOOST_TEST( (j ^ 1) == 2 );
PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) );
std::cout << "0 errors detected\n";
return 0;
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";
return boost::exit_success;
}

View File

@ -371,7 +371,7 @@ Betty
</pre>
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->10 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" --></p>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --></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;

View File

@ -312,8 +312,7 @@ simply use <tt>reverse_iterator_generator</tt> twice!<br><br>
<p>Revised
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->15
Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" -->
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" -->
<p>&copy; Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell

View File

@ -23,7 +23,9 @@
<TT>tie</TT>
</H1>
<P>
<h3>
[tie has been deprecated.&nbsp; Its functionality is supplied by the Boost
Tuples Library.]</h3>
<PRE>
template &lt;class A, class B&gt;
tied&lt;A,B&gt; tie(A&amp; a, B&amp; b);
@ -64,7 +66,7 @@ pair of iterators is assigned to the iterator variables <TT>i</TT> and
<P>
Here is another example that uses <TT>tie()</TT> for handling operations with <a
href="http://www.sgi.com/Technology/STL/set.html"><TT>std::set</TT></a>.
href="http://www.sgi.com/tech/stl/set.html"><TT>std::set</TT></a>.
<P>
<PRE>
@ -124,7 +126,7 @@ The output is:
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2000</TD><TD>
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>,
<A HREF=file:///c:/boost/site/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>

View File

@ -71,8 +71,11 @@ public:
<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.
<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>
@ -80,16 +83,18 @@ numbers, multiplying each of them by 2 when they are dereferenced.
#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 std::binder1st&lt; std::multiplies&lt;int&gt; &gt; Function;
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, std::bind1st(std::multiplies&lt;int&gt;(), 2)),
i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies&lt;int&gt;(), 2));
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)
@ -111,14 +116,17 @@ The output from this part is:
</TR>
<TR>
<TD><a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a></TD>
<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.</TD>
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>
@ -133,7 +141,7 @@ its argument.</TD>
The transform iterator adaptor (the type
<tt>transform_iterator_generator<...>::type</tt>) is a model of <a
href="www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a><a href="#1">[1]</a>.
href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a><a href="#1">[1]</a>.
<h3>Members</h3>
@ -173,8 +181,8 @@ 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, std::bind1st(std::plus<int>(), 4)),
boost::make_transform_iterator(x + N, std::bind1st(std::plus<int>(), 4)),
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;
@ -203,7 +211,7 @@ iterator always returns by-value.
<hr>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->10 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" --></p>
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->29 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14896" --></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;

View File

@ -9,6 +9,38 @@
#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*[])
{
@ -20,11 +52,11 @@ main(int, char*[])
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
const int N = sizeof(x)/sizeof(int);
typedef std::binder1st< std::multiplies<int> > Function;
typedef boost::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 + N, std::bind1st(std::multiplies<int>(), 2));
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)
@ -33,8 +65,8 @@ main(int, char*[])
std::cout << "adding 4 to each element in the array:" << std::endl;
std::copy(boost::make_transform_iterator(x, std::bind1st(std::plus<int>(), 4)),
boost::make_transform_iterator(x + N, std::bind1st(std::plus<int>(), 4)),
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;

View File

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

@ -16,10 +16,50 @@
<h2>Contents</h2>
<ul>
<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="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
@ -91,9 +131,11 @@ 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>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
-->28 September, 2000<!--webbot bot="Timestamp" endspan i-checksum="39343"
-->22 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13960"
-->
</p>
<p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and