mirror of
https://github.com/boostorg/utility.git
synced 2025-10-07 14:30:55 +02:00
Compare commits
51 Commits
svn-branch
...
boost-1.23
Author | SHA1 | Date | |
---|---|---|---|
|
e41b8607ae | ||
|
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>
|
</UL>
|
||||||
|
|
||||||
<h3>See also</h3>
|
<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
|
and
|
||||||
<A href="./CopyConstructible.html">CopyConstructible</A>
|
<A href="./CopyConstructible.html">CopyConstructible</A>
|
||||||
|
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
-- purpose. It is provided "as is" without express or implied warranty.
|
-- purpose. It is provided "as is" without express or implied warranty.
|
||||||
-->
|
-->
|
||||||
<Head>
|
<Head>
|
||||||
<Title>CopyConstructible</Title>
|
<Title>Copy Constructible</Title>
|
||||||
</HEAD>
|
</HEAD>
|
||||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
|
||||||
ALINK="#ff0000">
|
ALINK="#ff0000">
|
||||||
@@ -19,10 +19,10 @@
|
|||||||
ALT="C++ Boost" width="277" height="86">
|
ALT="C++ Boost" width="277" height="86">
|
||||||
<!--end header-->
|
<!--end header-->
|
||||||
<BR Clear>
|
<BR Clear>
|
||||||
<H1>CopyConstructible</H1>
|
<H1>Copy Constructible</H1>
|
||||||
|
|
||||||
<h3>Description</h3>
|
<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.
|
type.
|
||||||
|
|
||||||
<h3>Notation</h3>
|
<h3>Notation</h3>
|
||||||
@@ -32,7 +32,7 @@ type.
|
|||||||
<tt>T</tt>
|
<tt>T</tt>
|
||||||
</TD>
|
</TD>
|
||||||
<TD VAlign=top>
|
<TD VAlign=top>
|
||||||
is type that is a model of CopyConstructible
|
is type that is a model of Copy Constructible
|
||||||
</TD>
|
</TD>
|
||||||
</TR>
|
</TR>
|
||||||
|
|
||||||
@@ -194,9 +194,9 @@ denotes the address of <tt>u</tt>
|
|||||||
|
|
||||||
<h3>See also</h3>
|
<h3>See also</h3>
|
||||||
<A
|
<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
|
and
|
||||||
<A href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</A>
|
<A hrefa="./Assignable.html">Assignable</A>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
<HR>
|
<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
|
a <i>strict weak ordering</i> is stricter, and the definition of a
|
||||||
<i>total ordering</i> is stricter still.
|
<i>total ordering</i> is stricter still.
|
||||||
<h3>See also</h3>
|
<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>
|
<H2>
|
||||||
<A NAME="concept:MultiPassInputIterator"></A>
|
<A NAME="concept:MultiPassInputIterator"></A>
|
||||||
MultiPassInputIterator
|
Multi-Pass Input Iterator
|
||||||
</H2>
|
</H2>
|
||||||
|
|
||||||
This concept is a refinement of <a
|
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
|
adding the requirements that the iterator can be used to make multiple
|
||||||
passes through a range, and that if <TT>it1 == it2</TT> and
|
passes through a range, and that if <TT>it1 == it2</TT> and
|
||||||
<TT>it1</TT> is dereferenceable then <TT>++it1 == ++it2</TT>. The
|
<TT>it1</TT> is dereferenceable then <TT>++it1 == ++it2</TT>. The
|
||||||
MultiPassInputIterator is very similar to the <a
|
Multi-Pass Input Iterator is very similar to the <a
|
||||||
href="http://www.sgi.com/Technology/STL/ForwardIterator.hmtl">ForwardIterator</a>. The
|
href="http://www.sgi.com/tech/stl/ForwardIterator.hmtl">Forward Iterator</a>. The
|
||||||
only difference is that a <a
|
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
|
requires the <TT>reference</TT> type to be <TT>value_type&</TT>, whereas
|
||||||
MultiPassInputIterator is like <a
|
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
|
in that the <TT>reference</TT> type merely has to be convertible to
|
||||||
<TT>value_type</TT>.
|
<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:
|
comments by Valentin Bonnard:
|
||||||
|
|
||||||
<p> I think that introducing MultiPassInputIterator isn't the right
|
<p> I think that introducing Multi-Pass Input Iterator isn't the right
|
||||||
solution. Do you also want to define MultiPassBidirectionnalIterator
|
solution. Do you also want to define Multi-Pass Bidirectionnal Iterator
|
||||||
and MultiPassRandomAccessIterator ? I don't, definitly. It only
|
and Multi-Pass Random Access Iterator ? I don't, definitly. It only
|
||||||
confuses the issue. The problem lies into the existing hierarchy of
|
confuses the issue. The problem lies into the existing hierarchy of
|
||||||
iterators, which mixes movabillity, modifiabillity and lvalue-ness,
|
iterators, which mixes movabillity, modifiabillity and lvalue-ness,
|
||||||
and these are clearly independant.
|
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
|
movabillity and shouldn't be used to mean anything else. In a
|
||||||
completly orthogonal way, iterators can be immutable, mutable, or
|
completly orthogonal way, iterators can be immutable, mutable, or
|
||||||
neither. Lvalueness of iterators is also orthogonal with
|
neither. Lvalueness of iterators is also orthogonal with
|
||||||
immutabillity. With these clean concepts, your MultiPassInputIterator
|
immutabillity. With these clean concepts, your Multi-Pass Input Iterator
|
||||||
is just called a ForwardIterator.
|
is just called a Forward Iterator.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Other translations are:<br>
|
Other translations are:<br>
|
||||||
std::ForwardIterator -> ForwardIterator & LvalueIterator<br>
|
std::Forward Iterator -> ForwardIterator & Lvalue Iterator<br>
|
||||||
std::BidirectionnalIterator -> BidirectionnalIterator & LvalueIterator<br>
|
std::Bidirectionnal Iterator -> Bidirectionnal Iterator & Lvalue Iterator<br>
|
||||||
std::RandomAccessIterator -> RandomAccessIterator & LvalueIterator<br>
|
std::Random Access Iterator -> Random Access Iterator & Lvalue Iterator<br>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Note that in practice the only operation not allowed on my
|
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.
|
<tt>&*it</tt>. I think that <tt>&*</tt> is rarely needed in generic code.
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
@@ -75,9 +75,9 @@ reply by Jeremy Siek:
|
|||||||
<p>
|
<p>
|
||||||
The above analysis by Valentin is right on. Of course, there is
|
The above analysis by Valentin is right on. Of course, there is
|
||||||
the problem with backward compatibility. The current STL implementations
|
the problem with backward compatibility. The current STL implementations
|
||||||
are based on the old definition of ForwardIterator. The right course
|
are based on the old definition of Forward Iterator. The right course
|
||||||
of action is to get ForwardIterator, etc. changed in the C++ standard.
|
of action is to get Forward Iterator, etc. changed in the C++ standard.
|
||||||
Once that is done we can drop MultiPassInputIterator.
|
Once that is done we can drop Multi-Pass Input Iterator.
|
||||||
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
content="text/html; charset=iso-8859-1">
|
content="text/html; charset=iso-8859-1">
|
||||||
<meta name="Template"
|
<meta name="Template"
|
||||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
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>
|
<title>Call Traits</title>
|
||||||
</head>
|
</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
|
using call_traits: the call_traits defined types will always be
|
||||||
the same as the existing practice in this case. In addition if
|
the same as the existing practice in this case. In addition if
|
||||||
only member templates and not partial template specialisation is
|
only member templates and not partial template specialisation is
|
||||||
support by the compiler (for example Visual C++ 6) then call_traits
|
support by the compiler (for example Visual C++ 6) then
|
||||||
can not be used with array types (although it can be used to
|
call_traits can not be used with array types (although it can be
|
||||||
solve the reference to reference problem).</p>
|
used to solve the reference to reference problem).</p>
|
||||||
|
|
||||||
<table border="0" cellpadding="7" cellspacing="1" width="797">
|
<table border="0" cellpadding="7" cellspacing="1" width="797">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -79,7 +79,8 @@ solve the reference to reference problem).</p>
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<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>
|
(return value)</p>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::const_reference</code></p>
|
<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>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<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>
|
(function parameter)</p>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top" width="35%"><p align="center"><code>call_traits<T>::param_type</code></p>
|
<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
|
<p>The following table shows the effect that call_traits has on
|
||||||
various types, the table assumes that the compiler supports
|
various types, the table assumes that the compiler supports
|
||||||
partial specialization: if it doesn't then all types behave in
|
partial specialization: if it doesn't then all types behave in
|
||||||
the same way as the entry for "myclass", and call_traits
|
the same way as the entry for "myclass", and
|
||||||
can not be used with reference or array types.</p>
|
call_traits can not be used with reference or array types.</p>
|
||||||
|
|
||||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
<table border="0" cellpadding="7" cellspacing="1" width="766">
|
||||||
<tr>
|
<tr>
|
||||||
@@ -388,7 +390,8 @@ can not be used with reference or array types.</p>
|
|||||||
</td>
|
</td>
|
||||||
<td valign="top" width="17%"><p align="center">int&</p>
|
<td valign="top" width="17%"><p align="center">int&</p>
|
||||||
</td>
|
</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>
|
||||||
<td valign="top" width="17%"><p align="center">int const</p>
|
<td valign="top" width="17%"><p align="center">int const</p>
|
||||||
</td>
|
</td>
|
||||||
@@ -420,7 +423,8 @@ can not be used with reference or array types.</p>
|
|||||||
</td>
|
</td>
|
||||||
<td valign="top" width="17%"><p align="center">int&</p>
|
<td valign="top" width="17%"><p align="center">int&</p>
|
||||||
</td>
|
</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>
|
||||||
<td valign="top" width="17%"><p align="center">int&</p>
|
<td valign="top" width="17%"><p align="center">int&</p>
|
||||||
</td>
|
</td>
|
||||||
@@ -432,13 +436,17 @@ can not be used with reference or array types.</p>
|
|||||||
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
<td valign="top" width="17%" bgcolor="#C0C0C0"><p
|
||||||
align="center">const int&</p>
|
align="center">const int&</p>
|
||||||
</td>
|
</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>
|
||||||
<td valign="top" width="17%"><p align="center">const int&</p>
|
<td valign="top" width="17%"><p align="center">const
|
||||||
|
int&</p>
|
||||||
</td>
|
</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>
|
||||||
<td valign="top" width="17%"><p align="center">const int&</p>
|
<td valign="top" width="17%"><p align="center">const
|
||||||
|
int&</p>
|
||||||
</td>
|
</td>
|
||||||
<td valign="top" width="17%"><p align="center">All
|
<td valign="top" width="17%"><p align="center">All
|
||||||
constant-references.</p>
|
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
|
<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>
|
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
|
file), the aim is to illustrate how each of the available
|
||||||
typedefs may be used:</p>
|
call_traits typedefs may be used:</p>
|
||||||
|
|
||||||
<pre>template <class T>
|
<pre>template <class T>
|
||||||
struct contained
|
struct contained
|
||||||
@@ -523,14 +531,14 @@ problem):</h4>
|
|||||||
|
|
||||||
<pre>template <class Operation>
|
<pre>template <class Operation>
|
||||||
class binder1st :
|
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:
|
protected:
|
||||||
Operation op;
|
Operation op;
|
||||||
Operation::first_argument_type value;
|
typename Operation::first_argument_type value;
|
||||||
public:
|
public:
|
||||||
binder1st(const Operation& x, const Operation::first_argument_type& y);
|
binder1st(const Operation& x, const typename Operation::first_argument_type& y);
|
||||||
Operation::result_type operator()(const Operation::second_argument_type& x) const;
|
typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const;
|
||||||
}; </pre>
|
}; </pre>
|
||||||
|
|
||||||
<p>Now consider what happens in the relatively common case that
|
<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>
|
currently legal. The solution here is to modify <code>operator()</code>
|
||||||
to use call_traits:</p>
|
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>
|
<p>Now in the case that <code>Operation::second_argument_type</code>
|
||||||
is a reference type, the argument is passed as a reference, and
|
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
|
degraded to pointers if the deduced types are arrays, similar
|
||||||
situations occur in the standard binders and adapters: in
|
situations occur in the standard binders and adapters: in
|
||||||
principle in any function that "wraps" a temporary
|
principle in any function that "wraps" a temporary
|
||||||
whose type is deduced. Note that the function arguments to make_pair
|
whose type is deduced. Note that the function arguments to
|
||||||
are not expressed in terms of call_traits: doing so would prevent
|
make_pair are not expressed in terms of call_traits: doing so
|
||||||
template argument deduction from functioning.</p>
|
would prevent template argument deduction from functioning.</p>
|
||||||
|
|
||||||
<h4><a name="ex4"></a>Example 4 (optimising fill):</h4>
|
<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>Pointers follow the same rational as small built-in types.</p>
|
||||||
|
|
||||||
<p>For reference types the rational follows <a href="#refs">Example
|
<p>For reference types the rational follows <a href="#refs">Example
|
||||||
2</a> - references to references are not allowed, so the call_traits
|
2</a> - references to references are not allowed, so the
|
||||||
members must be defined such that these problems do not occur.
|
call_traits members must be defined such that these problems do
|
||||||
There is a proposal to modify the language such that "a
|
not occur. There is a proposal to modify the language such that
|
||||||
reference to a reference is a reference" (issue #106,
|
"a reference to a reference is a reference" (issue #106,
|
||||||
submitted by Bjarne Stroustrup), call_traits<T>::value_type
|
submitted by Bjarne Stroustrup), call_traits<T>::value_type
|
||||||
and call_traits<T>::param_type both provide the same effect
|
and call_traits<T>::param_type both provide the same effect
|
||||||
as that proposal, without the need for a language change (in
|
as that proposal, without the need for a language change (in
|
||||||
@@ -687,11 +695,11 @@ struct A
|
|||||||
void foo(T t);
|
void foo(T t);
|
||||||
};</pre>
|
};</pre>
|
||||||
|
|
||||||
<p><font face="Times New Roman">In this case if we instantiate A<int[2]>
|
<p><font face="Times New Roman">In this case if we instantiate
|
||||||
then the declared type of the parameter passed to member function
|
A<int[2]> then the declared type of the parameter passed to
|
||||||
foo is int[2], but it's actual type is const int*, if we try to
|
member function foo is int[2], but it's actual type is const int*,
|
||||||
use the type T within the function body, then there is a strong
|
if we try to use the type T within the function body, then there
|
||||||
likelyhood that our code will not compile:</font></p>
|
is a strong likelyhood that our code will not compile:</font></p>
|
||||||
|
|
||||||
<pre>template <class T>
|
<pre>template <class T>
|
||||||
void A<T>::foo(T t)
|
void A<T>::foo(T t)
|
||||||
@@ -706,13 +714,13 @@ declared type:</p>
|
|||||||
<pre>template <class T>
|
<pre>template <class T>
|
||||||
struct A
|
struct A
|
||||||
{
|
{
|
||||||
void foo(call_traits<T>::value_type t);
|
void foo(typename call_traits<T>::value_type t);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class 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>
|
}</pre>
|
||||||
|
|
||||||
<p>For value_type (return by value), again only a pointer may be
|
<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
|
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
|
||||||
Maddock</a>, the latest version of this file can be found at <a
|
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
|
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>
|
<p>.</p>
|
||||||
|
|
||||||
|
@@ -117,13 +117,14 @@ void call_traits_checker<T>::operator()(param_type p)
|
|||||||
assert(t == c.value());
|
assert(t == c.value());
|
||||||
assert(t == c.get());
|
assert(t == c.get());
|
||||||
assert(t == c.const_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() << ">::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() << ">::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() << ">::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() << ">::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 << "typeof contained<" << typeid(T).name() << ">::call() is: " << typeid(&contained<T>::call).name() << endl;
|
||||||
cout << endl;
|
cout << endl;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
@@ -192,14 +193,14 @@ int main(int argc, char *argv[ ])
|
|||||||
int i = 2;
|
int i = 2;
|
||||||
c2(i);
|
c2(i);
|
||||||
int* pi = &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;
|
call_traits_checker<int*> c3;
|
||||||
c3(pi);
|
c3(pi);
|
||||||
call_traits_checker<int&> c4;
|
call_traits_checker<int&> c4;
|
||||||
c4(i);
|
c4(i);
|
||||||
call_traits_checker<const int&> c5;
|
call_traits_checker<const int&> c5;
|
||||||
c5(i);
|
c5(i);
|
||||||
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__)
|
||||||
int a[2] = {1,2};
|
int a[2] = {1,2};
|
||||||
call_traits_checker<int[2]> c6;
|
call_traits_checker<int[2]> c6;
|
||||||
c6(a);
|
c6(a);
|
||||||
@@ -237,7 +238,7 @@ int main(int argc, char *argv[ ])
|
|||||||
type_test(int&, boost::call_traits<int&>::reference)
|
type_test(int&, boost::call_traits<int&>::reference)
|
||||||
type_test(const int&, boost::call_traits<int&>::const_reference)
|
type_test(const int&, boost::call_traits<int&>::const_reference)
|
||||||
type_test(int&, boost::call_traits<int&>::param_type)
|
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>::value_type)
|
||||||
type_test(int&, boost::call_traits<cr_type>::reference)
|
type_test(int&, boost::call_traits<cr_type>::reference)
|
||||||
type_test(const int&, boost::call_traits<cr_type>::const_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
|
#ifdef BOOST_MSVC
|
||||||
unsigned int expected_failures = 10;
|
unsigned int expected_failures = 10;
|
||||||
|
#elif defined(__SUNPRO_CC)
|
||||||
|
unsigned int expected_failures = 11;
|
||||||
#elif defined(__BORLANDC__)
|
#elif defined(__BORLANDC__)
|
||||||
unsigned int expected_failures = 2;
|
unsigned int expected_failures = 2;
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
@@ -373,3 +376,5 @@ unsigned int expected_failures = 0;
|
|||||||
#endif
|
#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"
|
<meta name="Template"
|
||||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
||||||
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
|
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
|
||||||
<title>Header <boost/compressed_pair.hpp></title>
|
<title>Header </title>
|
||||||
|
<boost/compressed_pair.hpp>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
|
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
|
||||||
vlink="#800080">
|
vlink="#800080">
|
||||||
|
|
||||||
<h2><img src="../../c++boost.gif" width="276" height="86">Header
|
<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
|
<p>All of the contents of <boost/compressed_pair.hpp> are
|
||||||
defined inside namespace boost.</p>
|
defined inside namespace boost.</p>
|
||||||
@@ -41,6 +42,8 @@ public:
|
|||||||
explicit compressed_pair(first_param_type x);
|
explicit compressed_pair(first_param_type x);
|
||||||
explicit compressed_pair(second_param_type y);
|
explicit compressed_pair(second_param_type y);
|
||||||
|
|
||||||
|
compressed_pair& operator=(const compressed_pair&);
|
||||||
|
|
||||||
first_reference first();
|
first_reference first();
|
||||||
first_const_reference first() const;
|
first_const_reference first() const;
|
||||||
|
|
||||||
@@ -61,17 +64,19 @@ constructor, and this constructor initialises both values in the
|
|||||||
pair to the passed value.</p>
|
pair to the passed value.</p>
|
||||||
|
|
||||||
<p>Note that compressed_pair can not be instantiated if either of
|
<p>Note that compressed_pair can not be instantiated if either of
|
||||||
the template arguments is an enumerator type, unless there is
|
the template arguments is a union type, unless there is compiler
|
||||||
compiler support for boost::is_enum, or if boost::is_enum is
|
support for boost::is_union, or if boost::is_union is specialised
|
||||||
specialised for the enumerator type.</p>
|
for the union type.</p>
|
||||||
|
|
||||||
<p>Finally, compressed_pair requires compiler support for partial
|
<p>Finally, a word of caution for Visual C++ 6 users: if either
|
||||||
specialisation of class templates - without that support
|
argument is an empty type, then assigning to that member will
|
||||||
compressed_pair behaves just like std::pair.</p>
|
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>
|
<hr>
|
||||||
|
|
||||||
<p>Revised 08 March 2000</p>
|
<p>Revised 08 May 2001</p>
|
||||||
|
|
||||||
<p><EFBFBD> Copyright boost.org 2000. Permission to copy, use, modify,
|
<p><EFBFBD> Copyright boost.org 2000. Permission to copy, use, modify,
|
||||||
sell and distribute this document is granted provided this
|
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
|
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
|
||||||
Maddock</a>, the latest version of this file can be found at <a
|
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
|
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>
|
<p> </p>
|
||||||
</body>
|
</body>
|
||||||
|
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
#include <boost/compressed_pair.hpp>
|
#include <boost/compressed_pair.hpp>
|
||||||
#include <boost/type_traits/type_traits_test.hpp>
|
#include <boost/type_traits/type_traits_test.hpp>
|
||||||
|
#define BOOST_INCLUDE_MAIN
|
||||||
|
#include <boost/test/test_tools.hpp>
|
||||||
|
|
||||||
using namespace boost;
|
using namespace boost;
|
||||||
|
|
||||||
@@ -54,108 +56,345 @@ struct non_empty2
|
|||||||
{ return a.i == b.i; }
|
{ return a.i == b.i; }
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, char *argv[ ])
|
#ifdef __GNUC__
|
||||||
{
|
using std::swap;
|
||||||
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();
|
|
||||||
#endif
|
#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:
|
// tests for case where one or both
|
||||||
#ifdef __MWERKS__
|
// parameters are reference types:
|
||||||
template class compressed_pair<int, double>;
|
//
|
||||||
template class compressed_pair<int, int>;
|
template <class T1, class T2>
|
||||||
template class compressed_pair<empty_UDT, int>;
|
struct compressed_pair_reference_tester
|
||||||
template class compressed_pair<int, empty_UDT>;
|
{
|
||||||
template class compressed_pair<empty_UDT, empty_UDT>;
|
// define the types we need:
|
||||||
template class compressed_pair<empty_UDT, empty_POD_UDT>;
|
typedef T1 first_type;
|
||||||
#else
|
typedef T2 second_type;
|
||||||
template class boost::compressed_pair<int, double>;
|
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||||
template class boost::compressed_pair<int, int>;
|
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||||
template class boost::compressed_pair<empty_UDT, int>;
|
// define our test proc:
|
||||||
template class boost::compressed_pair<int, empty_UDT>;
|
static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
|
||||||
template class boost::compressed_pair<empty_UDT, empty_UDT>;
|
};
|
||||||
template class boost::compressed_pair<empty_UDT, empty_POD_UDT>;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
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 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,
|
// supplimentary tests for case where second arg only is a reference type:
|
||||||
// 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&);
|
|
||||||
//
|
//
|
||||||
// and then arrays:
|
template <class T1, class T2>
|
||||||
#ifndef __BORLANDC__
|
struct compressed_pair_reference2_tester
|
||||||
template call_traits<int[2]>::reference compressed_pair<double, int[2]>::second();
|
{
|
||||||
#endif
|
// define the types we need:
|
||||||
template call_traits<double>::reference compressed_pair<double, int[2]>::first();
|
typedef T1 first_type;
|
||||||
#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95))
|
typedef T2 second_type;
|
||||||
template compressed_pair<double, int[2]>::compressed_pair(call_traits<double>::param_type);
|
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||||
#endif
|
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||||
template compressed_pair<double, int[2]>::compressed_pair();
|
// define our test proc:
|
||||||
#endif // __MWERKS__
|
static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
|
||||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
};
|
||||||
|
|
||||||
|
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;
|
unsigned int expected_failures = 0;
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -282,7 +282,7 @@ template <class Incrementable>
|
|||||||
struct counting_iterator_traits
|
struct counting_iterator_traits
|
||||||
{
|
{
|
||||||
if (numeric_limits<Incrementable>::is_specialized) {
|
if (numeric_limits<Incrementable>::is_specialized) {
|
||||||
if (!numeric_limits<Incrementable>::is_integral)
|
if (!numeric_limits<Incrementable>::is_integer)
|
||||||
COMPILE_TIME_ERROR;
|
COMPILE_TIME_ERROR;
|
||||||
|
|
||||||
if (!numeric_limits<Incrementable>::is_bounded
|
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.
|
integer type <tt>T</tt> is <tt>T</tt> itself.
|
||||||
|
|
||||||
<hr>
|
<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,
|
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
modify, sell and distribute this document is granted provided this copyright
|
||||||
notice appears in all copies. This document is provided "as is"
|
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
|
The filter iterator adaptor (the type
|
||||||
<tt>filter_iterator_generator<...>::type</tt>) may be a model of <a
|
<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="http://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/ForwardIterator.html">ForwardIterator</a>
|
||||||
depending on the adapted iterator type.
|
depending on the adapted iterator type.
|
||||||
|
|
||||||
|
|
||||||
@@ -261,7 +261,7 @@ default).
|
|||||||
|
|
||||||
|
|
||||||
<hr>
|
<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,
|
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
modify, sell and distribute this document is granted provided this copyright
|
||||||
notice appears in all copies. This document is provided "as is"
|
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,20 @@
|
|||||||
// Boost operators.hpp header file ----------------------------------------//
|
// Boost operators.hpp header file ----------------------------------------//
|
||||||
|
|
||||||
// (C) Copyright David Abrahams 1999. Permission to copy, use,
|
// (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-2001.
|
||||||
// modify, sell and distribute this software is granted provided this
|
// Permission to copy, use, modify, sell and distribute this software is
|
||||||
// copyright notice appears in all copies. This software is provided
|
// granted provided this copyright notice appears in all copies. This
|
||||||
// "as is" without express or implied warranty, and with no claim as
|
// software is provided "as is" without express or implied warranty, and
|
||||||
// to its suitability for any purpose.
|
// with no claim as to its suitability for any purpose.
|
||||||
|
|
||||||
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
|
|
||||||
// sell and distribute this software is granted provided this
|
|
||||||
// copyright notice appears in all copies. This software is provided
|
|
||||||
// "as is" without express or implied warranty, and with no claim as
|
|
||||||
// to its suitability for any purpose.
|
|
||||||
|
|
||||||
// See http://www.boost.org for most recent version including documentation.
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
// Revision History
|
// Revision History
|
||||||
|
// 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
|
// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
|
||||||
// supplied arguments from actually being used (Dave Abrahams)
|
// supplied arguments from actually being used (Dave Abrahams)
|
||||||
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
|
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
|
||||||
@@ -282,12 +282,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
|
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
#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
|
// 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
|
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
|
||||||
@@ -295,12 +473,31 @@ struct indexable : B
|
|||||||
// two-argument forms. Note that these macros expect to be invoked from within
|
// two-argument forms. Note that these macros expect to be invoked from within
|
||||||
// boost.
|
// 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) \
|
# define BOOST_IMPORT_TEMPLATE2(template_name) \
|
||||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||||
struct template_name : ::template_name<T, U, B> {};
|
struct template_name : ::template_name<T, U, B> {};
|
||||||
@@ -309,21 +506,8 @@ struct indexable : B
|
|||||||
template <class T, class B = ::boost::detail::empty_base> \
|
template <class T, class B = ::boost::detail::empty_base> \
|
||||||
struct template_name : ::template_name<T, B> {};
|
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
|
# 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
|
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -332,7 +516,7 @@ struct indexable : B
|
|||||||
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
|
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
|
||||||
// neccessary.
|
// 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
|
// 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
|
// template argument is being used for base class chaining, or is specifying a
|
||||||
@@ -355,6 +539,15 @@ template<class T> struct is_chained_base {
|
|||||||
|
|
||||||
} // namespace boost
|
} // 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
|
// Import a 2-type-argument operator template into boost (if neccessary) and
|
||||||
// provide a specialization of 'is_chained_base<>' for it.
|
// provide a specialization of 'is_chained_base<>' for it.
|
||||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||||
@@ -414,6 +607,8 @@ BOOST_OPERATOR_TEMPLATE1(template_name##1)
|
|||||||
|
|
||||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
|
|
||||||
|
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
|
||||||
|
BOOST_IMPORT_TEMPLATE3(template_name3)
|
||||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||||
BOOST_IMPORT_TEMPLATE2(template_name2)
|
BOOST_IMPORT_TEMPLATE2(template_name2)
|
||||||
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
||||||
@@ -442,47 +637,41 @@ BOOST_OPERATOR_TEMPLATE(orable)
|
|||||||
|
|
||||||
BOOST_OPERATOR_TEMPLATE1(incrementable)
|
BOOST_OPERATOR_TEMPLATE1(incrementable)
|
||||||
BOOST_OPERATOR_TEMPLATE1(decrementable)
|
BOOST_OPERATOR_TEMPLATE1(decrementable)
|
||||||
|
|
||||||
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
|
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
|
||||||
|
BOOST_OPERATOR_TEMPLATE3(indexable)
|
||||||
|
|
||||||
// indexable doesn't follow the patterns above (it has 4 template arguments), so
|
BOOST_OPERATOR_TEMPLATE(left_shiftable)
|
||||||
// we just write out the compiler hacks explicitly.
|
BOOST_OPERATOR_TEMPLATE(right_shiftable)
|
||||||
#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
|
BOOST_OPERATOR_TEMPLATE(equivalent)
|
||||||
# ifdef BOOST_NO_USING_TEMPLATE
|
BOOST_OPERATOR_TEMPLATE(partially_ordered)
|
||||||
template <class T, class I, class R, class B = ::boost::detail::empty_base>
|
|
||||||
struct indexable : ::indexable<T,I,R,B> {};
|
|
||||||
# else
|
|
||||||
using ::indexable;
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
BOOST_OPERATOR_TEMPLATE(totally_ordered)
|
||||||
template <class T, class I, class R, class B>
|
BOOST_OPERATOR_TEMPLATE(additive)
|
||||||
struct is_chained_base< ::boost::indexable<T, I, R, B> > {
|
BOOST_OPERATOR_TEMPLATE(multiplicative)
|
||||||
typedef ::boost::detail::true_t operator_template_type;
|
BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
|
||||||
};
|
BOOST_OPERATOR_TEMPLATE(arithmetic)
|
||||||
#endif
|
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_TEMPLATE
|
||||||
|
#undef BOOST_OPERATOR_TEMPLATE3
|
||||||
#undef BOOST_OPERATOR_TEMPLATE2
|
#undef BOOST_OPERATOR_TEMPLATE2
|
||||||
#undef BOOST_OPERATOR_TEMPLATE1
|
#undef BOOST_OPERATOR_TEMPLATE1
|
||||||
#undef BOOST_IMPORT_TEMPLATE1
|
#undef BOOST_IMPORT_TEMPLATE1
|
||||||
#undef BOOST_IMPORT_TEMPLATE2
|
#undef BOOST_IMPORT_TEMPLATE2
|
||||||
|
#undef BOOST_IMPORT_TEMPLATE3
|
||||||
|
|
||||||
// The following 'operators' classes can only be used portably if the derived class
|
// The following 'operators' classes can only be used portably if the derived class
|
||||||
// declares ALL of the required member operators.
|
// declares ALL of the required member operators.
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
struct operators2
|
struct operators2
|
||||||
: less_than_comparable2<T,U
|
: totally_ordered2<T,U
|
||||||
, equality_comparable2<T,U
|
, integer_arithmetic2<T,U
|
||||||
, addable2<T,U
|
, bitwise2<T,U
|
||||||
, subtractable2<T,U
|
> > > {};
|
||||||
, multipliable2<T,U
|
|
||||||
, dividable2<T,U
|
|
||||||
, modable2<T,U
|
|
||||||
, orable2<T,U
|
|
||||||
, andable2<T,U
|
|
||||||
, xorable2<T,U
|
|
||||||
> > > > > > > > > > {};
|
|
||||||
|
|
||||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
template <class T, class U = T>
|
template <class T, class U = T>
|
||||||
@@ -492,31 +681,47 @@ template <class T> struct operators<T, T>
|
|||||||
#else
|
#else
|
||||||
template <class T> struct operators
|
template <class T> struct operators
|
||||||
#endif
|
#endif
|
||||||
: less_than_comparable<T
|
: totally_ordered<T
|
||||||
, equality_comparable<T
|
, integer_arithmetic<T
|
||||||
, addable<T
|
, bitwise<T
|
||||||
, subtractable<T
|
, unit_steppable<T
|
||||||
, multipliable<T
|
> > > > {};
|
||||||
, dividable<T
|
|
||||||
, modable<T
|
|
||||||
, orable<T
|
|
||||||
, andable<T
|
|
||||||
, xorable<T
|
|
||||||
, incrementable<T
|
|
||||||
, decrementable<T
|
|
||||||
> > > > > > > > > > > > {};
|
|
||||||
|
|
||||||
// Iterator helper classes (contributed by Jeremy Siek) -------------------//
|
// 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
|
||||||
|
> > > > {};
|
||||||
|
#ifndef BOOST_MSVC
|
||||||
|
template <class T,
|
||||||
|
class V = void,
|
||||||
|
class D = void,
|
||||||
|
class P = void,
|
||||||
|
class R = void>
|
||||||
|
struct output_iterator_helper
|
||||||
|
: incrementable<T
|
||||||
|
, boost::iterator<std::output_iterator_tag, V, D, P, R
|
||||||
|
> > {};
|
||||||
|
#endif
|
||||||
template <class T,
|
template <class T,
|
||||||
class V,
|
class V,
|
||||||
class D = std::ptrdiff_t,
|
class D = std::ptrdiff_t,
|
||||||
class P = V*,
|
class P = V*,
|
||||||
class R = V&>
|
class R = V&>
|
||||||
struct forward_iterator_helper
|
struct forward_iterator_helper
|
||||||
: equality_comparable<T
|
: equality_comparable1<T
|
||||||
, incrementable<T
|
, incrementable<T
|
||||||
, dereferenceable<T,P
|
, dereferenceable<T, P
|
||||||
, boost::iterator<std::forward_iterator_tag,V,D,P,R
|
, boost::iterator<std::forward_iterator_tag, V, D, P, R
|
||||||
> > > > {};
|
> > > > {};
|
||||||
|
|
||||||
template <class T,
|
template <class T,
|
||||||
@@ -525,12 +730,11 @@ template <class T,
|
|||||||
class P = V*,
|
class P = V*,
|
||||||
class R = V&>
|
class R = V&>
|
||||||
struct bidirectional_iterator_helper
|
struct bidirectional_iterator_helper
|
||||||
: equality_comparable<T
|
: equality_comparable1<T
|
||||||
, incrementable<T
|
, unit_steppable<T
|
||||||
, decrementable<T
|
, dereferenceable<T, P
|
||||||
, dereferenceable<T,P
|
, boost::iterator<std::bidirectional_iterator_tag, V, D, P, R
|
||||||
, boost::iterator<std::bidirectional_iterator_tag,V,D,P,R
|
> > > > {};
|
||||||
> > > > > {};
|
|
||||||
|
|
||||||
template <class T,
|
template <class T,
|
||||||
class V,
|
class V,
|
||||||
@@ -538,22 +742,17 @@ template <class T,
|
|||||||
class P = V*,
|
class P = V*,
|
||||||
class R = V&>
|
class R = V&>
|
||||||
struct random_access_iterator_helper
|
struct random_access_iterator_helper
|
||||||
: equality_comparable<T
|
: totally_ordered1<T
|
||||||
, less_than_comparable<T
|
, unit_steppable<T
|
||||||
, incrementable<T
|
, dereferenceable<T, P
|
||||||
, decrementable<T
|
, additive2<T, D
|
||||||
, dereferenceable<T,P
|
, indexable<T, D, R
|
||||||
, addable2<T,D
|
, boost::iterator<std::random_access_iterator_tag, V, D, P, R
|
||||||
, subtractable2<T,D
|
> > > > > >
|
||||||
, indexable<T,D,R
|
|
||||||
, boost::iterator<std::random_access_iterator_tag,V,D,P,R
|
|
||||||
> > > > > > > > >
|
|
||||||
{
|
{
|
||||||
#ifndef __BORLANDC__
|
|
||||||
friend D requires_difference_operator(const T& x, const T& y) {
|
friend D requires_difference_operator(const T& x, const T& y) {
|
||||||
return x - y;
|
return x - y;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}; // random_access_iterator_helper
|
}; // random_access_iterator_helper
|
||||||
|
|
||||||
} // namespace boost
|
} // namespace boost
|
||||||
|
@@ -11,6 +11,9 @@
|
|||||||
// Classes appear in alphabetical order
|
// Classes appear in alphabetical order
|
||||||
|
|
||||||
// Revision History
|
// 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)
|
// 26 Jan 00 protected noncopyable destructor added (Miki Jovanovic)
|
||||||
// 10 Dec 99 next() and prior() templates added (Dave Abrahams)
|
// 10 Dec 99 next() and prior() templates added (Dave Abrahams)
|
||||||
// 30 Aug 99 moved cast templates to cast.hpp (Beman Dawes)
|
// 30 Aug 99 moved cast templates to cast.hpp (Beman Dawes)
|
||||||
@@ -22,12 +25,32 @@
|
|||||||
#ifndef BOOST_UTILITY_HPP
|
#ifndef BOOST_UTILITY_HPP
|
||||||
#define BOOST_UTILITY_HPP
|
#define BOOST_UTILITY_HPP
|
||||||
|
|
||||||
#include <boost/config.hpp>
|
#include <boost/config.hpp> // broken compiler workarounds
|
||||||
#include <cstddef> // for size_t
|
#include <boost/static_assert.hpp>
|
||||||
#include <utility> // for std::pair
|
#include <cstddef> // for size_t
|
||||||
|
#include <utility> // for std::pair
|
||||||
|
|
||||||
namespace boost
|
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 -----------------------------------//
|
// next() and prior() template functions -----------------------------------//
|
||||||
|
|
||||||
@@ -41,10 +64,10 @@ namespace boost
|
|||||||
// Contributed by Dave Abrahams
|
// Contributed by Dave Abrahams
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
T next(T x) { return ++x; }
|
inline T next(T x) { return ++x; }
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
T prior(T x) { return --x; }
|
inline T prior(T x) { return --x; }
|
||||||
|
|
||||||
|
|
||||||
// class noncopyable -------------------------------------------------------//
|
// class noncopyable -------------------------------------------------------//
|
||||||
|
@@ -422,8 +422,7 @@ a,b,c,d,e,f,g,
|
|||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
<p>Revised
|
<p>Revised
|
||||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->10
|
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" -->
|
||||||
Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p>© Copyright Jeremy Siek and David Abrahams 2001. Permission to
|
<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
|
// Example of using indirect_iterator_pair_generator
|
||||||
|
|
||||||
typedef boost::indirect_iterator_pair_generator<char**,
|
typedef boost::indirect_iterator_pair_generator<char**, char> PairGen;
|
||||||
char, char*, char&, const char*, const char&> PairGen;
|
|
||||||
|
|
||||||
char mutable_characters[N];
|
char mutable_characters[N];
|
||||||
char* pointers_to_mutable_chars[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,
|
// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
|
||||||
// sell and distribute this software is granted provided this
|
// sell and distribute this software is granted provided this
|
||||||
@@ -9,6 +9,8 @@
|
|||||||
// See http://www.boost.org for most recent version including documentation.
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
// Revision History
|
// 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
|
// 19 Feb 01 Take adavantage of improved iterator_traits to do more tests
|
||||||
// on MSVC. Hack around an MSVC-with-STLport internal compiler
|
// on MSVC. Hack around an MSVC-with-STLport internal compiler
|
||||||
// error. (David Abrahams)
|
// error. (David Abrahams)
|
||||||
@@ -59,28 +61,6 @@ struct my_iterator_tag : public std::random_access_iterator_tag { };
|
|||||||
|
|
||||||
using boost::dummyT;
|
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 {
|
struct mult_functor {
|
||||||
typedef int result_type;
|
typedef int result_type;
|
||||||
@@ -117,78 +97,6 @@ typedef std::deque<int> storage;
|
|||||||
typedef std::deque<int*> pointer_deque;
|
typedef std::deque<int*> pointer_deque;
|
||||||
typedef std::set<storage::iterator> iterator_set;
|
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
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
@@ -210,67 +118,14 @@ main()
|
|||||||
|
|
||||||
// Test the iterator_adaptor
|
// 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);
|
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::random_access_iterator_test(j, N, array);
|
||||||
boost::const_nonconst_iterator_test(i, ++j);
|
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
|
// Test projection_iterator_pair_generator
|
||||||
{
|
{
|
||||||
typedef std::pair<dummyT,dummyT> Pair;
|
typedef std::pair<dummyT,dummyT> Pair;
|
||||||
@@ -376,23 +231,33 @@ main()
|
|||||||
|
|
||||||
// Test filter iterator
|
// Test filter iterator
|
||||||
{
|
{
|
||||||
// Using typedefs for filter_gen::type and filter_gen::policies_type
|
// Using typedefs for filter_gen::type confused Borland terribly.
|
||||||
// confused Borland terribly.
|
|
||||||
typedef boost::detail::non_bidirectional_category<dummyT*>::type category;
|
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
|
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||||
, dummyT
|
, dummyT
|
||||||
#endif
|
#endif
|
||||||
>::type filter_iter;
|
>::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));
|
filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N));
|
||||||
boost::forward_iterator_test(i, dummyT(1), dummyT(4));
|
boost::forward_iterator_test(i, dummyT(1), dummyT(4));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__BORLANDC__)
|
||||||
|
//
|
||||||
enum { is_forward = boost::is_same<
|
enum { is_forward = boost::is_same<
|
||||||
filter_iter::iterator_category,
|
filter_iter::iterator_category,
|
||||||
std::forward_iterator_tag>::value };
|
std::forward_iterator_tag>::value };
|
||||||
BOOST_STATIC_ASSERT(is_forward);
|
BOOST_STATIC_ASSERT(is_forward);
|
||||||
|
#endif
|
||||||
|
|
||||||
// On compilers not supporting partial specialization, we can do more type
|
// On compilers not supporting partial specialization, we can do more type
|
||||||
// deduction with deque iterators than with pointers... unless the library
|
// deduction with deque iterators than with pointers... unless the library
|
||||||
@@ -433,12 +298,24 @@ main()
|
|||||||
// check operator-> with a forward iterator
|
// check operator-> with a forward iterator
|
||||||
{
|
{
|
||||||
boost::forward_iterator_archetype<dummyT> forward_iter;
|
boost::forward_iterator_archetype<dummyT> forward_iter;
|
||||||
|
#if defined(__BORLANDC__)
|
||||||
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
|
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
|
||||||
boost::default_iterator_policies,
|
boost::default_iterator_policies,
|
||||||
dummyT, const dummyT&, const dummyT*,
|
dummyT, const dummyT&, const dummyT*,
|
||||||
std::forward_iterator_tag, std::ptrdiff_t> adaptor_type;
|
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);
|
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());
|
assert((*i).m_x == i->foo());
|
||||||
}
|
}
|
||||||
// check operator-> with an input iterator
|
// check operator-> with an input iterator
|
||||||
@@ -449,10 +326,10 @@ main()
|
|||||||
dummyT, const dummyT&, const dummyT*,
|
dummyT, const dummyT&, const dummyT*,
|
||||||
std::input_iterator_tag, std::ptrdiff_t> adaptor_type;
|
std::input_iterator_tag, std::ptrdiff_t> adaptor_type;
|
||||||
adaptor_type i(input_iter);
|
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());
|
assert((*i).m_x == i->foo());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "test successful " << std::endl;
|
std::cout << "test successful " << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,8 @@
|
|||||||
|
|
||||||
<li><a href="#template_parameters">Template Parameters</a>
|
<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="#policies">The Policies Class</a>
|
||||||
|
|
||||||
<li><a href="#additional_members">Additional Class Members</a>
|
<li><a href="#additional_members">Additional Class Members</a>
|
||||||
@@ -63,7 +65,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
Specialized Iterator Adaptors
|
<a name="specialized_adaptors">Specialized Iterator Adaptors</a>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="indirect_iterator.htm">Indirect Iterator Adaptor</a>
|
<li><a href="indirect_iterator.htm">Indirect Iterator Adaptor</a>
|
||||||
@@ -84,6 +86,11 @@
|
|||||||
"../../boost/counting_iterator.hpp">boost/counting_iterator.hpp</a></tt><br>
|
"../../boost/counting_iterator.hpp">boost/counting_iterator.hpp</a></tt><br>
|
||||||
|
|
||||||
<a href="counting_iterator.htm">Counting Iterator Adaptor</a>
|
<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>
|
</ul>
|
||||||
|
|
||||||
<p><b><a href="http://www.boost.org/people/dave_abrahams.htm">Dave
|
<p><b><a href="http://www.boost.org/people/dave_abrahams.htm">Dave
|
||||||
@@ -98,8 +105,9 @@
|
|||||||
<b><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy
|
<b><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy
|
||||||
Siek</a></b> contributed the <a href="transform_iterator.htm">transform
|
Siek</a></b> contributed the <a href="transform_iterator.htm">transform
|
||||||
iterator</a> adaptor, the integer-only version of <tt><a href=
|
iterator</a> adaptor, the integer-only version of <tt><a href=
|
||||||
"counting_iterator.htm">counting_iterator_generator</a></tt>, and most of
|
"counting_iterator.htm">counting_iterator_generator</a></tt>,
|
||||||
the documentation.<br>
|
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
|
<b><a href="http://www.boost.org/people/john_potter.htm">John
|
||||||
Potter</a></b> contributed the <tt><a href=
|
Potter</a></b> contributed the <tt><a href=
|
||||||
"projection_iterator.htm">projection_</a></tt> and <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:
|
<p><tt>iterator_adaptor</tt> is declared like this:
|
||||||
<pre>
|
<pre>
|
||||||
template <class Base, class Policies,
|
template <class Base, class Policies,
|
||||||
class Value = typename std::iterator_traits<Base>::value_type,
|
class ValueOrNamedParams = typename std::iterator_traits<Base>::value_type,
|
||||||
class Reference = <i>...(see below)</i>,
|
class ReferenceOrNamedParams = <i>...(see below)</i>,
|
||||||
class Pointer = <i>...(see below)</i>,
|
class PointerOrNamedParams = <i>...(see below)</i>,
|
||||||
class Category = typename std::iterator_traits<Base>::iterator_category,
|
class CategoryOrNamedParams = typename std::iterator_traits<Base>::iterator_category,
|
||||||
class Distance = typename std::iterator_traits<Base>::difference_type>
|
class DistanceOrNamedParams = typename std::iterator_traits<Base>::difference_type>
|
||||||
struct iterator_adaptor;
|
struct iterator_adaptor;
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
@@ -162,7 +170,8 @@ struct iterator_adaptor;
|
|||||||
<td>The <tt>value_type</tt> of the resulting iterator, unless const. If
|
<td>The <tt>value_type</tt> of the resulting iterator, unless const. If
|
||||||
Value is <tt>const X</tt> the
|
Value is <tt>const X</tt> the
|
||||||
<tt>value_type</tt> will be (<i>non-</i><tt>const</tt>) <tt>X</tt><a href=
|
<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>
|
<b>Default:</b>
|
||||||
<tt>std::iterator_traits<BaseType>::value_type</tt> <a href=
|
<tt>std::iterator_traits<BaseType>::value_type</tt> <a href=
|
||||||
"#2">[2]</a>
|
"#2">[2]</a>
|
||||||
@@ -197,27 +206,99 @@ struct iterator_adaptor;
|
|||||||
<td>The <tt>difference_type</tt> for the resulting iterator.<br>
|
<td>The <tt>difference_type</tt> for the resulting iterator.<br>
|
||||||
<b>Default:</b>
|
<b>Default:</b>
|
||||||
<tt>std::iterator_traits<BaseType>::difference_type</tt>
|
<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>
|
</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>
|
<h3><a name="policies">The Policies Class</a></h3>
|
||||||
|
|
||||||
<p>The main task in using <tt>iterator_adaptor</tt> is creating an
|
<p>The main task in using <tt>iterator_adaptor</tt> is creating an
|
||||||
appropriate <tt>Policies</tt> class. The <tt>Policies</tt> class will
|
appropriate <tt>Policies</tt> class. The <tt>Policies</tt> class will become
|
||||||
become the functional heart of the iterator adaptor, supplying the core
|
the functional heart of the resulting iterator, supplying the core
|
||||||
iterator operations that will determine how your new adaptor class will
|
operations that determine its behavior. The <tt>iterator_adaptor</tt>
|
||||||
behave. The <tt>iterator_adaptor</tt> template defines all of the operators
|
template defines all of the operators required of a <a href=
|
||||||
required of a <a href=
|
|
||||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
|
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
|
||||||
Iterator</a>. Your <tt>Policies</tt> class must implement three, four, or
|
Iterator</a> by dispatching to a <tt>Policies</tt> object. Your
|
||||||
seven of the core iterator operations below depending on the iterator
|
<tt>Policies</tt> class must implement a subset of the core iterator
|
||||||
categories you want it to support.<br>
|
operations below corresponding to the iterator categories you want it to
|
||||||
|
support.<br>
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
|
||||||
<table border="1" summary="iterator_adaptor Policies operations">
|
<table border="1" summary="iterator_adaptor Policies operations">
|
||||||
<caption>
|
<caption>
|
||||||
<b>Core Iterator Operations</b><br>
|
<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>
|
</caption>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
@@ -230,13 +311,13 @@ struct iterator_adaptor;
|
|||||||
<th>Required for Iterator Categories
|
<th>Required for Iterator Categories
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td><tt>dereference</tt>
|
<td><tt>initialize</tt>
|
||||||
|
|
||||||
<td>returns an element of the iterator's <tt>reference</tt> type
|
<td>optionally modify base iterator during iterator construction
|
||||||
|
|
||||||
<td><tt>*p</tt>, <tt>p[n]</tt>
|
|
||||||
|
|
||||||
<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/InputIterator.html">Input</a>/ <a href=
|
||||||
"http://www.sgi.com/tech/stl/OutputIterator.html">Output</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
|
"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
|
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||||
Access</a>
|
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>
|
<tr>
|
||||||
<td><tt>equal</tt>
|
<td><tt>equal</tt>
|
||||||
|
|
||||||
@@ -324,6 +414,10 @@ struct iterator_adaptor;
|
|||||||
<pre>
|
<pre>
|
||||||
struct <a name="default_iterator_policies">default_iterator_policies</a>
|
struct <a name="default_iterator_policies">default_iterator_policies</a>
|
||||||
{
|
{
|
||||||
|
template <class BaseType>
|
||||||
|
void initialize(BaseType&)
|
||||||
|
{ }
|
||||||
|
|
||||||
template <class Reference, class BaseType>
|
template <class Reference, class BaseType>
|
||||||
Reference dereference(type<Reference>, const BaseType& x) const
|
Reference dereference(type<Reference>, const BaseType& x) const
|
||||||
{ return *x; }
|
{ 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
|
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
|
usefulness of <tt>default_iterator_policies</tt> to a particular range of
|
||||||
adapted iterators. If you follow the same pattern with your
|
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>
|
<h3><a name="additional_members">Additional Members</a></h3>
|
||||||
In addition to all of the member functions required of a <a href=
|
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
|
returning a reference could cause serious memory problems due to the
|
||||||
reference being bound to a temporary object whose lifetime ends inside of
|
reference being bound to a temporary object whose lifetime ends inside of
|
||||||
the <tt>operator[]</tt>.
|
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>
|
<hr>
|
||||||
|
|
||||||
<p>Revised
|
<p>Revised
|
||||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->15
|
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14895" -->
|
||||||
Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p>© Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy,
|
<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
|
<!-- LocalWords: iostream hpp sizeof InputIterator constness ConstIterator
|
||||||
David Abrahams
|
David Abrahams
|
||||||
-->
|
-->
|
||||||
</body>
|
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
// See http://www.boost.org for most recent version including documentation.
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
// Revision History
|
// Revision History
|
||||||
|
// 04 Mar 2001 Patches for Intel C++ (Dave Abrahams)
|
||||||
// 19 Feb 2001 Take advantage of improved iterator_traits to do more tests
|
// 19 Feb 2001 Take advantage of improved iterator_traits to do more tests
|
||||||
// on MSVC. Reordered some #ifdefs for coherency.
|
// on MSVC. Reordered some #ifdefs for coherency.
|
||||||
// (David Abrahams)
|
// (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;
|
typedef ::std::char_traits<char>::off_type distance;
|
||||||
non_pointer_test<std::ostream_iterator<int>,int,
|
non_pointer_test<std::ostream_iterator<int>,int,
|
||||||
distance,int*,int&,std::output_iterator_tag> ostream_iterator_test;
|
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>,
|
non_pointer_test<std::ostream_iterator<int>,
|
||||||
int, void, void, void, std::output_iterator_tag>
|
int, void, void, void, std::output_iterator_tag>
|
||||||
ostream_iterator_test;
|
ostream_iterator_test;
|
||||||
|
@@ -9,16 +9,25 @@
|
|||||||
// See http://www.boost.org for most recent version including documentation.
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
// Revision History
|
// 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)
|
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
|
||||||
|
|
||||||
#include <string>
|
#define BOOST_INCLUDE_MAIN
|
||||||
#include <iostream>
|
#include <boost/test/test_tools.hpp> // for main
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
#include <boost/operators.hpp>
|
#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT
|
||||||
using namespace boost;
|
#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
|
||||||
|
|
||||||
|
|
||||||
|
// Iterator test class
|
||||||
template <class T, class R, class P>
|
template <class T, class R, class P>
|
||||||
struct test_iter
|
struct test_iter
|
||||||
: public boost::random_access_iterator_helper<
|
: public boost::random_access_iterator_helper<
|
||||||
@@ -29,7 +38,7 @@ struct test_iter
|
|||||||
typedef std::ptrdiff_t Distance;
|
typedef std::ptrdiff_t Distance;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
test_iter(T* i) : _i(i) { }
|
explicit test_iter(T* i =0) : _i(i) { }
|
||||||
test_iter(const self& x) : _i(x._i) { }
|
test_iter(const self& x) : _i(x._i) { }
|
||||||
self& operator=(const self& x) { _i = x._i; return *this; }
|
self& operator=(const self& x) { _i = x._i; return *this; }
|
||||||
Reference operator*() const { return *_i; }
|
Reference operator*() const { return *_i; }
|
||||||
@@ -43,127 +52,280 @@ public:
|
|||||||
return x._i - y._i;
|
return x._i - y._i;
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
T* _i;
|
P _i;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Iterator operator testing classes
|
||||||
int
|
class test_opr_base
|
||||||
main()
|
|
||||||
{
|
{
|
||||||
string array[] = { "apple", "orange", "pear", "peach", "grape", "plum" };
|
protected:
|
||||||
{
|
// Test data and types
|
||||||
test_iter<string,string&,string*> i = array,
|
BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u );
|
||||||
ie = array + sizeof(array)/sizeof(string);
|
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++
|
static fruit_array_type fruit;
|
||||||
while (i != ie)
|
static scratch_array_type scratch;
|
||||||
cout << *i++ << " ";
|
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test i--
|
}; // test_opr_base
|
||||||
while (ie != i) {
|
|
||||||
ie--;
|
|
||||||
cout << *ie << " ";
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
ie = array + sizeof(array)/sizeof(string);
|
|
||||||
|
|
||||||
// test i->m
|
template <typename T, typename R = T&, typename P = T*>
|
||||||
while (i != ie) {
|
class test_opr
|
||||||
cout << i->size() << " ";
|
: public test_opr_base
|
||||||
++i;
|
{
|
||||||
}
|
typedef test_opr<T, R, P> self_type;
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test i + n
|
public:
|
||||||
while (i < ie) {
|
// Types
|
||||||
cout << *i << " ";
|
typedef T value_type;
|
||||||
i = i + 2;
|
typedef R reference;
|
||||||
}
|
typedef P pointer;
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test n + i
|
typedef test_iter<T, R, P> iter_type;
|
||||||
while (i < ie) {
|
|
||||||
cout << *i << " ";
|
|
||||||
i = ptrdiff_t(2) + i;
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test i - n
|
// Test controller
|
||||||
while (ie > i) {
|
static void master_test( char const name[] );
|
||||||
ie = ie - 2;
|
|
||||||
cout << *ie << " ";
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
ie = array + sizeof(array)/sizeof(string);
|
|
||||||
|
|
||||||
// test i[n]
|
private:
|
||||||
for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j)
|
// Test data
|
||||||
cout << i[j] << " ";
|
static iter_type const fruit_begin, fruit_end;
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
test_iter<string, const string&, const string*> i = array,
|
|
||||||
ie = array + sizeof(array)/sizeof(string);
|
|
||||||
|
|
||||||
// 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++
|
}; // test_opr
|
||||||
while (i != ie)
|
|
||||||
cout << *i++ << " ";
|
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test i--
|
|
||||||
while (ie != i) {
|
|
||||||
ie--;
|
|
||||||
cout << *ie << " ";
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
ie = array + sizeof(array)/sizeof(string);
|
|
||||||
|
|
||||||
// test i->m
|
// Class-static data definitions
|
||||||
while (i != ie) {
|
test_opr_base::fruit_array_type
|
||||||
cout << i->size() << " ";
|
test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" };
|
||||||
++i;
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test i + n
|
test_opr_base::scratch_array_type
|
||||||
while (i < ie) {
|
test_opr_base::scratch = "";
|
||||||
cout << *i << " ";
|
|
||||||
i = i + 2;
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test n + i
|
template <typename T, typename R, typename P>
|
||||||
while (i < ie) {
|
typename test_opr<T, R, P>::iter_type const
|
||||||
cout << *i << " ";
|
test_opr<T, R, P>::fruit_begin( fruit );
|
||||||
i = ptrdiff_t(2) + i;
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
i = array;
|
|
||||||
|
|
||||||
// test i - n
|
template <typename T, typename R, typename P>
|
||||||
while (ie > i) {
|
typename test_opr<T, R, P>::iter_type const
|
||||||
ie = ie - 2;
|
test_opr<T, R, P>::fruit_end( fruit + fruit_length );
|
||||||
cout << *ie << " ";
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
ie = array + sizeof(array)/sizeof(string);
|
|
||||||
|
|
||||||
// test i[n]
|
|
||||||
for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j)
|
// Main testing function
|
||||||
cout << i[j] << " ";
|
int
|
||||||
cout << endl;
|
test_main( int , char * [] )
|
||||||
}
|
{
|
||||||
return 0;
|
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 );
|
||||||
}
|
}
|
||||||
|
1513
operators.htm
1513
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.
|
// See http://www.boost.org for most recent version including documentation.
|
||||||
|
|
||||||
// Revision History
|
// 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)
|
// 04 Jun 00 Added regression test for a bug I found (David Abrahams)
|
||||||
// 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy)
|
// 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy)
|
||||||
// ?? ??? 00 Major update to randomly test all one- and two- argument forms by
|
// ?? ??? 00 Major update to randomly test all one- and two- argument forms by
|
||||||
// wrapping integral types and comparing the results of operations to
|
// wrapping integral types and comparing the results of operations
|
||||||
// the results for the raw types (David Abrahams)
|
// to the results for the raw types (David Abrahams)
|
||||||
// 12 Dec 99 Minor update, output confirmation message.
|
// 12 Dec 99 Minor update, output confirmation message.
|
||||||
// 15 Nov 99 Initial version
|
// 15 Nov 99 Initial version
|
||||||
|
|
||||||
#include <boost/operators.hpp>
|
#define BOOST_INCLUDE_MAIN
|
||||||
#include <cassert>
|
|
||||||
#include <iostream>
|
#include <boost/config.hpp> // for BOOST_MSVC
|
||||||
#include <boost/min_rand.hpp>
|
#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
|
namespace
|
||||||
@@ -28,14 +36,18 @@ namespace
|
|||||||
int true_value(int x) { return x; }
|
int true_value(int x) { return x; }
|
||||||
long true_value(long x) { return x; }
|
long true_value(long x) { return x; }
|
||||||
signed char true_value(signed char 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 int true_value(unsigned int x) { return x; }
|
||||||
unsigned long true_value(unsigned long x) { return x; }
|
unsigned long true_value(unsigned long x) { return x; }
|
||||||
unsigned char true_value(unsigned char 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
|
// The use of operators<> here tended to obscure
|
||||||
// compiler bugs
|
// interactions with certain compiler bugs
|
||||||
template <class T>
|
template <class T>
|
||||||
class Wrapped1 : boost::operators<Wrapped1<T> >
|
class Wrapped1
|
||||||
|
: boost::operators<Wrapped1<T> >
|
||||||
|
, boost::shiftable<Wrapped1<T> >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Wrapped1( T v = T() ) : _value(v) {}
|
explicit Wrapped1( T v = T() ) : _value(v) {}
|
||||||
@@ -60,6 +72,10 @@ namespace
|
|||||||
{ _value &= x._value; return *this; }
|
{ _value &= x._value; return *this; }
|
||||||
Wrapped1& operator^=(const Wrapped1& x)
|
Wrapped1& operator^=(const Wrapped1& x)
|
||||||
{ _value ^= x._value; return *this; }
|
{ _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; }
|
||||||
Wrapped1& operator--() { --_value; return *this; }
|
Wrapped1& operator--() { --_value; return *this; }
|
||||||
|
|
||||||
@@ -70,9 +86,11 @@ namespace
|
|||||||
T true_value(Wrapped1<T> x) { return x.value(); }
|
T true_value(Wrapped1<T> x) { return x.value(); }
|
||||||
|
|
||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
class Wrapped2 :
|
class Wrapped2
|
||||||
boost::operators<Wrapped2<T, U> >,
|
: boost::operators<Wrapped2<T, U> >
|
||||||
boost::operators2<Wrapped2<T, U>, U>
|
, boost::operators2<Wrapped2<T, U>, U>
|
||||||
|
, boost::shiftable1<Wrapped2<T, U>
|
||||||
|
, boost::shiftable2<Wrapped2<T, U>, U > >
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Wrapped2( T v = T() ) : _value(v) {}
|
explicit Wrapped2( T v = T() ) : _value(v) {}
|
||||||
@@ -97,6 +115,10 @@ namespace
|
|||||||
{ _value &= x._value; return *this; }
|
{ _value &= x._value; return *this; }
|
||||||
Wrapped2& operator^=(const Wrapped2& x)
|
Wrapped2& operator^=(const Wrapped2& x)
|
||||||
{ _value ^= x._value; return *this; }
|
{ _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; }
|
||||||
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; }
|
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:
|
private:
|
||||||
T _value;
|
T _value;
|
||||||
@@ -118,203 +142,268 @@ namespace
|
|||||||
template <class T, class U>
|
template <class T, class U>
|
||||||
T true_value(Wrapped2<T,U> x) { return x.value(); }
|
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<>
|
// MyInt uses only the single template-argument form of all_operators<>
|
||||||
typedef Wrapped1<int> MyInt;
|
typedef Wrapped1<int> MyInt;
|
||||||
|
|
||||||
typedef Wrapped2<long, long> MyLong;
|
typedef Wrapped2<long, long> MyLong;
|
||||||
|
|
||||||
|
typedef Wrapped3<signed char> MyChar;
|
||||||
|
|
||||||
|
typedef Wrapped4<short, short> MyShort;
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
assert(true_value(y1) == true_value(y2));
|
BOOST_TEST( true_value(y1) == true_value(y2) );
|
||||||
assert(true_value(x1) == true_value(x2));
|
BOOST_TEST( true_value(x1) == true_value(x2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
assert((x1 < y1) == (x2 < y2));
|
BOOST_TEST( (x1 < y1) == (x2 < y2) );
|
||||||
assert((x1 <= y1) == (x2 <= y2));
|
BOOST_TEST( (x1 <= y1) == (x2 <= y2) );
|
||||||
assert((x1 >= y1) == (x2 >= y2));
|
BOOST_TEST( (x1 >= y1) == (x2 >= y2) );
|
||||||
assert((x1 > y1) == (x2 > y2));
|
BOOST_TEST( (x1 > y1) == (x2 > y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_less_than_comparable_aux(x1, y1, x2, y2);
|
test_less_than_comparable_aux( x1, y1, x2, y2 );
|
||||||
test_less_than_comparable_aux(y1, x1, y2, x2);
|
test_less_than_comparable_aux( y1, x1, y2, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
assert((x1 == y1) == (x2 == y2));
|
BOOST_TEST( (x1 == y1) == (x2 == y2) );
|
||||||
assert((x1 != y1) == (x2 != y2));
|
BOOST_TEST( (x1 != y1) == (x2 != y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_equality_comparable_aux(x1, y1, x2, y2);
|
test_equality_comparable_aux( x1, y1, x2, y2 );
|
||||||
test_equality_comparable_aux(y1, x1, y2, x2);
|
test_equality_comparable_aux( y1, x1, y2, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 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>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_multipliable_aux(x1, y1, x2, y2);
|
test_multipliable_aux( x1, y1, x2, y2 );
|
||||||
test_multipliable_aux(y1, x1, y2, x2);
|
test_multipliable_aux( y1, x1, y2, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 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>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_addable_aux(x1, y1, x2, y2);
|
test_addable_aux( x1, y1, x2, y2 );
|
||||||
test_addable_aux(y1, x1, y2, x2);
|
test_addable_aux( y1, x1, y2, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
assert((x1 - y1).value() == x2 - y2);
|
BOOST_TEST( (x1 - y1).value() == (x2 - y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
if (y2 != 0)
|
if ( y2 != 0 )
|
||||||
assert((x1 / y1).value() == x2 / y2);
|
BOOST_TEST( (x1 / y1).value() == (x2 / y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
if (y2 != 0)
|
if ( y2 != 0 )
|
||||||
assert((x1 / y1).value() == x2 / y2);
|
BOOST_TEST( (x1 % y1).value() == (x2 % y2) );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 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>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_xorable_aux(x1, y1, x2, y2);
|
test_xorable_aux( x1, y1, x2, y2 );
|
||||||
test_xorable_aux(y1, x1, y2, x2);
|
test_xorable_aux( y1, x1, y2, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 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>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_andable_aux(x1, y1, x2, y2);
|
test_andable_aux( x1, y1, x2, y2 );
|
||||||
test_andable_aux(y1, x1, y2, x2);
|
test_andable_aux( y1, x1, y2, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 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>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, y1, x2, y2);
|
sanity_check( x1, y1, x2, y2 );
|
||||||
test_orable_aux(x1, y1, x2, y2);
|
test_orable_aux( x1, y1, x2, y2 );
|
||||||
test_orable_aux(y1, x1, y2, x2);
|
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>
|
template <class X1, class X2>
|
||||||
void test_incrementable(X1 x1, X2 x2)
|
void test_incrementable(X1 x1, X2 x2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, x1, x2, x2);
|
sanity_check( x1, x1, x2, x2 );
|
||||||
assert(x1++.value() == x2++);
|
BOOST_TEST( (x1++).value() == x2++ );
|
||||||
assert(x1.value() == x2);
|
BOOST_TEST( x1.value() == x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class X2>
|
template <class X1, class X2>
|
||||||
void test_decrementable(X1 x1, X2 x2)
|
void test_decrementable(X1 x1, X2 x2)
|
||||||
{
|
{
|
||||||
sanity_check(x1, x1, x2, x2);
|
sanity_check( x1, x1, x2, x2 );
|
||||||
assert(x1--.value() == x2--);
|
BOOST_TEST( (x1--).value() == x2-- );
|
||||||
assert(x1.value() == x2);
|
BOOST_TEST( x1.value() == x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class X1, class Y1, class X2, class Y2>
|
template <class X1, class Y1, class X2, class Y2>
|
||||||
void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||||
{
|
{
|
||||||
test_less_than_comparable(x1, y1, x2, y2);
|
test_less_than_comparable( x1, y1, x2, y2 );
|
||||||
test_equality_comparable(x1, y1, x2, y2);
|
test_equality_comparable( x1, y1, x2, y2 );
|
||||||
test_multipliable(x1, y1, x2, y2);
|
test_multipliable( x1, y1, x2, y2 );
|
||||||
test_addable(x1, y1, x2, y2);
|
test_addable( x1, y1, x2, y2 );
|
||||||
test_subtractable(x1, y1, x2, y2);
|
test_subtractable( x1, y1, x2, y2 );
|
||||||
test_dividable(x1, y1, x2, y2);
|
test_dividable( x1, y1, x2, y2 );
|
||||||
test_modable(x1, y1, x2, y2);
|
test_modable( x1, y1, x2, y2 );
|
||||||
test_xorable(x1, y1, x2, y2);
|
test_xorable( x1, y1, x2, y2 );
|
||||||
test_andable(x1, y1, x2, y2);
|
test_andable( x1, y1, x2, y2 );
|
||||||
test_orable(x1, y1, x2, y2);
|
test_orable( x1, y1, x2, y2 );
|
||||||
test_incrementable(x1, x2);
|
test_left_shiftable( x1, y1, x2, y2 );
|
||||||
test_decrementable(x1, x2);
|
test_right_shiftable( x1, y1, x2, y2 );
|
||||||
|
test_incrementable( x1, x2 );
|
||||||
|
test_decrementable( x1, x2 );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Big, class Small>
|
template <class Big, class Small>
|
||||||
struct tester
|
struct tester
|
||||||
{
|
{
|
||||||
void operator()(boost::min_rand& randomizer) const
|
void operator()(boost::minstd_rand& randomizer) const
|
||||||
{
|
{
|
||||||
Big b1 = Big(randomizer());
|
Big b1 = Big( randomizer() );
|
||||||
Big b2 = Big(randomizer());
|
Big b2 = Big( randomizer() );
|
||||||
Small s = Small(randomizer());
|
Small s = Small( randomizer() );
|
||||||
|
|
||||||
test_all(Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2);
|
test_all( Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2 );
|
||||||
test_all(Wrapped2<Big, Small>(b1), s, b1, s);
|
test_all( Wrapped2<Big, Small>(b1), s, b1, s );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// added as a regression test. We had a bug which this uncovered.
|
// added as a regression test. We had a bug which this uncovered.
|
||||||
struct Point
|
struct Point
|
||||||
: boost::addable<Point,
|
: boost::addable<Point
|
||||||
boost::subtractable<Point> >
|
, boost::subtractable<Point> >
|
||||||
{
|
{
|
||||||
Point( int h, int v ) : h(h), v(v) {}
|
Point( int h, int v ) : h(h), v(v) {}
|
||||||
Point() :h(0), v(0) {}
|
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 )
|
||||||
const Point& operator-=( const Point& rhs ) { h -= rhs.h; v -= rhs.v; return *this; }
|
{ 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 h;
|
||||||
int v;
|
int v;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
|
|
||||||
|
|
||||||
@@ -340,20 +429,25 @@ template Wrapped2<unsigned long, unsigned char>;
|
|||||||
template Wrapped2<unsigned long, unsigned long>;
|
template Wrapped2<unsigned long, unsigned long>;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) )
|
||||||
#error This program is pointless when NDEBUG disables assert()!
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main()
|
|
||||||
|
int
|
||||||
|
test_main( int , char * [] )
|
||||||
{
|
{
|
||||||
|
using std::cout;
|
||||||
|
using std::endl;
|
||||||
|
|
||||||
// Regression test.
|
// Regression test.
|
||||||
Point x;
|
Point x;
|
||||||
x = x + Point(3, 4);
|
x = x + Point(3, 4);
|
||||||
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)
|
for (int n = 0; n < 10000; ++n)
|
||||||
{
|
{
|
||||||
boost::min_rand r;
|
boost::minstd_rand r;
|
||||||
tester<long, int>()(r);
|
tester<long, int>()(r);
|
||||||
tester<long, signed char>()(r);
|
tester<long, signed char>()(r);
|
||||||
tester<long, long>()(r);
|
tester<long, long>()(r);
|
||||||
@@ -367,115 +461,197 @@ int main()
|
|||||||
tester<unsigned int, unsigned char>()(r);
|
tester<unsigned int, unsigned char>()(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cout << "Did random tester loop." << endl;
|
||||||
|
|
||||||
MyInt i1(1);
|
MyInt i1(1);
|
||||||
MyInt i2(2);
|
MyInt i2(2);
|
||||||
MyInt i;
|
MyInt i;
|
||||||
|
|
||||||
assert( i1.value() == 1 );
|
BOOST_TEST( i1.value() == 1 );
|
||||||
assert( i2.value() == 2 );
|
BOOST_TEST( i2.value() == 2 );
|
||||||
assert( i.value() == 0 );
|
BOOST_TEST( i.value() == 0 );
|
||||||
|
|
||||||
i = i2;
|
cout << "Created MyInt objects.\n";
|
||||||
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 );
|
|
||||||
|
|
||||||
i = i1 + i2; assert( i.value() == 3 );
|
PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) );
|
||||||
i = i + i2; assert( i.value() == 5 );
|
|
||||||
i = i - i1; assert( i.value() == 4 );
|
BOOST_TEST( i2 == i );
|
||||||
i = i * i2; assert( i.value() == 8 );
|
BOOST_TEST( i1 != i2 );
|
||||||
i = i / i2; assert( i.value() == 4 );
|
BOOST_TEST( i1 < i2 );
|
||||||
i = i % (i - i1); assert( i.value() == 1 );
|
BOOST_TEST( i1 <= i2 );
|
||||||
i = i2 + i2; assert( i.value() == 4 );
|
BOOST_TEST( i <= i2 );
|
||||||
i = i1 | i2 | i; assert( i.value() == 7 );
|
BOOST_TEST( i2 > i1 );
|
||||||
i = i & i2; assert( i.value() == 2 );
|
BOOST_TEST( i2 >= i1 );
|
||||||
i = i + i1; assert( i.value() == 3 );
|
BOOST_TEST( i2 >= i );
|
||||||
i = i ^ i1; assert( i.value() == 2 );
|
|
||||||
i = (i+i1)*(i2|i1); assert( i.value() == 9 );
|
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 j1(1);
|
||||||
MyLong j2(2);
|
MyLong j2(2);
|
||||||
MyLong j;
|
MyLong j;
|
||||||
|
|
||||||
assert( j1.value() == 1 );
|
BOOST_TEST( j1.value() == 1 );
|
||||||
assert( j2.value() == 2 );
|
BOOST_TEST( j2.value() == 2 );
|
||||||
assert( j.value() == 0 );
|
BOOST_TEST( j.value() == 0 );
|
||||||
|
|
||||||
j = j2;
|
cout << "Created MyLong objects.\n";
|
||||||
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 );
|
|
||||||
|
|
||||||
assert( (j1 + 2) == 3 );
|
PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) );
|
||||||
assert( (1 + j2) == 3 );
|
|
||||||
j = j1 + j2; assert( j.value() == 3 );
|
|
||||||
|
|
||||||
assert( (j + 2) == 5 );
|
BOOST_TEST( j2 == j );
|
||||||
assert( (3 + j2) == 5 );
|
BOOST_TEST( 2 == j );
|
||||||
j = j + j2; assert( j.value() == 5 );
|
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 );
|
BOOST_TEST( (j + 2) == 5 );
|
||||||
j = j - j1; assert( j.value() == 4 );
|
BOOST_TEST( (3 + j2) == 5 );
|
||||||
|
PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) );
|
||||||
|
|
||||||
assert( (j * 2) == 8 );
|
BOOST_TEST( (j - 1) == 4 );
|
||||||
assert( (4 * j2) == 8 );
|
PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) );
|
||||||
j = j * j2; assert( j.value() == 8 );
|
|
||||||
|
|
||||||
assert( (j / 2) == 4 );
|
BOOST_TEST( (j * 2) == 8 );
|
||||||
j = j / j2; assert( j.value() == 4 );
|
BOOST_TEST( (4 * j2) == 8 );
|
||||||
|
PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) );
|
||||||
|
|
||||||
assert( (j % 3) == 1 );
|
BOOST_TEST( (j / 2) == 4 );
|
||||||
j = j % (j - j1); assert( j.value() == 1 );
|
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 );
|
PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) );
|
||||||
assert( (j1 | 2 | j) == 7 );
|
|
||||||
assert( (j1 | j2 | 4) == 7 );
|
|
||||||
j = j1 | j2 | j; assert( j.value() == 7 );
|
|
||||||
|
|
||||||
assert( (7 & j2) == 2 );
|
BOOST_TEST( (1 | j2 | j) == 7 );
|
||||||
assert( (j & 2) == 2 );
|
BOOST_TEST( (j1 | 2 | j) == 7 );
|
||||||
j = j & j2; assert( j.value() == 2 );
|
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 );
|
PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) );
|
||||||
assert( (j ^ 1) == 2 );
|
|
||||||
j = j ^ j1; assert( j.value() == 2 );
|
|
||||||
|
|
||||||
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";
|
PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) );
|
||||||
return 0;
|
|
||||||
|
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>
|
</pre>
|
||||||
|
|
||||||
<hr>
|
<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,
|
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
modify, sell and distribute this document is granted provided this copyright
|
||||||
notice appears in all copies. This document is provided "as is"
|
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
|
<p>Revised
|
||||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->15
|
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" -->
|
||||||
Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14373" -->
|
|
||||||
|
|
||||||
|
|
||||||
<p>© Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell
|
<p>© Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell
|
||||||
|
6
tie.html
6
tie.html
@@ -23,7 +23,9 @@
|
|||||||
<TT>tie</TT>
|
<TT>tie</TT>
|
||||||
</H1>
|
</H1>
|
||||||
|
|
||||||
<P>
|
<h3>
|
||||||
|
[tie has been deprecated. Its functionality is supplied by the Boost
|
||||||
|
Tuples Library.]</h3>
|
||||||
<PRE>
|
<PRE>
|
||||||
template <class A, class B>
|
template <class A, class B>
|
||||||
tied<A,B> tie(A& a, B& 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>
|
<P>
|
||||||
Here is another example that uses <TT>tie()</TT> for handling operations with <a
|
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>
|
<P>
|
||||||
<PRE>
|
<PRE>
|
||||||
|
@@ -71,8 +71,11 @@ public:
|
|||||||
|
|
||||||
<p>
|
<p>
|
||||||
The following is an example of how to use the
|
The following is an example of how to use the
|
||||||
<tt>transform_iterator_generator</tt> class to iterate through a range of
|
<tt>transform_iterator_generator</tt> class to iterate through a range
|
||||||
numbers, multiplying each of them by 2 when they are dereferenced.
|
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>
|
<p>
|
||||||
<PRE>
|
<PRE>
|
||||||
@@ -80,16 +83,18 @@ numbers, multiplying each of them by 2 when they are dereferenced.
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <boost/iterator_adaptors.hpp>
|
#include <boost/iterator_adaptors.hpp>
|
||||||
|
|
||||||
|
// definition of class boost::binder1st and function boost::bind1st() ...
|
||||||
|
|
||||||
int
|
int
|
||||||
main(int, char*[])
|
main(int, char*[])
|
||||||
{
|
{
|
||||||
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
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;
|
typedef boost::transform_iterator_generator<Function, int*>::type doubling_iterator;
|
||||||
|
|
||||||
doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),
|
doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)),
|
||||||
i_end(x + sizeof(x)/sizeof(int), std::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;
|
std::cout << "multiplying the array by 2:" << std::endl;
|
||||||
while (i != i_end)
|
while (i != i_end)
|
||||||
@@ -111,14 +116,17 @@ The output from this part is:
|
|||||||
</TR>
|
</TR>
|
||||||
|
|
||||||
<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
|
<TD>The function object that transforms each element in the iterator
|
||||||
range. The <tt>argument_type</tt> of the function object must match
|
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
|
the value type of the base iterator. The <tt>result_type</tt> of the
|
||||||
function object will be the resulting iterator's
|
function object will be the resulting iterator's
|
||||||
<tt>value_type</tt>. If you want the resulting iterator to behave as
|
<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
|
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>
|
||||||
|
|
||||||
<TR>
|
<TR>
|
||||||
@@ -133,7 +141,7 @@ its argument.</TD>
|
|||||||
|
|
||||||
The transform iterator adaptor (the type
|
The transform iterator adaptor (the type
|
||||||
<tt>transform_iterator_generator<...>::type</tt>) is a model of <a
|
<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>
|
<h3>Members</h3>
|
||||||
@@ -173,8 +181,8 @@ function to add four to each element of the array.
|
|||||||
<pre>
|
<pre>
|
||||||
std::cout << "adding 4 to each element in the array:" << std::endl;
|
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)),
|
std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)),
|
||||||
boost::make_transform_iterator(x + N, std::bind1st(std::plus<int>(), 4)),
|
boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
|
||||||
std::ostream_iterator<int>(std::cout, " "));
|
std::ostream_iterator<int>(std::cout, " "));
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
|
||||||
@@ -203,7 +211,7 @@ iterator always returns by-value.
|
|||||||
|
|
||||||
|
|
||||||
<hr>
|
<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,
|
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
|
||||||
modify, sell and distribute this document is granted provided this copyright
|
modify, sell and distribute this document is granted provided this copyright
|
||||||
notice appears in all copies. This document is provided "as is"
|
notice appears in all copies. This document is provided "as is"
|
||||||
|
@@ -9,6 +9,38 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <boost/iterator_adaptors.hpp>
|
#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
|
int
|
||||||
main(int, char*[])
|
main(int, char*[])
|
||||||
{
|
{
|
||||||
@@ -20,11 +52,11 @@ main(int, char*[])
|
|||||||
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||||
const int N = sizeof(x)/sizeof(int);
|
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;
|
typedef boost::transform_iterator_generator<Function, int*>::type doubling_iterator;
|
||||||
|
|
||||||
doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),
|
doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)),
|
||||||
i_end(x + N, std::bind1st(std::multiplies<int>(), 2));
|
i_end(x + N, boost::bind1st(std::multiplies<int>(), 2));
|
||||||
|
|
||||||
std::cout << "multiplying the array by 2:" << std::endl;
|
std::cout << "multiplying the array by 2:" << std::endl;
|
||||||
while (i != i_end)
|
while (i != i_end)
|
||||||
@@ -33,8 +65,8 @@ main(int, char*[])
|
|||||||
|
|
||||||
std::cout << "adding 4 to each element in the array:" << std::endl;
|
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)),
|
std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)),
|
||||||
boost::make_transform_iterator(x + N, std::bind1st(std::plus<int>(), 4)),
|
boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
|
||||||
std::ostream_iterator<int>(std::cout, " "));
|
std::ostream_iterator<int>(std::cout, " "));
|
||||||
std::cout << std::endl;
|
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>
|
<h2>Contents</h2>
|
||||||
|
|
||||||
<ul>
|
<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>Function templates <a href="#functions next">next() and prior()</a></li>
|
||||||
<li>Class <a href="#Class noncopyable">noncopyable</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>
|
<li>Function template <a href="tie.html">tie()</a> and supporting class tied.</li>
|
||||||
</ul>
|
</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>
|
<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
|
<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)
|
concern about the effect on compiler optimization of adding (even trivial inline)
|
||||||
destructor declarations. He says "Probably this concern is misplaced, because
|
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>
|
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>
|
<hr>
|
||||||
<p>Revised <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan
|
<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>
|
||||||
<p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and
|
<p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and
|
||||||
|
Reference in New Issue
Block a user