forked from boostorg/utility
Compare commits
57 Commits
svn-branch
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
d9c9685be2 | |||
31d0908b74 | |||
32c77599f4 | |||
812ebf3562 | |||
37f476013d | |||
9f3104166f | |||
64cc0daf34 | |||
d5d64df124 | |||
0edcfcd5c1 | |||
50ba2d419a | |||
ff3a77ca5a | |||
4eaed6c23d | |||
4d0dd46471 | |||
9c2549bd00 | |||
b7c8e0c17f | |||
dd3cfe1837 | |||
43f525298e | |||
1bb1898ab9 | |||
9578f24be9 | |||
46fae3aed2 | |||
e35f91a70a | |||
851052fcca | |||
5ef81b2952 | |||
ef2851c053 | |||
0b4387cff5 | |||
a40cf11fbf | |||
5c495cd223 | |||
cf1296dff8 | |||
d6d88db6e8 | |||
85c2a35257 | |||
836d8b1c64 | |||
98d8c8ab71 | |||
db45013339 | |||
a55c37e7f6 | |||
46a270fcca | |||
967856518e | |||
7f93e739fe | |||
2cd1422514 | |||
feb370b201 | |||
d1b34e64d8 | |||
b9a1eead40 | |||
1e4bfac98c | |||
3bb504fbf3 | |||
5029791c90 | |||
a1a68f0970 | |||
f8543d79eb | |||
f353415136 | |||
26240403b0 | |||
3a39729b58 | |||
096c961d9a | |||
01fe04a6a2 | |||
7ea4014993 | |||
d50b374f88 | |||
27dfb25570 | |||
b5ed77985e | |||
61243bd15f | |||
368b94d804 |
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
||||
|
||||
|
||||
|
@ -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&</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 © 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>
|
||||
|
@ -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&<br>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
T&<br>
|
||||
(return value)</p>
|
||||
</td>
|
||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::const_reference</code></p>
|
||||
@ -91,7 +92,8 @@ solve the reference to reference problem).</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" width="17%"><p align="center">const T&<br>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
T&<br>
|
||||
(function parameter)</p>
|
||||
</td>
|
||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::param_type</code></p>
|
||||
@ -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 "myclass", and call_traits
|
||||
can not be used with reference or array types.</p>
|
||||
the same way as the entry for "myclass", and
|
||||
call_traits can not be used with reference or array types.</p>
|
||||
|
||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
||||
<tr>
|
||||
@ -388,7 +390,8 @@ can not be used with reference or array types.</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int&</p>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</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&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int&</p>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">int&</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&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int&</p>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int&</p>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int&</p>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</p>
|
||||
</td>
|
||||
<td valign="top" width="17%"><p align="center">const int&</p>
|
||||
<td valign="top" width="17%"><p align="center">const
|
||||
int&</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 <class T>
|
||||
struct contained
|
||||
@ -523,14 +531,14 @@ problem):</h4>
|
||||
|
||||
<pre>template <class Operation>
|
||||
class binder1st :
|
||||
public unary_function<Operation::second_argument_type, Operation::result_type>
|
||||
public unary_function<typename Operation::second_argument_type, typename Operation::result_type>
|
||||
{
|
||||
protected:
|
||||
Operation op;
|
||||
Operation::first_argument_type value;
|
||||
typename Operation::first_argument_type value;
|
||||
public:
|
||||
binder1st(const Operation& x, const Operation::first_argument_type& y);
|
||||
Operation::result_type operator()(const Operation::second_argument_type& x) const;
|
||||
binder1st(const Operation& x, const typename Operation::first_argument_type& y);
|
||||
typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const;
|
||||
}; </pre>
|
||||
|
||||
<p>Now consider what happens in the relatively common case that
|
||||
@ -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<Operation::second_argument_type>::param_type x) const;</pre>
|
||||
<pre>typename Operation::result_type operator()(typename call_traits<typename Operation::second_argument_type>::param_type x) const;</pre>
|
||||
|
||||
<p>Now in the case that <code>Operation::second_argument_type</code>
|
||||
is a reference type, the argument is passed as a reference, and
|
||||
@ -575,9 +583,9 @@ std::pair<
|
||||
degraded to pointers if the deduced types are arrays, similar
|
||||
situations occur in the standard binders and adapters: in
|
||||
principle in any function that "wraps" a temporary
|
||||
whose type is deduced. Note that the function arguments to make_pair
|
||||
are not expressed in terms of call_traits: doing so would prevent
|
||||
template argument deduction from functioning.</p>
|
||||
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 "a
|
||||
reference to a reference is a reference" (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
|
||||
"a reference to a reference is a reference" (issue #106,
|
||||
submitted by Bjarne Stroustrup), call_traits<T>::value_type
|
||||
and call_traits<T>::param_type both provide the same effect
|
||||
as that proposal, without the need for a language change (in
|
||||
@ -687,11 +695,11 @@ struct A
|
||||
void foo(T t);
|
||||
};</pre>
|
||||
|
||||
<p><font face="Times New Roman">In this case if we instantiate A<int[2]>
|
||||
then the declared type of the parameter passed to member function
|
||||
foo is int[2], but it's actual type is const int*, if we try to
|
||||
use the type T within the function body, then there is a strong
|
||||
likelyhood that our code will not compile:</font></p>
|
||||
<p><font face="Times New Roman">In this case if we instantiate
|
||||
A<int[2]> then the declared type of the parameter passed to
|
||||
member function foo is int[2], but it's actual type is const int*,
|
||||
if we try to use the type T within the function body, then there
|
||||
is a strong likelyhood that our code will not compile:</font></p>
|
||||
|
||||
<pre>template <class T>
|
||||
void A<T>::foo(T t)
|
||||
@ -706,13 +714,13 @@ declared type:</p>
|
||||
<pre>template <class T>
|
||||
struct A
|
||||
{
|
||||
void foo(call_traits<T>::value_type t);
|
||||
void foo(typename call_traits<T>::value_type t);
|
||||
};
|
||||
|
||||
template <class T>
|
||||
void A<T>::foo(call_traits<T>::value_type t)
|
||||
void A<T>::foo(typename call_traits<T>::value_type t)
|
||||
{
|
||||
call_traits<T>::value_type dup(t); // OK even if T is an array type.
|
||||
typename call_traits<T>::value_type dup(t); // OK even if T is an array type.
|
||||
}</pre>
|
||||
|
||||
<p>For value_type (return by value), again only a pointer may be
|
||||
@ -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>
|
||||
|
||||
|
@ -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
31
checked_delete_test.cpp
Normal 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
|
@ -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
|
||||
<<a href="../../boost/detail/call_traits.hpp">boost/compressed_pair.hpp</a>></h2>
|
||||
<<a href="../../boost/detail/compressed_pair.hpp">boost/compressed_pair.hpp</a>></h2>
|
||||
|
||||
<p>All of the contents of <boost/compressed_pair.hpp> 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& operator=(const compressed_pair&);
|
||||
|
||||
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 "do
|
||||
nothing" 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> </p>
|
||||
</body>
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -282,7 +282,7 @@ template <class Incrementable>
|
||||
struct counting_iterator_traits
|
||||
{
|
||||
if (numeric_limits<Incrementable>::is_specialized) {
|
||||
if (!numeric_limits<Incrementable>::is_integral)
|
||||
if (!numeric_limits<Incrementable>::is_integer)
|
||||
COMPILE_TIME_ERROR;
|
||||
|
||||
if (!numeric_limits<Incrementable>::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 "as is"
|
||||
|
@ -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 "as is"
|
||||
|
41
fun_out_iter_example.cpp
Normal file
41
fun_out_iter_example.cpp
Normal 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;
|
||||
}
|
169
function_output_iterator.htm
Normal file
169
function_output_iterator.htm
Normal 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 <class UnaryFunction>
|
||||
class function_output_iterator;
|
||||
|
||||
template <class UnaryFunction>
|
||||
function_output_iterator<UnaryFunction>
|
||||
make_function_output_iterator(const UnaryFunction& 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 <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;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2><a name="function_output_iterator">The Function Output Iterator Class</a></h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class UnaryFunction>
|
||||
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 <class UnaryFunction>
|
||||
function_output_iterator<UnaryFunction>
|
||||
make_function_output_iterator(const UnaryFunction& f = UnaryFunction())
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>© 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>
|
@ -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
|
||||
|
@ -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 -------------------------------------------------------//
|
||||
|
@ -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>© Copyright Jeremy Siek and David Abrahams 2001. Permission to
|
||||
|
@ -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
151
indirect_iterator_test.cpp
Normal 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
61
iter_traits_gen_test.cpp
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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 <class Base, class Policies,
|
||||
class Value = typename std::iterator_traits<Base>::value_type,
|
||||
class Reference = <i>...(see below)</i>,
|
||||
class Pointer = <i>...(see below)</i>,
|
||||
class Category = typename std::iterator_traits<Base>::iterator_category,
|
||||
class Distance = typename std::iterator_traits<Base>::difference_type>
|
||||
class ValueOrNamedParams = typename std::iterator_traits<Base>::value_type,
|
||||
class ReferenceOrNamedParams = <i>...(see below)</i>,
|
||||
class PointerOrNamedParams = <i>...(see below)</i>,
|
||||
class CategoryOrNamedParams = typename std::iterator_traits<Base>::iterator_category,
|
||||
class DistanceOrNamedParams = typename std::iterator_traits<Base>::difference_type>
|
||||
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<BaseType>::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<BaseType>::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 <class Value>
|
||||
struct value_type : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Reference>
|
||||
struct reference : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Pointer>
|
||||
struct pointer : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Distance>
|
||||
struct difference_type : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Category>
|
||||
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<foo>::category<std::input_iterator_tag>
|
||||
</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<foo_iterator, foo_policies,
|
||||
iterator_traits_generator
|
||||
::reference<foo>
|
||||
::iterator_category<std::input_iterator_tag>
|
||||
>
|
||||
</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 <class BaseType>
|
||||
void initialize(BaseType&)
|
||||
{ }
|
||||
|
||||
template <class Reference, class BaseType>
|
||||
Reference dereference(type<Reference>, const BaseType& 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<B1,P,V1,R1,P1,C,D>&,
|
||||
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>© Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy,
|
||||
@ -779,6 +887,5 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
|
||||
<!-- LocalWords: iostream hpp sizeof InputIterator constness ConstIterator
|
||||
David Abrahams
|
||||
-->
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
}
|
||||
|
@ -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.
|
||||
|
1563
operators.htm
1563
operators.htm
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
@ -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 "as is"
|
||||
|
@ -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>© Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell
|
||||
|
8
tie.html
8
tie.html
@ -23,7 +23,9 @@
|
||||
<TT>tie</TT>
|
||||
</H1>
|
||||
|
||||
<P>
|
||||
<h3>
|
||||
[tie has been deprecated. Its functionality is supplied by the Boost
|
||||
Tuples Library.]</h3>
|
||||
<PRE>
|
||||
template <class A, class B>
|
||||
tied<A,B> tie(A& a, B& 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 © 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>
|
||||
|
@ -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 <iostream>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
// 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< 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 + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2));
|
||||
doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)),
|
||||
i_end(x + sizeof(x)/sizeof(int), boost::bind1st(std::multiplies<int>(), 2));
|
||||
|
||||
std::cout << "multiplying the array by 2:" << 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 "as is"
|
||||
|
@ -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;
|
||||
|
||||
|
54
transform_iterator_test.cpp
Normal file
54
transform_iterator_test.cpp
Normal 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;
|
||||
}
|
44
utility.htm
44
utility.htm
@ -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. 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. They issue an appropriate
|
||||
compiler error diagnostic if that requirement is not met. A typical
|
||||
implementation is shown; other implementations may vary:</p>
|
||||
|
||||
<pre> template< typename T >
|
||||
inline void checked_delete(T const volatile * x)
|
||||
{
|
||||
BOOST_STATIC_ASSERT( sizeof(T) ); // assert type complete at point
|
||||
// of instantiation
|
||||
delete x;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
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 [expr.delete]
|
||||
5.3.5 paragraph. No diagnostic is required. 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. Dave Abrahams notes
|
||||
concern about the effect on compiler optimization of adding (even trivial inline)
|
||||
destructor declarations. He says "Probably this concern is misplaced, because
|
||||
noncopyable will be used mostly for classes which own resources and thus have non-trivial destruction semantics."</p>
|
||||
<h2>Function template tie()</h2>
|
||||
<p>See <a href="tie.html">separate documentation</a>.</p>
|
||||
<hr>
|
||||
<p>Revised <!--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
|
||||
|
Reference in New Issue
Block a user