mirror of
				https://github.com/boostorg/utility.git
				synced 2025-11-04 02:11:45 +01:00 
			
		
		
		
	Compare commits
	
		
			186 Commits
		
	
	
		
			boost-1.19
			...
			boost-1.24
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					885e4d4c6b | ||
| 
						 | 
					d68a11cc42 | ||
| 
						 | 
					328a81e194 | ||
| 
						 | 
					31d0908b74 | ||
| 
						 | 
					32c77599f4 | ||
| 
						 | 
					812ebf3562 | ||
| 
						 | 
					37f476013d | ||
| 
						 | 
					9f3104166f | ||
| 
						 | 
					64cc0daf34 | ||
| 
						 | 
					d5d64df124 | ||
| 
						 | 
					0edcfcd5c1 | ||
| 
						 | 
					50ba2d419a | ||
| 
						 | 
					ff3a77ca5a | ||
| 
						 | 
					4eaed6c23d | ||
| 
						 | 
					4d0dd46471 | ||
| 
						 | 
					9c2549bd00 | ||
| 
						 | 
					b7c8e0c17f | ||
| 
						 | 
					dd3cfe1837 | ||
| 
						 | 
					43f525298e | ||
| 
						 | 
					1bb1898ab9 | ||
| 
						 | 
					9578f24be9 | ||
| 
						 | 
					46fae3aed2 | ||
| 
						 | 
					e35f91a70a | ||
| 
						 | 
					851052fcca | ||
| 
						 | 
					5ef81b2952 | ||
| 
						 | 
					ef2851c053 | ||
| 
						 | 
					0b4387cff5 | ||
| 
						 | 
					a40cf11fbf | ||
| 
						 | 
					5c495cd223 | ||
| 
						 | 
					cf1296dff8 | ||
| 
						 | 
					d6d88db6e8 | ||
| 
						 | 
					85c2a35257 | ||
| 
						 | 
					836d8b1c64 | ||
| 
						 | 
					98d8c8ab71 | ||
| 
						 | 
					db45013339 | ||
| 
						 | 
					a55c37e7f6 | ||
| 
						 | 
					46a270fcca | ||
| 
						 | 
					967856518e | ||
| 
						 | 
					7f93e739fe | ||
| 
						 | 
					2cd1422514 | ||
| 
						 | 
					feb370b201 | ||
| 
						 | 
					d1b34e64d8 | ||
| 
						 | 
					b9a1eead40 | ||
| 
						 | 
					1e4bfac98c | ||
| 
						 | 
					3bb504fbf3 | ||
| 
						 | 
					5029791c90 | ||
| 
						 | 
					a1a68f0970 | ||
| 
						 | 
					f8543d79eb | ||
| 
						 | 
					f353415136 | ||
| 
						 | 
					26240403b0 | ||
| 
						 | 
					3a39729b58 | ||
| 
						 | 
					096c961d9a | ||
| 
						 | 
					01fe04a6a2 | ||
| 
						 | 
					7ea4014993 | ||
| 
						 | 
					d50b374f88 | ||
| 
						 | 
					27dfb25570 | ||
| 
						 | 
					b5ed77985e | ||
| 
						 | 
					61243bd15f | ||
| 
						 | 
					368b94d804 | ||
| 
						 | 
					a5adbbfd5f | ||
| 
						 | 
					a19d13f123 | ||
| 
						 | 
					78886ab383 | ||
| 
						 | 
					168012b465 | ||
| 
						 | 
					d9d58ea66e | ||
| 
						 | 
					56f5f6e8d5 | ||
| 
						 | 
					3cb6420eda | ||
| 
						 | 
					60be2c1186 | ||
| 
						 | 
					ed210f6b2c | ||
| 
						 | 
					029bc59d74 | ||
| 
						 | 
					961c08a82f | ||
| 
						 | 
					7ee484c614 | ||
| 
						 | 
					05c6fbbf99 | ||
| 
						 | 
					91078b7f7a | ||
| 
						 | 
					20d804afc4 | ||
| 
						 | 
					c21f6d1cbf | ||
| 
						 | 
					393e79c1fd | ||
| 
						 | 
					8b92c8a085 | ||
| 
						 | 
					ff73dd94c9 | ||
| 
						 | 
					af43904f38 | ||
| 
						 | 
					485074f265 | ||
| 
						 | 
					2e0ee55b5e | ||
| 
						 | 
					e9105d32cb | ||
| 
						 | 
					964d23f68c | ||
| 
						 | 
					be5aaaae7b | ||
| 
						 | 
					bf13bd7b3f | ||
| 
						 | 
					352e392fcb | ||
| 
						 | 
					083b1b02df | ||
| 
						 | 
					648c6240a2 | ||
| 
						 | 
					60cab840cb | ||
| 
						 | 
					83a4380dab | ||
| 
						 | 
					de84fe8d98 | ||
| 
						 | 
					ed3cbfdb8e | ||
| 
						 | 
					fda44ca17d | ||
| 
						 | 
					272025bb07 | ||
| 
						 | 
					8e92bcf1b2 | ||
| 
						 | 
					84f1ffdefe | ||
| 
						 | 
					7e25450054 | ||
| 
						 | 
					4a563fa266 | ||
| 
						 | 
					aa4c0ec000 | ||
| 
						 | 
					e1ecfbdc43 | ||
| 
						 | 
					a4e122a82e | ||
| 
						 | 
					93216e8fb7 | ||
| 
						 | 
					16272c210d | ||
| 
						 | 
					e104b00da1 | ||
| 
						 | 
					ce5c6bcc08 | ||
| 
						 | 
					8694ce31fe | ||
| 
						 | 
					d960e5eadd | ||
| 
						 | 
					2dc71e87a3 | ||
| 
						 | 
					6bf17edde2 | ||
| 
						 | 
					88573d515d | ||
| 
						 | 
					89b9f77823 | ||
| 
						 | 
					765d9be17d | ||
| 
						 | 
					7135373008 | ||
| 
						 | 
					ee269884fc | ||
| 
						 | 
					387540d5f1 | ||
| 
						 | 
					2eba7b42a8 | ||
| 
						 | 
					07115d26c7 | ||
| 
						 | 
					c43ed815a0 | ||
| 
						 | 
					ff01e36d12 | ||
| 
						 | 
					ac4798b16c | ||
| 
						 | 
					d4e14fed0e | ||
| 
						 | 
					5f91259344 | ||
| 
						 | 
					20a9d9645d | ||
| 
						 | 
					c86f6b4abd | ||
| 
						 | 
					d66489b5b2 | ||
| 
						 | 
					b743ee9f0c | ||
| 
						 | 
					95ba69c00a | ||
| 
						 | 
					2ac273739c | ||
| 
						 | 
					5b4d28708c | ||
| 
						 | 
					4cc4383488 | ||
| 
						 | 
					8935232248 | ||
| 
						 | 
					5c6dd2f172 | ||
| 
						 | 
					eeeb7ef5b9 | ||
| 
						 | 
					2efc9c1178 | ||
| 
						 | 
					a84c46f6e3 | ||
| 
						 | 
					a5c3dcdd02 | ||
| 
						 | 
					46f7a75eb7 | ||
| 
						 | 
					94b6710c5b | ||
| 
						 | 
					d8dd3da9ab | ||
| 
						 | 
					803ced004a | ||
| 
						 | 
					0ea7d36ad0 | ||
| 
						 | 
					87aafab759 | ||
| 
						 | 
					994d310abd | ||
| 
						 | 
					228cdcf05e | ||
| 
						 | 
					42598e352c | ||
| 
						 | 
					36a9e4d1da | ||
| 
						 | 
					456dfd0dea | ||
| 
						 | 
					155457e2b5 | ||
| 
						 | 
					b5c91485bf | ||
| 
						 | 
					c959cf7870 | ||
| 
						 | 
					5878c88636 | ||
| 
						 | 
					ddcef2fb19 | ||
| 
						 | 
					493d124c07 | ||
| 
						 | 
					f42060c616 | ||
| 
						 | 
					834facc932 | ||
| 
						 | 
					f82d0b76ee | ||
| 
						 | 
					c25d225275 | ||
| 
						 | 
					c503a274b5 | ||
| 
						 | 
					087069d215 | ||
| 
						 | 
					826a6dd114 | ||
| 
						 | 
					f31483838d | ||
| 
						 | 
					d8a9b633d9 | ||
| 
						 | 
					c060e4466a | ||
| 
						 | 
					a9951376f4 | ||
| 
						 | 
					bda0c8f5e3 | ||
| 
						 | 
					71902f23a2 | ||
| 
						 | 
					dfd6c85569 | ||
| 
						 | 
					0e41b2cc1a | ||
| 
						 | 
					e5c81d0702 | ||
| 
						 | 
					6caf7d4d5a | ||
| 
						 | 
					98e87c8afb | ||
| 
						 | 
					d9e0f80d50 | ||
| 
						 | 
					6396fdb5ff | ||
| 
						 | 
					2470b53373 | ||
| 
						 | 
					16334e92ca | ||
| 
						 | 
					c22d98a8ec | ||
| 
						 | 
					28617afbb9 | ||
| 
						 | 
					0c3bc42bec | ||
| 
						 | 
					e3d9745df1 | ||
| 
						 | 
					b8471c1015 | ||
| 
						 | 
					045b09c9ef | ||
| 
						 | 
					4ac07b97d3 | ||
| 
						 | 
					34c847c17f | ||
| 
						 | 
					f694e557e1 | ||
| 
						 | 
					6a0c3e92a0 | ||
| 
						 | 
					cba48df8e3 | 
@@ -100,7 +100,7 @@ Assignment
 | 
			
		||||
</UL>
 | 
			
		||||
 | 
			
		||||
<h3>See also</h3>
 | 
			
		||||
<a href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">DefaultConstructible</A>
 | 
			
		||||
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">DefaultConstructible</A>
 | 
			
		||||
and 
 | 
			
		||||
<A href="./CopyConstructible.html">CopyConstructible</A>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@
 | 
			
		||||
  -- purpose.  It is provided "as is" without express or implied warranty.
 | 
			
		||||
  -->
 | 
			
		||||
<Head>
 | 
			
		||||
<Title>CopyConstructible</Title>
 | 
			
		||||
<Title>Copy Constructible</Title>
 | 
			
		||||
</HEAD>
 | 
			
		||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b" 
 | 
			
		||||
        ALINK="#ff0000"> 
 | 
			
		||||
@@ -19,10 +19,10 @@
 | 
			
		||||
     ALT="C++ Boost" width="277" height="86"> 
 | 
			
		||||
<!--end header-->
 | 
			
		||||
<BR Clear>
 | 
			
		||||
<H1>CopyConstructible</H1>
 | 
			
		||||
<H1>Copy Constructible</H1>
 | 
			
		||||
 | 
			
		||||
<h3>Description</h3>
 | 
			
		||||
A type is CopyConstructible if it is possible to copy objects of that
 | 
			
		||||
A type is Copy Constructible if it is possible to copy objects of that
 | 
			
		||||
type.
 | 
			
		||||
 | 
			
		||||
<h3>Notation</h3>
 | 
			
		||||
@@ -32,7 +32,7 @@ type.
 | 
			
		||||
<tt>T</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
is type that is a model of CopyConstructible
 | 
			
		||||
is type that is a model of Copy Constructible
 | 
			
		||||
</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
@@ -194,9 +194,9 @@ denotes the address of <tt>u</tt>
 | 
			
		||||
 | 
			
		||||
<h3>See also</h3>
 | 
			
		||||
<A
 | 
			
		||||
href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">DefaultConstructible</A>
 | 
			
		||||
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</A>
 | 
			
		||||
and 
 | 
			
		||||
<A href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</A>
 | 
			
		||||
<A hrefa="./Assignable.html">Assignable</A>
 | 
			
		||||
 | 
			
		||||
<br>
 | 
			
		||||
<HR>
 | 
			
		||||
 
 | 
			
		||||
@@ -196,7 +196,7 @@ satisfies the definition of a <i>partial ordering</i>.  The definition of
 | 
			
		||||
a <i>strict weak ordering</i> is stricter, and the definition of a
 | 
			
		||||
<i>total ordering</i> is stricter still.
 | 
			
		||||
<h3>See also</h3>
 | 
			
		||||
<A href="http://www.sgi.com/Technology/STL/EqualityComparable.html">EqualityComparable</A>, <A href="http://www.sgi.com/Technology/STL/StrictWeakOrdering.html">StrictWeakOrdering</A>
 | 
			
		||||
<A href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</A>, <A href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html">StrictWeakOrdering</A>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -21,21 +21,21 @@
 | 
			
		||||
 | 
			
		||||
<H2>
 | 
			
		||||
<A NAME="concept:MultiPassInputIterator"></A>
 | 
			
		||||
MultiPassInputIterator
 | 
			
		||||
Multi-Pass Input Iterator
 | 
			
		||||
</H2>
 | 
			
		||||
 | 
			
		||||
This concept is a refinement of <a
 | 
			
		||||
href="http://www.sgi.com/Technology/STL/InputIterator.html">InputIterator</a>,
 | 
			
		||||
href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>,
 | 
			
		||||
adding the requirements that the iterator can be used to make multiple
 | 
			
		||||
passes through a range, and that if <TT>it1 == it2</TT> and
 | 
			
		||||
<TT>it1</TT> is dereferenceable then <TT>++it1 == ++it2</TT>. The
 | 
			
		||||
MultiPassInputIterator is very similar to the <a
 | 
			
		||||
href="http://www.sgi.com/Technology/STL/ForwardIterator.hmtl">ForwardIterator</a>. The
 | 
			
		||||
Multi-Pass Input Iterator is very similar to the <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/ForwardIterator.hmtl">Forward Iterator</a>. The
 | 
			
		||||
only difference is that a <a
 | 
			
		||||
href="http://www.sgi.com/Technology/STL/ForwardIterator.hmtl">ForwardIterator</a>
 | 
			
		||||
href="http://www.sgi.com/tech/stl/ForwardIterator.hmtl">Forward Iterator</a>
 | 
			
		||||
requires the <TT>reference</TT> type to be <TT>value_type&</TT>, whereas
 | 
			
		||||
MultiPassInputIterator is like <a
 | 
			
		||||
href="http://www.sgi.com/Technology/STL/InputIterator.html">InputIterator</a>
 | 
			
		||||
href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>
 | 
			
		||||
in that the <TT>reference</TT> type merely has to be convertible to
 | 
			
		||||
<TT>value_type</TT>.
 | 
			
		||||
 | 
			
		||||
@@ -44,29 +44,29 @@ in that the <TT>reference</TT> type merely has to be convertible to
 | 
			
		||||
 | 
			
		||||
comments by Valentin Bonnard:
 | 
			
		||||
 | 
			
		||||
<p> I think that introducing MultiPassInputIterator isn't the right
 | 
			
		||||
solution. Do you also want to define MultiPassBidirectionnalIterator
 | 
			
		||||
and MultiPassRandomAccessIterator ? I don't, definitly. It only
 | 
			
		||||
<p> I think that introducing Multi-Pass Input Iterator isn't the right
 | 
			
		||||
solution. Do you also want to define Multi-Pass Bidirectionnal Iterator
 | 
			
		||||
and Multi-Pass Random Access Iterator ? I don't, definitly. It only
 | 
			
		||||
confuses the issue. The problem lies into the existing hierarchy of
 | 
			
		||||
iterators, which mixes movabillity, modifiabillity and lvalue-ness,
 | 
			
		||||
and these are clearly independant.
 | 
			
		||||
 | 
			
		||||
<p> The terms Forward, Bidirectionnal and RandomAccess are about
 | 
			
		||||
<p> The terms Forward, Bidirectionnal and Random Access are about
 | 
			
		||||
movabillity and shouldn't be used to mean anything else.  In a
 | 
			
		||||
completly orthogonal way, iterators can be immutable, mutable, or
 | 
			
		||||
neither.  Lvalueness of iterators is also orthogonal with
 | 
			
		||||
immutabillity.  With these clean concepts, your MultiPassInputIterator
 | 
			
		||||
is just called a ForwardIterator.
 | 
			
		||||
immutabillity.  With these clean concepts, your Multi-Pass Input Iterator
 | 
			
		||||
is just called a Forward Iterator.
 | 
			
		||||
 | 
			
		||||
<p>                
 | 
			
		||||
Other translations are:<br>
 | 
			
		||||
std::ForwardIterator -> ForwardIterator & LvalueIterator<br>
 | 
			
		||||
std::BidirectionnalIterator -> BidirectionnalIterator & LvalueIterator<br>
 | 
			
		||||
std::RandomAccessIterator -> RandomAccessIterator & LvalueIterator<br>
 | 
			
		||||
std::Forward Iterator -> ForwardIterator & Lvalue Iterator<br>
 | 
			
		||||
std::Bidirectionnal Iterator -> Bidirectionnal Iterator & Lvalue Iterator<br>
 | 
			
		||||
std::Random Access Iterator -> Random Access Iterator & Lvalue Iterator<br>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
Note that in practice the only operation not allowed on my 
 | 
			
		||||
ForwardIterator which is allowed on std::ForwardIterator is 
 | 
			
		||||
Forward Iterator which is allowed on std::Forward Iterator is 
 | 
			
		||||
<tt>&*it</tt>. I think that <tt>&*</tt> is rarely needed in generic code.
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
@@ -75,9 +75,9 @@ reply by Jeremy Siek:
 | 
			
		||||
<p>
 | 
			
		||||
The above analysis by Valentin is right on. Of course, there is
 | 
			
		||||
the problem with backward compatibility. The current STL implementations
 | 
			
		||||
are based on the old definition of ForwardIterator. The right course
 | 
			
		||||
of action is to get ForwardIterator, etc. changed in the C++ standard.
 | 
			
		||||
Once that is done we can drop MultiPassInputIterator.
 | 
			
		||||
are based on the old definition of Forward Iterator. The right course
 | 
			
		||||
of action is to get Forward Iterator, etc. changed in the C++ standard.
 | 
			
		||||
Once that is done we can drop Multi-Pass Input Iterator.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<br>
 | 
			
		||||
@@ -85,7 +85,7 @@ Once that is done we can drop MultiPassInputIterator.
 | 
			
		||||
<TABLE>
 | 
			
		||||
<TR valign=top>
 | 
			
		||||
<TD nowrap>Copyright © 2000</TD><TD>
 | 
			
		||||
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
 | 
			
		||||
<a HREF="../../people/jeremy_siek.htm">Jeremy Siek</a>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
 | 
			
		||||
</TD></TR></TABLE>
 | 
			
		||||
 | 
			
		||||
</BODY>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,424 +0,0 @@
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright (c) 1999
 | 
			
		||||
 * Dr John Maddock
 | 
			
		||||
 *
 | 
			
		||||
 * Permission to use, copy, modify, distribute and sell this software
 | 
			
		||||
 * and its documentation for any purpose is hereby granted without fee,
 | 
			
		||||
 * provided that the above copyright notice appear in all copies and
 | 
			
		||||
 * that both that copyright notice and this permission notice appear
 | 
			
		||||
 * in supporting documentation.  Dr John Maddock makes no representations
 | 
			
		||||
 * about the suitability of this software for any purpose.
 | 
			
		||||
 * It is provided "as is" without express or implied warranty.
 | 
			
		||||
 *
 | 
			
		||||
 * This file provides some example of type_traits usage -
 | 
			
		||||
 * by "optimising" various algorithms:
 | 
			
		||||
 *
 | 
			
		||||
 * opt::copy - optimised for trivial copy (cf std::copy)
 | 
			
		||||
 * opt::fill - optimised for trivial copy/small types (cf std::fill)
 | 
			
		||||
 * opt::destroy_array - an example of optimisation based upon omitted destructor calls
 | 
			
		||||
 * opt::iter_swap - uses type_traits to determine whether the iterator is a proxy
 | 
			
		||||
 *                  in which case it uses a "safe" approach, otherwise calls swap
 | 
			
		||||
 *                  on the assumption that swap may be specialised for the pointed-to type.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/* Release notes:
 | 
			
		||||
   23rd July 2000:
 | 
			
		||||
      Added explicit failure for broken compilers that don't support these examples.
 | 
			
		||||
      Fixed broken gcc support (broken using directive).
 | 
			
		||||
      Reordered tests slightly.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <typeinfo>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <memory>
 | 
			
		||||
 | 
			
		||||
#include <boost/timer.hpp>
 | 
			
		||||
#include <boost/type_traits.hpp>
 | 
			
		||||
#include <boost/call_traits.hpp>
 | 
			
		||||
 | 
			
		||||
using std::cout;
 | 
			
		||||
using std::endl;
 | 
			
		||||
using std::cin;
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
#error "Sorry, without template partial specialisation support there isn't anything to test here..."
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace opt{
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// algorithm destroy_array:
 | 
			
		||||
// The reverse of std::unitialized_copy, takes a block of
 | 
			
		||||
// unitialized memory and calls destructors on all objects therein.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
namespace detail{
 | 
			
		||||
 | 
			
		||||
template <bool>
 | 
			
		||||
struct array_destroyer
 | 
			
		||||
{
 | 
			
		||||
   template <class T>
 | 
			
		||||
   static void destroy_array(T* i, T* j){ do_destroy_array(i, j); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct array_destroyer<true>
 | 
			
		||||
{
 | 
			
		||||
   template <class T>
 | 
			
		||||
   static void destroy_array(T*, T*){}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
void do_destroy_array(T* first, T* last)
 | 
			
		||||
{
 | 
			
		||||
   while(first != last)
 | 
			
		||||
   {
 | 
			
		||||
      first->~T();
 | 
			
		||||
      ++first;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}; // namespace detail
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
inline void destroy_array(T* p1, T* p2)
 | 
			
		||||
{
 | 
			
		||||
   detail::array_destroyer<boost::has_trivial_destructor<T>::value>::destroy_array(p1, p2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// unoptimised versions of destroy_array:
 | 
			
		||||
//
 | 
			
		||||
template <class T>
 | 
			
		||||
void destroy_array1(T* first, T* last)
 | 
			
		||||
{
 | 
			
		||||
   while(first != last)
 | 
			
		||||
   {
 | 
			
		||||
      first->~T();
 | 
			
		||||
      ++first;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
template <class T>
 | 
			
		||||
void destroy_array2(T* first, T* last)
 | 
			
		||||
{
 | 
			
		||||
   for(; first != last; ++first) first->~T();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// opt::copy
 | 
			
		||||
// same semantics as std::copy
 | 
			
		||||
// calls memcpy where appropiate.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
namespace detail{
 | 
			
		||||
 | 
			
		||||
template <bool b>
 | 
			
		||||
struct copier
 | 
			
		||||
{
 | 
			
		||||
   template<typename I1, typename I2>
 | 
			
		||||
   static I2 do_copy(I1 first, I1 last, I2 out);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <bool b>
 | 
			
		||||
template<typename I1, typename I2>
 | 
			
		||||
I2 copier<b>::do_copy(I1 first, I1 last, I2 out)
 | 
			
		||||
{
 | 
			
		||||
   while(first != last)
 | 
			
		||||
   {
 | 
			
		||||
      *out = *first;
 | 
			
		||||
      ++out;
 | 
			
		||||
      ++first;
 | 
			
		||||
   }
 | 
			
		||||
   return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct copier<true>
 | 
			
		||||
{
 | 
			
		||||
   template<typename I1, typename I2>
 | 
			
		||||
   static I2* do_copy(I1* first, I1* last, I2* out)
 | 
			
		||||
   {
 | 
			
		||||
      memcpy(out, first, (last-first)*sizeof(I2));
 | 
			
		||||
      return out+(last-first);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename I1, typename I2>
 | 
			
		||||
inline I2 copy(I1 first, I1 last, I2 out)
 | 
			
		||||
{
 | 
			
		||||
   typedef typename boost::remove_cv<typename std::iterator_traits<I1>::value_type>::type v1_t;
 | 
			
		||||
   typedef typename boost::remove_cv<typename std::iterator_traits<I2>::value_type>::type v2_t;
 | 
			
		||||
   enum{ can_opt = boost::is_same<v1_t, v2_t>::value
 | 
			
		||||
                   && boost::is_pointer<I1>::value
 | 
			
		||||
                   && boost::is_pointer<I2>::value
 | 
			
		||||
                   && boost::has_trivial_assign<v1_t>::value };
 | 
			
		||||
   return detail::copier<can_opt>::do_copy(first, last, out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// fill
 | 
			
		||||
// same as std::fill, uses memset where appropriate, along with call_traits
 | 
			
		||||
// to "optimise" parameter passing.
 | 
			
		||||
//
 | 
			
		||||
namespace detail{
 | 
			
		||||
 | 
			
		||||
template <bool opt>
 | 
			
		||||
struct filler
 | 
			
		||||
{
 | 
			
		||||
   template <typename I, typename T>
 | 
			
		||||
   static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val);
 | 
			
		||||
 };
 | 
			
		||||
 | 
			
		||||
template <bool b>
 | 
			
		||||
template <typename I, typename T>
 | 
			
		||||
void filler<b>::do_fill(I first, I last, typename boost::call_traits<T>::param_type val)
 | 
			
		||||
{
 | 
			
		||||
   while(first != last)
 | 
			
		||||
   {
 | 
			
		||||
      *first = val;
 | 
			
		||||
      ++first;
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct filler<true>
 | 
			
		||||
{
 | 
			
		||||
   template <typename I, typename T>
 | 
			
		||||
   static void do_fill(I first, I last, T val)
 | 
			
		||||
   {
 | 
			
		||||
      std::memset(first, val, last-first);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class I, class T>
 | 
			
		||||
inline void fill(I first, I last, const T& val)
 | 
			
		||||
{
 | 
			
		||||
   enum{ can_opt = boost::is_pointer<I>::value
 | 
			
		||||
                   && boost::is_arithmetic<T>::value
 | 
			
		||||
                   && (sizeof(T) == 1) };
 | 
			
		||||
   typedef detail::filler<can_opt> filler_t;
 | 
			
		||||
   filler_t::template do_fill<I,T>(first, last, val);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// iter_swap:
 | 
			
		||||
// tests whether iterator is a proxying iterator or not, and
 | 
			
		||||
// uses optimal form accordingly:
 | 
			
		||||
//
 | 
			
		||||
namespace detail{
 | 
			
		||||
 | 
			
		||||
template <bool b>
 | 
			
		||||
struct swapper
 | 
			
		||||
{
 | 
			
		||||
   template <typename I>
 | 
			
		||||
   static void do_swap(I one, I two)
 | 
			
		||||
   {
 | 
			
		||||
      typedef typename std::iterator_traits<I>::value_type v_t;
 | 
			
		||||
      v_t v = *one;
 | 
			
		||||
      *one = *two;
 | 
			
		||||
      *two = v;
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
using std::swap;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct swapper<true>
 | 
			
		||||
{
 | 
			
		||||
   template <typename I>
 | 
			
		||||
   static void do_swap(I one, I two)
 | 
			
		||||
   {
 | 
			
		||||
      using std::swap;
 | 
			
		||||
      swap(*one, *two);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename I1, typename I2>
 | 
			
		||||
inline void iter_swap(I1 one, I2 two)
 | 
			
		||||
{
 | 
			
		||||
   typedef typename std::iterator_traits<I1>::reference r1_t;
 | 
			
		||||
   typedef typename std::iterator_traits<I2>::reference r2_t;
 | 
			
		||||
   enum{ can_opt = boost::is_reference<r1_t>::value && boost::is_reference<r2_t>::value && boost::is_same<r1_t, r2_t>::value };
 | 
			
		||||
   detail::swapper<can_opt>::do_swap(one, two);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
};   // namespace opt
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// define some global data:
 | 
			
		||||
//
 | 
			
		||||
const int array_size = 1000;
 | 
			
		||||
int i_array[array_size] = {0,};
 | 
			
		||||
const int ci_array[array_size] = {0,};
 | 
			
		||||
char c_array[array_size] = {0,};
 | 
			
		||||
const char cc_array[array_size] = { 0,};
 | 
			
		||||
 | 
			
		||||
const int iter_count = 1000000;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
   //
 | 
			
		||||
   // test destroy_array,
 | 
			
		||||
   // compare destruction time of an array of ints
 | 
			
		||||
   // with unoptimised form.
 | 
			
		||||
   //
 | 
			
		||||
   cout << "Measuring times in micro-seconds per 1000 elements processed" << endl << endl;
 | 
			
		||||
   cout << "testing destroy_array...\n"
 | 
			
		||||
    "[Some compilers may be able to optimise the \"unoptimised\"\n versions as well as type_traits does.]" << endl;
 | 
			
		||||
   /*cache load*/ opt::destroy_array(i_array, i_array + array_size);
 | 
			
		||||
   boost::timer t;
 | 
			
		||||
   double result;
 | 
			
		||||
   int i;
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      opt::destroy_array(i_array, i_array + array_size);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "destroy_array<int>: " << result << endl;
 | 
			
		||||
   /*cache load*/ opt::destroy_array1(i_array, i_array + array_size);
 | 
			
		||||
   t.restart();
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      opt::destroy_array1(i_array, i_array + array_size);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "destroy_array<int>(unoptimised#1): " << result << endl;
 | 
			
		||||
   /*cache load*/ opt::destroy_array2(i_array, i_array + array_size);
 | 
			
		||||
   t.restart();
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      opt::destroy_array2(i_array, i_array + array_size);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "destroy_array<int>(unoptimised#2): " << result << endl << endl;
 | 
			
		||||
 | 
			
		||||
   cout << "testing fill(char)...\n"
 | 
			
		||||
   "[Some standard library versions may already perform this optimisation.]" << endl;
 | 
			
		||||
   /*cache load*/ opt::fill<char*, char>(c_array, c_array + array_size, (char)3);
 | 
			
		||||
   t.restart();
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      opt::fill<char*, char>(c_array, c_array + array_size, (char)3);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "opt::fill<char*, char>: " << result << endl;
 | 
			
		||||
   /*cache load*/ std::fill(c_array, c_array + array_size, (char)3);
 | 
			
		||||
   t.restart();
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      std::fill(c_array, c_array + array_size, (char)3);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "std::fill<char*, char>: " << result << endl << endl;
 | 
			
		||||
 | 
			
		||||
   cout << "testing fill(int)...\n"
 | 
			
		||||
   "[Tests the effect of call_traits pass-by-value optimisation -\nthe value of this optimisation may depend upon hardware characteristics.]" << endl;
 | 
			
		||||
   /*cache load*/ opt::fill<int*, int>(i_array, i_array + array_size, 3);
 | 
			
		||||
   t.restart();
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      opt::fill<int*, int>(i_array, i_array + array_size, 3);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "opt::fill<int*, int>: " << result << endl;
 | 
			
		||||
   /*cache load*/ std::fill(i_array, i_array + array_size, 3);
 | 
			
		||||
   t.restart();
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      std::fill(i_array, i_array + array_size, 3);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "std::fill<int*, int>: " << result << endl << endl;
 | 
			
		||||
 | 
			
		||||
   cout << "testing copy...\n"
 | 
			
		||||
   "[Some standard library versions may already perform this optimisation.]" << endl;
 | 
			
		||||
   /*cache load*/ opt::copy<const int*, int*>(ci_array, ci_array + array_size, i_array);
 | 
			
		||||
   t.restart();
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      opt::copy<const int*, int*>(ci_array, ci_array + array_size, i_array);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "opt::copy<const int*, int*>: " << result << endl;
 | 
			
		||||
   /*cache load*/ std::copy<const int*, int*>(ci_array, ci_array + array_size, i_array);
 | 
			
		||||
   t.restart();
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      std::copy<const int*, int*>(ci_array, ci_array + array_size, i_array);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "std::copy<const int*, int*>: " << result << endl;
 | 
			
		||||
   /*cache load*/ opt::detail::copier<false>::template do_copy<const int*, int*>(ci_array, ci_array + array_size, i_array);
 | 
			
		||||
   t.restart();
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      opt::detail::copier<false>::template do_copy<const int*, int*>(ci_array, ci_array + array_size, i_array);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "standard \"unoptimised\" copy: " << result << endl << endl;
 | 
			
		||||
 | 
			
		||||
   /*cache load*/ opt::copy<const char*, char*>(cc_array, cc_array + array_size, c_array);
 | 
			
		||||
   t.restart();
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      opt::copy<const char*, char*>(cc_array, cc_array + array_size, c_array);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "opt::copy<const char*, char*>: " << result << endl;
 | 
			
		||||
   /*cache load*/ std::copy<const char*, char*>(cc_array, cc_array + array_size, c_array);
 | 
			
		||||
   t.restart();
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      std::copy<const char*, char*>(cc_array, cc_array + array_size, c_array);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "std::copy<const char*, char*>: " << result << endl;
 | 
			
		||||
   /*cache load*/ opt::detail::copier<false>::template do_copy<const char*, char*>(cc_array, cc_array + array_size, c_array);
 | 
			
		||||
   t.restart();
 | 
			
		||||
   for(i = 0; i < iter_count; ++i)
 | 
			
		||||
   {
 | 
			
		||||
      opt::detail::copier<false>::template do_copy<const char*, char*>(cc_array, cc_array + array_size, c_array);
 | 
			
		||||
   }
 | 
			
		||||
   result = t.elapsed();
 | 
			
		||||
   cout << "standard \"unoptimised\" copy: " << result << endl << endl;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   //
 | 
			
		||||
   // testing iter_swap
 | 
			
		||||
   // really just a check that it does in fact compile...
 | 
			
		||||
   std::vector<int> v1;
 | 
			
		||||
   v1.push_back(0);
 | 
			
		||||
   v1.push_back(1);
 | 
			
		||||
   std::vector<bool> v2;
 | 
			
		||||
   v2.push_back(0);
 | 
			
		||||
   v2.push_back(1);
 | 
			
		||||
   opt::iter_swap(v1.begin(), v1.begin()+1);
 | 
			
		||||
   opt::iter_swap(v2.begin(), v2.begin()+1);
 | 
			
		||||
 | 
			
		||||
   cout << "Press any key to exit...";
 | 
			
		||||
   cin.get();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,489 +0,0 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
<title>C++ Type traits</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
 | 
			
		||||
 | 
			
		||||
<h2 align="center">C++ Type traits</h2>
 | 
			
		||||
<p align="center"><em>by John Maddock and Steve Cleary</em></p>
 | 
			
		||||
<p align="center"><em>This is a draft of an article that will appear in a future
 | 
			
		||||
issue of </em><a href="http://www.ddj.com"><em>Dr Dobb's Journal</em></a></p>
 | 
			
		||||
<p>Generic programming (writing code which works with any data type meeting a
 | 
			
		||||
set of requirements) has become the method of choice for providing reusable
 | 
			
		||||
code. However, there are times in generic programming when "generic"
 | 
			
		||||
just isn't good enough - sometimes the differences between types are too large
 | 
			
		||||
for an efficient generic implementation. This is when the traits technique
 | 
			
		||||
becomes important - by encapsulating those properties that need to be considered
 | 
			
		||||
on a type by type basis inside a traits class, we can minimise the amount of
 | 
			
		||||
code that has to differ from one type to another, and maximise the amount of
 | 
			
		||||
generic code.</p>
 | 
			
		||||
<p>Consider an example: when working with character strings, one common
 | 
			
		||||
operation is to determine the length of a null terminated string. Clearly it's
 | 
			
		||||
possible to write generic code that can do this, but it turns out that there are
 | 
			
		||||
much more efficient methods available: for example, the C library functions <font size="2" face="Courier New">strlen</font>
 | 
			
		||||
and <font size="2" face="Courier New">wcslen</font> are usually written in
 | 
			
		||||
assembler, and with suitable hardware support can be considerably faster than a
 | 
			
		||||
generic version written in C++. The authors of the C++ standard library realised
 | 
			
		||||
this, and abstracted the properties of <font size="2" face="Courier New">char</font>
 | 
			
		||||
and <font size="2" face="Courier New">wchar_t</font> into the class <font size="2" face="Courier New">char_traits</font>.
 | 
			
		||||
Generic code that works with character strings can simply use <font size="2" face="Courier New">char_traits<>::length</font>
 | 
			
		||||
to determine the length of a null terminated string, safe in the knowledge that
 | 
			
		||||
specialisations of <font size="2" face="Courier New">char_traits</font> will use
 | 
			
		||||
the most appropriate method available to them.</p>
 | 
			
		||||
<h4>Type traits</h4>
 | 
			
		||||
<p>Class <font size="2" face="Courier New">char_traits</font> is a classic
 | 
			
		||||
example of a collection of type specific properties wrapped up in a single class
 | 
			
		||||
- what Nathan Myers termed a <i>baggage class</i>[1]. In the Boost type-traits
 | 
			
		||||
library, we[2] have written a set of very specific traits classes, each of which
 | 
			
		||||
encapsulate a single trait from the C++ type system; for example, is a type a
 | 
			
		||||
pointer or a reference type? Or does a type have a trivial constructor, or a
 | 
			
		||||
const-qualifier? The type-traits classes share a unified design: each class has
 | 
			
		||||
a single member <i>value</i>, a compile-time constant that is true if the type
 | 
			
		||||
has the specified property, and false otherwise. As we will show, these classes
 | 
			
		||||
can be used in generic programming to determine the properties of a given type
 | 
			
		||||
and introduce optimisations that are appropriate for that case.</p>
 | 
			
		||||
<p>The type-traits library also contains a set of classes that perform a
 | 
			
		||||
specific transformation on a type; for example, they can remove a top-level
 | 
			
		||||
const or volatile qualifier from a type. Each class that performs a
 | 
			
		||||
transformation defines a single typedef-member <i>type</i> that is the result of
 | 
			
		||||
the transformation. All of the type-traits classes are defined inside namespace <font size="2" face="Courier New">boost</font>;
 | 
			
		||||
for brevity, namespace-qualification is omitted in most of the code samples
 | 
			
		||||
given.</p>
 | 
			
		||||
<h4>Implementation</h4>
 | 
			
		||||
<p>There are far too many separate classes contained in the type-traits library
 | 
			
		||||
to give a full implementation here - see the source code in the Boost library
 | 
			
		||||
for the full details - however, most of the implementation is fairly repetitive
 | 
			
		||||
anyway, so here we will just give you a flavour for how some of the classes are
 | 
			
		||||
implemented. Beginning with possibly the simplest class in the library, is_void<T>
 | 
			
		||||
has a member <i>value</i> that is true only if T is void.</p>
 | 
			
		||||
<pre>template <typename T> 
 | 
			
		||||
struct is_void
 | 
			
		||||
{ static const bool value = false; };
 | 
			
		||||
 | 
			
		||||
template <> 
 | 
			
		||||
struct is_void<void>
 | 
			
		||||
{ static const bool value = true; };</pre>
 | 
			
		||||
<p>Here we define a primary version of the template class <font size="2" face="Courier New">is_void</font>,
 | 
			
		||||
and provide a full-specialisation when T is void. While full specialisation of a
 | 
			
		||||
template class is an important technique, sometimes we need a solution that is
 | 
			
		||||
halfway between a fully generic solution, and a full specialisation. This is
 | 
			
		||||
exactly the situation for which the standards committee defined partial
 | 
			
		||||
template-class specialisation. As an example, consider the class
 | 
			
		||||
boost::is_pointer<T>: here we needed a primary version that handles all
 | 
			
		||||
the cases where T is not a pointer, and a partial specialisation to handle all
 | 
			
		||||
the cases where T is a pointer:</p>
 | 
			
		||||
<pre>template <typename T> 
 | 
			
		||||
struct is_pointer 
 | 
			
		||||
{ static const bool value = false; };
 | 
			
		||||
 | 
			
		||||
template <typename T> 
 | 
			
		||||
struct is_pointer<T*> 
 | 
			
		||||
{ static const bool value = true; };</pre>
 | 
			
		||||
<p>The syntax for partial specialisation is somewhat arcane and could easily
 | 
			
		||||
occupy an article in its own right; like full specialisation, in order to write
 | 
			
		||||
a partial specialisation for a class, you must first declare the primary
 | 
			
		||||
template. The partial specialisation contains an extra <<EFBFBD>> after the
 | 
			
		||||
class name that contains the partial specialisation parameters; these define the
 | 
			
		||||
types that will bind to that partial specialisation rather than the default
 | 
			
		||||
template. The rules for what can appear in a partial specialisation are somewhat
 | 
			
		||||
convoluted, but as a rule of thumb if you can legally write two function
 | 
			
		||||
overloads of the form:</p>
 | 
			
		||||
<pre>void foo(T);
 | 
			
		||||
void foo(U);</pre>
 | 
			
		||||
<p>Then you can also write a partial specialisation of the form:</p>
 | 
			
		||||
<pre>template <typename T>
 | 
			
		||||
class c{ /*details*/ };
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
 | 
			
		||||
class c<U>{ /*details*/ };</pre>
 | 
			
		||||
<p>This rule is by no means foolproof, but it is reasonably simple to remember
 | 
			
		||||
and close enough to the actual rule to be useful for everyday use.</p>
 | 
			
		||||
<p>As a more complex example of partial specialisation consider the class
 | 
			
		||||
remove_bounds<T>. This class defines a single typedef-member <i>type</i>
 | 
			
		||||
that is the same type as T but with any top-level array bounds removed; this is
 | 
			
		||||
an example of a traits class that performs a transformation on a type:</p>
 | 
			
		||||
<pre>template <typename T> 
 | 
			
		||||
struct remove_bounds
 | 
			
		||||
{ typedef T type; };
 | 
			
		||||
 | 
			
		||||
template <typename T, std::size_t N> 
 | 
			
		||||
struct remove_bounds<T[N]>
 | 
			
		||||
{ typedef T type; };</pre>
 | 
			
		||||
<p>The aim of remove_bounds is this: imagine a generic algorithm that is passed
 | 
			
		||||
an array type as a template parameter, <font size="2" face="Courier New">remove_bounds</font>
 | 
			
		||||
provides a means of determining the underlying type of the array. For example <code>remove_bounds<int[4][5]>::type</code>
 | 
			
		||||
would evaluate to the type <code>int[5]</code>. This example also shows that the
 | 
			
		||||
number of template parameters in a partial specialisation does not have to match
 | 
			
		||||
the number in the default template. However, the number of parameters that
 | 
			
		||||
appear after the class name do have to match the number and type of the
 | 
			
		||||
parameters in the default template.</p>
 | 
			
		||||
<h4>Optimised copy</h4>
 | 
			
		||||
<p>As an example of how the type traits classes can be used, consider the
 | 
			
		||||
standard library algorithm copy:</p>
 | 
			
		||||
<pre>template<typename Iter1, typename Iter2>
 | 
			
		||||
Iter2 copy(Iter1 first, Iter1 last, Iter2 out);</pre>
 | 
			
		||||
<p>Obviously, there's no problem writing a generic version of copy that works
 | 
			
		||||
for all iterator types Iter1 and Iter2; however, there are some circumstances
 | 
			
		||||
when the copy operation can best be performed by a call to <font size="2" face="Courier New">memcpy</font>.
 | 
			
		||||
In order to implement copy in terms of <font size="2" face="Courier New">memcpy</font>
 | 
			
		||||
all of the following conditions need to be met:</p>
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>Both of the iterator types Iter1 and Iter2 must be pointers.</li>
 | 
			
		||||
  <li>Both Iter1 and Iter2 must point to the same type - excluding <font size="2" face="Courier New">const</font>
 | 
			
		||||
    and <font size="2" face="Courier New">volatile</font>-qualifiers.</li>
 | 
			
		||||
  <li>The type pointed to by Iter1 must have a trivial assignment operator.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<p>By trivial assignment operator we mean that the type is either a scalar
 | 
			
		||||
type[3] or:</p>
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>The type has no user defined assignment operator.</li>
 | 
			
		||||
  <li>The type does not have any data members that are references.</li>
 | 
			
		||||
  <li>All base classes, and all data member objects must have trivial assignment
 | 
			
		||||
    operators.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<p>If all these conditions are met then a type can be copied using <font size="2" face="Courier New">memcpy</font>
 | 
			
		||||
rather than using a compiler generated assignment operator. The type-traits
 | 
			
		||||
library provides a class <i>has_trivial_assign</i>, such that <code>has_trivial_assign<T>::value</code>
 | 
			
		||||
is true only if T has a trivial assignment operator. This class "just
 | 
			
		||||
works" for scalar types, but has to be explicitly specialised for
 | 
			
		||||
class/struct types that also happen to have a trivial assignment operator. In
 | 
			
		||||
other words if <i>has_trivial_assign</i> gives the wrong answer, it will give
 | 
			
		||||
the "safe" wrong answer - that trivial assignment is not allowable.</p>
 | 
			
		||||
<p>The code for an optimised version of copy that uses <font size="2" face="Courier New">memcpy</font>
 | 
			
		||||
where appropriate is given in listing 1. The code begins by defining a template
 | 
			
		||||
class <i>copier</i>, that takes a single Boolean template parameter, and has a
 | 
			
		||||
static template member function <font size="2" face="Courier New">do_copy</font>
 | 
			
		||||
which performs the generic version of <font size="2">copy</font> (in other words
 | 
			
		||||
the "slow but safe version"). Following that there is a specialisation
 | 
			
		||||
for <i>copier<true></i>: again this defines a static template member
 | 
			
		||||
function <font size="2" face="Courier New">do_copy</font>, but this version uses
 | 
			
		||||
memcpy to perform an "optimised" copy.</p>
 | 
			
		||||
<p>In order to complete the implementation, what we need now is a version of
 | 
			
		||||
copy, that calls <code>copier<true>::do_copy</code> if it is safe to use <font size="2" face="Courier New">memcpy</font>,
 | 
			
		||||
and otherwise calls <code>copier<false>::do_copy</code> to do a
 | 
			
		||||
"generic" copy. This is what the version in listing 1 does. To
 | 
			
		||||
understand how the code works look at the code for <font size="2" face="Courier New">copy</font>
 | 
			
		||||
and consider first the two typedefs <i>v1_t</i> and <i>v2_t</i>. These use <code>std::iterator_traits<Iter1>::value_type</code>
 | 
			
		||||
to determine what type the two iterators point to, and then feed the result into
 | 
			
		||||
another type-traits class <i>remove_cv</i> that removes the top-level
 | 
			
		||||
const-volatile-qualifiers: this will allow copy to compare the two types without
 | 
			
		||||
regard to const- or volatile-qualifiers. Next, <font size="2" face="Courier New">copy</font>
 | 
			
		||||
declares an enumerated value <i>can_opt</i> that will become the template
 | 
			
		||||
parameter to copier - declaring this here as a constant is really just a
 | 
			
		||||
convenience - the value could be passed directly to class <font size="2" face="Courier New">copier</font>.
 | 
			
		||||
The value of <i>can_opt</i> is computed by verifying that all of the following
 | 
			
		||||
are true:</p>
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>first that the two iterators point to the same type by using a type-traits
 | 
			
		||||
    class <i>is_same</i>.</li>
 | 
			
		||||
  <li>Then that both iterators are real pointers - using the class <i>is_pointer</i>
 | 
			
		||||
    described above.</li>
 | 
			
		||||
  <li>Finally that the pointed-to types have a trivial assignment operator using
 | 
			
		||||
    <i>has_trivial_assign</i>.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<p>Finally we can use the value of <i>can_opt</i> as the template argument to
 | 
			
		||||
copier - this version of copy will now adapt to whatever parameters are passed
 | 
			
		||||
to it, if its possible to use <font size="2" face="Courier New">memcpy</font>,
 | 
			
		||||
then it will do so, otherwise it will use a generic copy.</p>
 | 
			
		||||
<h4>Was it worth it?</h4>
 | 
			
		||||
<p>It has often been repeated in these columns that "premature optimisation
 | 
			
		||||
is the root of all evil" [4]. So the question must be asked: was our
 | 
			
		||||
optimisation premature? To put this in perspective the timings for our version
 | 
			
		||||
of copy compared a conventional generic copy[5] are shown in table 1.</p>
 | 
			
		||||
<p>Clearly the optimisation makes a difference in this case; but, to be fair,
 | 
			
		||||
the timings are loaded to exclude cache miss effects - without this accurate
 | 
			
		||||
comparison between algorithms becomes difficult. However, perhaps we can add a
 | 
			
		||||
couple of caveats to the premature optimisation rule:</p>
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>If you use the right algorithm for the job in the first place then
 | 
			
		||||
    optimisation will not be required; in some cases, <font size="2" face="Courier New">memcpy</font>
 | 
			
		||||
    is the right algorithm.</li>
 | 
			
		||||
  <li>If a component is going to be reused in many places by many people then
 | 
			
		||||
    optimisations may well be worthwhile where they would not be so for a single
 | 
			
		||||
    case - in other words, the likelihood that the optimisation will be
 | 
			
		||||
    absolutely necessary somewhere, sometime is that much higher. Just as
 | 
			
		||||
    importantly the perceived value of the stock implementation will be higher:
 | 
			
		||||
    there is no point standardising an algorithm if users reject it on the
 | 
			
		||||
    grounds that there are better, more heavily optimised versions available.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<h4>Table 1: Time taken to copy 1000 elements using copy<const T*, T*>
 | 
			
		||||
(times in micro-seconds)</h4>
 | 
			
		||||
<table border="1" cellpadding="7" cellspacing="1" width="529">
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="33%">
 | 
			
		||||
      <p align="center">Version</p>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="33%">
 | 
			
		||||
      <p align="center">T</p>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="33%">
 | 
			
		||||
      <p align="center">Time</p>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="33%">"Optimised" copy</td>
 | 
			
		||||
    <td valign="top" width="33%">char</td>
 | 
			
		||||
    <td valign="top" width="33%">0.99</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="33%">Conventional copy</td>
 | 
			
		||||
    <td valign="top" width="33%">char</td>
 | 
			
		||||
    <td valign="top" width="33%">8.07</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="33%">"Optimised" copy</td>
 | 
			
		||||
    <td valign="top" width="33%">int</td>
 | 
			
		||||
    <td valign="top" width="33%">2.52</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="33%">Conventional copy</td>
 | 
			
		||||
    <td valign="top" width="33%">int</td>
 | 
			
		||||
    <td valign="top" width="33%">8.02</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
</table>
 | 
			
		||||
<p> </p>
 | 
			
		||||
<h4>Pair of References</h4>
 | 
			
		||||
<p>The optimised copy example shows how type traits may be used to perform
 | 
			
		||||
optimisation decisions at compile-time. Another important usage of type traits
 | 
			
		||||
is to allow code to compile that otherwise would not do so unless excessive
 | 
			
		||||
partial specialization is used. This is possible by delegating partial
 | 
			
		||||
specialization to the type traits classes. Our example for this form of usage is
 | 
			
		||||
a pair that can hold references [6].</p>
 | 
			
		||||
<p>First, let us examine the definition of "std::pair", omitting the
 | 
			
		||||
comparision operators, default constructor, and template copy constructor for
 | 
			
		||||
simplicity:</p>
 | 
			
		||||
<pre>template <typename T1, typename T2> 
 | 
			
		||||
struct pair 
 | 
			
		||||
{
 | 
			
		||||
  typedef T1 first_type;
 | 
			
		||||
  typedef T2 second_type;
 | 
			
		||||
 | 
			
		||||
  T1 first;
 | 
			
		||||
  T2 second;
 | 
			
		||||
 | 
			
		||||
  pair(const T1 & nfirst, const T2 & nsecond)
 | 
			
		||||
  :first(nfirst), second(nsecond) { }
 | 
			
		||||
};</pre>
 | 
			
		||||
<p>Now, this "pair" cannot hold references as it currently stands,
 | 
			
		||||
because the constructor would require taking a reference to a reference, which
 | 
			
		||||
is currently illegal [7]. Let us consider what the constructor's parameters
 | 
			
		||||
would have to be in order to allow "pair" to hold non-reference types,
 | 
			
		||||
references, and constant references:</p>
 | 
			
		||||
<table border="1" cellpadding="7" cellspacing="1" width="638">
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="50%">Type of "T1"</td>
 | 
			
		||||
    <td valign="top" width="50%">Type of parameter to initializing constructor</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="50%">
 | 
			
		||||
      <pre>T</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="50%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="50%">
 | 
			
		||||
      <pre>T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="50%">
 | 
			
		||||
      <pre>T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="50%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="50%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
</table>
 | 
			
		||||
<p>A little familiarity with the type traits classes allows us to construct a
 | 
			
		||||
single mapping that allows us to determine the type of parameter from the type
 | 
			
		||||
of the contained class. The type traits classes provide a transformation "add_reference",
 | 
			
		||||
which adds a reference to its type, unless it is already a reference.</p>
 | 
			
		||||
<table border="1" cellpadding="7" cellspacing="1" width="580">
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="21%">Type of "T1"</td>
 | 
			
		||||
    <td valign="top" width="27%">Type of "const T1"</td>
 | 
			
		||||
    <td valign="top" width="53%">Type of "add_reference<const
 | 
			
		||||
      T1>::type"</td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="21%">
 | 
			
		||||
      <pre>T</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="27%">
 | 
			
		||||
      <pre>const T</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="53%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="21%">
 | 
			
		||||
      <pre>T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="27%">
 | 
			
		||||
      <pre>T & [8]</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="53%">
 | 
			
		||||
      <pre>T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
  <tr>
 | 
			
		||||
    <td valign="top" width="21%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="27%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td valign="top" width="53%">
 | 
			
		||||
      <pre>const T &</pre>
 | 
			
		||||
    </td>
 | 
			
		||||
  </tr>
 | 
			
		||||
</table>
 | 
			
		||||
<p>This allows us to build a primary template definition for "pair"
 | 
			
		||||
that can contain non-reference types, reference types, and constant reference
 | 
			
		||||
types:</p>
 | 
			
		||||
<pre>template <typename T1, typename T2> 
 | 
			
		||||
struct pair 
 | 
			
		||||
{
 | 
			
		||||
  typedef T1 first_type;
 | 
			
		||||
  typedef T2 second_type;
 | 
			
		||||
 | 
			
		||||
  T1 first;
 | 
			
		||||
  T2 second;
 | 
			
		||||
 | 
			
		||||
  pair(boost::add_reference<const T1>::type nfirst,
 | 
			
		||||
       boost::add_reference<const T2>::type nsecond)
 | 
			
		||||
  :first(nfirst), second(nsecond) { }
 | 
			
		||||
};</pre>
 | 
			
		||||
<p>Add back in the standard comparision operators, default constructor, and
 | 
			
		||||
template copy constructor (which are all the same), and you have a std::pair
 | 
			
		||||
that can hold reference types!</p>
 | 
			
		||||
<p>This same extension <i>could</i> have been done using partial template
 | 
			
		||||
specialization of "pair", but to specialize "pair" in this
 | 
			
		||||
way would require three partial specializations, plus the primary template. Type
 | 
			
		||||
traits allows us to define a single primary template that adjusts itself
 | 
			
		||||
auto-magically to any of these partial specializations, instead of a brute-force
 | 
			
		||||
partial specialization approach. Using type traits in this fashion allows
 | 
			
		||||
programmers to delegate partial specialization to the type traits classes,
 | 
			
		||||
resulting in code that is easier to maintain and easier to understand.</p>
 | 
			
		||||
<h4>Conclusion</h4>
 | 
			
		||||
<p>We hope that in this article we have been able to give you some idea of what
 | 
			
		||||
type-traits are all about. A more complete listing of the available classes are
 | 
			
		||||
in the boost documentation, along with further examples using type traits.
 | 
			
		||||
Templates have enabled C++ uses to take the advantage of the code reuse that
 | 
			
		||||
generic programming brings; hopefully this article has shown that generic
 | 
			
		||||
programming does not have to sink to the lowest common denominator, and that
 | 
			
		||||
templates can be optimal as well as generic.</p>
 | 
			
		||||
<h4>Acknowledgements</h4>
 | 
			
		||||
<p>The authors would like to thank Beman Dawes and Howard Hinnant for their
 | 
			
		||||
helpful comments when preparing this article.</p>
 | 
			
		||||
<h4>References</h4>
 | 
			
		||||
<ol>
 | 
			
		||||
  <li>Nathan C. Myers, C++ Report, June 1995.</li>
 | 
			
		||||
  <li>The type traits library is based upon contributions by Steve Cleary, Beman
 | 
			
		||||
    Dawes, Howard Hinnant and John Maddock: it can be found at www.boost.org.</li>
 | 
			
		||||
  <li>A scalar type is an arithmetic type (i.e. a built-in integer or floating
 | 
			
		||||
    point type), an enumeration type, a pointer, a pointer to member, or a
 | 
			
		||||
    const- or volatile-qualified version of one of these types.</li>
 | 
			
		||||
  <li>This quote is from Donald Knuth, ACM Computing Surveys, December 1974, pg
 | 
			
		||||
    268.</li>
 | 
			
		||||
  <li>The test code is available as part of the boost utility library (see
 | 
			
		||||
    algo_opt_examples.cpp), the code was compiled with gcc 2.95 with all
 | 
			
		||||
    optimisations turned on, tests were conducted on a 400MHz Pentium II machine
 | 
			
		||||
    running Microsoft Windows 98.</li>
 | 
			
		||||
  <li>John Maddock and Howard Hinnant have submitted a "compressed_pair"
 | 
			
		||||
    library to Boost, which uses a technique similar to the one described here
 | 
			
		||||
    to hold references. Their pair also uses type traits to determine if any of
 | 
			
		||||
    the types are empty, and will derive instead of contain to conserve space --
 | 
			
		||||
    hence the name "compressed".</li>
 | 
			
		||||
  <li>This is actually an issue with the C++ Core Language Working Group (issue
 | 
			
		||||
    #106), submitted by Bjarne Stroustrup. The tentative resolution is to allow
 | 
			
		||||
    a "reference to a reference to T" to mean the same thing as a
 | 
			
		||||
    "reference to T", but only in template instantiation, in a method
 | 
			
		||||
    similar to multiple cv-qualifiers.</li>
 | 
			
		||||
  <li>For those of you who are wondering why this shouldn't be const-qualified,
 | 
			
		||||
    remember that references are always implicitly constant (for example, you
 | 
			
		||||
    can't re-assign a reference). Remember also that "const T &"
 | 
			
		||||
    is something completely different. For this reason, cv-qualifiers on
 | 
			
		||||
    template type arguments that are references are ignored.</li>
 | 
			
		||||
</ol>
 | 
			
		||||
<h2>Listing 1</h2>
 | 
			
		||||
<pre>namespace detail{
 | 
			
		||||
 | 
			
		||||
template <bool b>
 | 
			
		||||
struct copier
 | 
			
		||||
{
 | 
			
		||||
   template<typename I1, typename I2>
 | 
			
		||||
   static I2 do_copy(I1 first, 
 | 
			
		||||
                     I1 last, I2 out);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <bool b>
 | 
			
		||||
template<typename I1, typename I2>
 | 
			
		||||
I2 copier<b>::do_copy(I1 first, 
 | 
			
		||||
                      I1 last, 
 | 
			
		||||
                      I2 out)
 | 
			
		||||
{
 | 
			
		||||
   while(first != last)
 | 
			
		||||
   {
 | 
			
		||||
      *out = *first;
 | 
			
		||||
      ++out;
 | 
			
		||||
      ++first;
 | 
			
		||||
   }
 | 
			
		||||
   return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct copier<true>
 | 
			
		||||
{
 | 
			
		||||
   template<typename I1, typename I2>
 | 
			
		||||
   static I2* do_copy(I1* first, I1* last, I2* out)
 | 
			
		||||
   {
 | 
			
		||||
      memcpy(out, first, (last-first)*sizeof(I2));
 | 
			
		||||
      return out+(last-first);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename I1, typename I2>
 | 
			
		||||
inline I2 copy(I1 first, I1 last, I2 out)
 | 
			
		||||
{
 | 
			
		||||
   typedef typename 
 | 
			
		||||
    boost::remove_cv<
 | 
			
		||||
     typename std::iterator_traits<I1>
 | 
			
		||||
      ::value_type>::type v1_t;
 | 
			
		||||
 | 
			
		||||
   typedef typename 
 | 
			
		||||
    boost::remove_cv<
 | 
			
		||||
     typename std::iterator_traits<I2>
 | 
			
		||||
      ::value_type>::type v2_t;
 | 
			
		||||
 | 
			
		||||
   enum{ can_opt = 
 | 
			
		||||
      boost::is_same<v1_t, v2_t>::value
 | 
			
		||||
      && boost::is_pointer<I1>::value
 | 
			
		||||
      && boost::is_pointer<I2>::value
 | 
			
		||||
      && boost::
 | 
			
		||||
      has_trivial_assign<v1_t>::value 
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   return detail::copier<can_opt>::
 | 
			
		||||
      do_copy(first, last, out);
 | 
			
		||||
}</pre>
 | 
			
		||||
<hr>
 | 
			
		||||
<p><EFBFBD> Copyright John Maddock and Steve Cleary, 2000</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
content="text/html; charset=iso-8859-1">
 | 
			
		||||
<meta name="Template"
 | 
			
		||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<title>Call Traits</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
@@ -34,9 +34,9 @@ specialization or member templates, no benefit will occur from
 | 
			
		||||
using call_traits: the call_traits defined types will always be
 | 
			
		||||
the same as the existing practice in this case. In addition if
 | 
			
		||||
only member templates and not partial template specialisation is
 | 
			
		||||
support by the compiler (for example Visual C++ 6) then call_traits
 | 
			
		||||
can not be used with array types (although it can be used to
 | 
			
		||||
solve the reference to reference problem).</p>
 | 
			
		||||
support by the compiler (for example Visual C++ 6) then
 | 
			
		||||
call_traits can not be used with array types (although it can be
 | 
			
		||||
used to solve the reference to reference problem).</p>
 | 
			
		||||
 | 
			
		||||
<table border="0" cellpadding="7" cellspacing="1" width="797">
 | 
			
		||||
    <tr>
 | 
			
		||||
@@ -79,7 +79,8 @@ solve the reference to reference problem).</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const T&<br>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        T&<br>
 | 
			
		||||
        (return value)</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="35%"><p align="center"><code>call_traits<T>::const_reference</code></p>
 | 
			
		||||
@@ -91,7 +92,8 @@ solve the reference to reference problem).</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const T&<br>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        T&<br>
 | 
			
		||||
        (function parameter)</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="35%"><p align="center"><code>call_traits<T>::param_type</code></p>
 | 
			
		||||
@@ -332,8 +334,8 @@ possible:</p>
 | 
			
		||||
<p>The following table shows the effect that call_traits has on
 | 
			
		||||
various types, the table assumes that the compiler supports
 | 
			
		||||
partial specialization: if it doesn't then all types behave in
 | 
			
		||||
the same way as the entry for "myclass", and call_traits
 | 
			
		||||
can not be used with reference or array types.</p>
 | 
			
		||||
the same way as the entry for "myclass", and
 | 
			
		||||
call_traits can not be used with reference or array types.</p>
 | 
			
		||||
 | 
			
		||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
 | 
			
		||||
    <tr>
 | 
			
		||||
@@ -388,7 +390,8 @@ can not be used with reference or array types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int&</p>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int const</p>
 | 
			
		||||
        </td>
 | 
			
		||||
@@ -420,7 +423,8 @@ can not be used with reference or array types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int&</p>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
@@ -432,13 +436,17 @@ can not be used with reference or array types.</p>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">const int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int&</p>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int&</p>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int&</p>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int&</p>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All
 | 
			
		||||
        constant-references.</p>
 | 
			
		||||
@@ -486,8 +494,8 @@ can not be used with reference or array types.</p>
 | 
			
		||||
 | 
			
		||||
<p>The following class is a trivial class that stores some type T
 | 
			
		||||
by value (see the <a href="call_traits_test.cpp">call_traits_test.cpp</a>
 | 
			
		||||
file), the aim is to illustrate how each of the available call_traits
 | 
			
		||||
typedefs may be used:</p>
 | 
			
		||||
file), the aim is to illustrate how each of the available
 | 
			
		||||
call_traits typedefs may be used:</p>
 | 
			
		||||
 | 
			
		||||
<pre>template <class T>
 | 
			
		||||
struct contained
 | 
			
		||||
@@ -523,14 +531,14 @@ problem):</h4>
 | 
			
		||||
 | 
			
		||||
<pre>template <class Operation> 
 | 
			
		||||
class binder1st : 
 | 
			
		||||
   public unary_function<Operation::second_argument_type, Operation::result_type> 
 | 
			
		||||
   public unary_function<typename Operation::second_argument_type, typename Operation::result_type> 
 | 
			
		||||
{ 
 | 
			
		||||
protected: 
 | 
			
		||||
   Operation op; 
 | 
			
		||||
   Operation::first_argument_type value; 
 | 
			
		||||
   typename Operation::first_argument_type value; 
 | 
			
		||||
public: 
 | 
			
		||||
   binder1st(const Operation& x, const Operation::first_argument_type& y); 
 | 
			
		||||
   Operation::result_type operator()(const Operation::second_argument_type& x) const; 
 | 
			
		||||
   binder1st(const Operation& x, const typename Operation::first_argument_type& y); 
 | 
			
		||||
   typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const; 
 | 
			
		||||
}; </pre>
 | 
			
		||||
 | 
			
		||||
<p>Now consider what happens in the relatively common case that
 | 
			
		||||
@@ -541,7 +549,7 @@ reference to a reference as an argument, and that is not
 | 
			
		||||
currently legal. The solution here is to modify <code>operator()</code>
 | 
			
		||||
to use call_traits:</p>
 | 
			
		||||
 | 
			
		||||
<pre>Operation::result_type operator()(call_traits<Operation::second_argument_type>::param_type x) const;</pre>
 | 
			
		||||
<pre>typename Operation::result_type operator()(typename call_traits<typename Operation::second_argument_type>::param_type x) const;</pre>
 | 
			
		||||
 | 
			
		||||
<p>Now in the case that <code>Operation::second_argument_type</code>
 | 
			
		||||
is a reference type, the argument is passed as a reference, and
 | 
			
		||||
@@ -575,9 +583,9 @@ std::pair<
 | 
			
		||||
degraded to pointers if the deduced types are arrays, similar
 | 
			
		||||
situations occur in the standard binders and adapters: in
 | 
			
		||||
principle in any function that "wraps" a temporary
 | 
			
		||||
whose type is deduced. Note that the function arguments to make_pair
 | 
			
		||||
are not expressed in terms of call_traits: doing so would prevent
 | 
			
		||||
template argument deduction from functioning.</p>
 | 
			
		||||
whose type is deduced. Note that the function arguments to
 | 
			
		||||
make_pair are not expressed in terms of call_traits: doing so
 | 
			
		||||
would prevent template argument deduction from functioning.</p>
 | 
			
		||||
 | 
			
		||||
<h4><a name="ex4"></a>Example 4 (optimising fill):</h4>
 | 
			
		||||
 | 
			
		||||
@@ -666,10 +674,10 @@ be any worse than existing practice.</p>
 | 
			
		||||
<p>Pointers follow the same rational as small built-in types.</p>
 | 
			
		||||
 | 
			
		||||
<p>For reference types the rational follows <a href="#refs">Example
 | 
			
		||||
2</a> - references to references are not allowed, so the call_traits
 | 
			
		||||
members must be defined such that these problems do not occur.
 | 
			
		||||
There is a proposal to modify the language such that "a
 | 
			
		||||
reference to a reference is a reference" (issue #106,
 | 
			
		||||
2</a> - references to references are not allowed, so the
 | 
			
		||||
call_traits members must be defined such that these problems do
 | 
			
		||||
not occur. There is a proposal to modify the language such that
 | 
			
		||||
"a reference to a reference is a reference" (issue #106,
 | 
			
		||||
submitted by Bjarne Stroustrup), call_traits<T>::value_type
 | 
			
		||||
and call_traits<T>::param_type both provide the same effect
 | 
			
		||||
as that proposal, without the need for a language change (in
 | 
			
		||||
@@ -687,11 +695,11 @@ struct A
 | 
			
		||||
   void foo(T t);
 | 
			
		||||
};</pre>
 | 
			
		||||
 | 
			
		||||
<p><font face="Times New Roman">In this case if we instantiate A<int[2]>
 | 
			
		||||
then the declared type of the parameter passed to member function
 | 
			
		||||
foo is int[2], but it's actual type is const int*, if we try to
 | 
			
		||||
use the type T within the function body, then there is a strong
 | 
			
		||||
likelyhood that our code will not compile:</font></p>
 | 
			
		||||
<p><font face="Times New Roman">In this case if we instantiate
 | 
			
		||||
A<int[2]> then the declared type of the parameter passed to
 | 
			
		||||
member function foo is int[2], but it's actual type is const int*,
 | 
			
		||||
if we try to use the type T within the function body, then there
 | 
			
		||||
is a strong likelyhood that our code will not compile:</font></p>
 | 
			
		||||
 | 
			
		||||
<pre>template <class T>
 | 
			
		||||
void A<T>::foo(T t)
 | 
			
		||||
@@ -706,13 +714,13 @@ declared type:</p>
 | 
			
		||||
<pre>template <class T>
 | 
			
		||||
struct A
 | 
			
		||||
{
 | 
			
		||||
   void foo(call_traits<T>::value_type t);
 | 
			
		||||
   void foo(typename call_traits<T>::value_type t);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
void A<T>::foo(call_traits<T>::value_type t)
 | 
			
		||||
void A<T>::foo(typename call_traits<T>::value_type t)
 | 
			
		||||
{
 | 
			
		||||
   call_traits<T>::value_type dup(t); // OK even if T is an array type.
 | 
			
		||||
   typename call_traits<T>::value_type dup(t); // OK even if T is an array type.
 | 
			
		||||
}</pre>
 | 
			
		||||
 | 
			
		||||
<p>For value_type (return by value), again only a pointer may be
 | 
			
		||||
@@ -743,7 +751,7 @@ Hinnant and John Maddock.</p>
 | 
			
		||||
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
 | 
			
		||||
Maddock</a>, the latest version of this file can be found at <a
 | 
			
		||||
href="http://www.boost.org/">www.boost.org</a>, and the boost
 | 
			
		||||
discussion list at <a href="http://www.egroups.com/list/boost">www.egroups.com/list/boost</a>.</p>
 | 
			
		||||
discussion list at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
 | 
			
		||||
 | 
			
		||||
<p>.</p>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@
 | 
			
		||||
#include <typeinfo>
 | 
			
		||||
#include <boost/call_traits.hpp>
 | 
			
		||||
 | 
			
		||||
#include "type_traits_test.hpp"
 | 
			
		||||
#include <boost/type_traits/type_traits_test.hpp>
 | 
			
		||||
//
 | 
			
		||||
// struct contained models a type that contains a type (for example std::pair)
 | 
			
		||||
// arrays are contained by value, and have to be treated as a special case:
 | 
			
		||||
@@ -98,18 +98,18 @@ std::pair<
 | 
			
		||||
using namespace std;
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// struct checker:
 | 
			
		||||
// struct call_traits_checker:
 | 
			
		||||
// verifies behaviour of contained example:
 | 
			
		||||
//
 | 
			
		||||
template <class T>
 | 
			
		||||
struct checker
 | 
			
		||||
struct call_traits_checker
 | 
			
		||||
{
 | 
			
		||||
   typedef typename boost::call_traits<T>::param_type param_type;
 | 
			
		||||
   void operator()(param_type);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
void checker<T>::operator()(param_type p)
 | 
			
		||||
void call_traits_checker<T>::operator()(param_type p)
 | 
			
		||||
{
 | 
			
		||||
   T t(p);
 | 
			
		||||
   contained<T> c(t);
 | 
			
		||||
@@ -117,18 +117,19 @@ void checker<T>::operator()(param_type p)
 | 
			
		||||
   assert(t == c.value());
 | 
			
		||||
   assert(t == c.get());
 | 
			
		||||
   assert(t == c.const_get());
 | 
			
		||||
 | 
			
		||||
#ifndef __ICL
 | 
			
		||||
   //cout << "typeof contained<" << typeid(T).name() << ">::v_ is:           " << typeid(&contained<T>::v_).name() << endl;
 | 
			
		||||
   cout << "typeof contained<" << typeid(T).name() << ">::value() is:      " << typeid(&contained<T>::value).name() << endl;
 | 
			
		||||
   cout << "typeof contained<" << typeid(T).name() << ">::get() is:        " << typeid(&contained<T>::get).name() << endl;
 | 
			
		||||
   cout << "typeof contained<" << typeid(T).name() << ">::const_get() is:  " << typeid(&contained<T>::const_get).name() << endl;
 | 
			
		||||
   cout << "typeof contained<" << typeid(T).name() << ">::call() is:       " << typeid(&contained<T>::call).name() << endl;
 | 
			
		||||
   cout << endl;
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
template <class T, std::size_t N>
 | 
			
		||||
struct checker<T[N]>
 | 
			
		||||
struct call_traits_checker<T[N]>
 | 
			
		||||
{
 | 
			
		||||
   typedef typename boost::call_traits<T[N]>::param_type param_type;
 | 
			
		||||
   void operator()(param_type t)
 | 
			
		||||
@@ -176,32 +177,32 @@ void check_make_pair(T c, U u, V v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct UDT
 | 
			
		||||
struct comparible_UDT
 | 
			
		||||
{
 | 
			
		||||
   int i_;
 | 
			
		||||
   UDT() : i_(2){}
 | 
			
		||||
   bool operator == (const UDT& v){ return v.i_ == i_; }
 | 
			
		||||
   comparible_UDT() : i_(2){}
 | 
			
		||||
   bool operator == (const comparible_UDT& v){ return v.i_ == i_; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
int main(int argc, char *argv[ ])
 | 
			
		||||
{
 | 
			
		||||
   checker<UDT> c1;
 | 
			
		||||
   UDT u;
 | 
			
		||||
   call_traits_checker<comparible_UDT> c1;
 | 
			
		||||
   comparible_UDT u;
 | 
			
		||||
   c1(u);
 | 
			
		||||
   checker<int> c2;
 | 
			
		||||
   call_traits_checker<int> c2;
 | 
			
		||||
   int i = 2;
 | 
			
		||||
   c2(i);
 | 
			
		||||
   int* pi = &i;
 | 
			
		||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
 | 
			
		||||
   checker<int*> c3;
 | 
			
		||||
#if (defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)) && !defined(__ICL)
 | 
			
		||||
   call_traits_checker<int*> c3;
 | 
			
		||||
   c3(pi);
 | 
			
		||||
   checker<int&> c4;
 | 
			
		||||
   call_traits_checker<int&> c4;
 | 
			
		||||
   c4(i);
 | 
			
		||||
   checker<const int&> c5;
 | 
			
		||||
   call_traits_checker<const int&> c5;
 | 
			
		||||
   c5(i);
 | 
			
		||||
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
 | 
			
		||||
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__)
 | 
			
		||||
   int a[2] = {1,2};
 | 
			
		||||
   checker<int[2]> c6;
 | 
			
		||||
   call_traits_checker<int[2]> c6;
 | 
			
		||||
   c6(a);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
@@ -220,10 +221,10 @@ int main()
 | 
			
		||||
   typedef int& r_type;
 | 
			
		||||
   typedef const r_type cr_type;
 | 
			
		||||
 | 
			
		||||
   type_test(UDT, boost::call_traits<UDT>::value_type)
 | 
			
		||||
   type_test(UDT&, boost::call_traits<UDT>::reference)
 | 
			
		||||
   type_test(const UDT&, boost::call_traits<UDT>::const_reference)
 | 
			
		||||
   type_test(const UDT&, boost::call_traits<UDT>::param_type)
 | 
			
		||||
   type_test(comparible_UDT, boost::call_traits<comparible_UDT>::value_type)
 | 
			
		||||
   type_test(comparible_UDT&, boost::call_traits<comparible_UDT>::reference)
 | 
			
		||||
   type_test(const comparible_UDT&, boost::call_traits<comparible_UDT>::const_reference)
 | 
			
		||||
   type_test(const comparible_UDT&, boost::call_traits<comparible_UDT>::param_type)
 | 
			
		||||
   type_test(int, boost::call_traits<int>::value_type)
 | 
			
		||||
   type_test(int&, boost::call_traits<int>::reference)
 | 
			
		||||
   type_test(const int&, boost::call_traits<int>::const_reference)
 | 
			
		||||
@@ -237,7 +238,7 @@ int main()
 | 
			
		||||
   type_test(int&, boost::call_traits<int&>::reference)
 | 
			
		||||
   type_test(const int&, boost::call_traits<int&>::const_reference)
 | 
			
		||||
   type_test(int&, boost::call_traits<int&>::param_type)
 | 
			
		||||
#if !(defined(__GNUC__) && (__GNUC__ < 3))
 | 
			
		||||
#if !(defined(__GNUC__) && (__GNUC__ < 4))
 | 
			
		||||
   type_test(int&, boost::call_traits<cr_type>::value_type)
 | 
			
		||||
   type_test(int&, boost::call_traits<cr_type>::reference)
 | 
			
		||||
   type_test(const int&, boost::call_traits<cr_type>::const_reference)
 | 
			
		||||
@@ -271,9 +272,7 @@ int main()
 | 
			
		||||
   test_count += 20;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   std::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit";
 | 
			
		||||
   std::cin.get();
 | 
			
		||||
   return failures;
 | 
			
		||||
   return check_result(argc, argv);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
@@ -364,3 +363,18 @@ template struct call_traits_test<int[2], true>;
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
unsigned int expected_failures = 10;
 | 
			
		||||
#elif defined(__SUNPRO_CC)
 | 
			
		||||
unsigned int expected_failures = 11;
 | 
			
		||||
#elif defined(__BORLANDC__)
 | 
			
		||||
unsigned int expected_failures = 2;
 | 
			
		||||
#elif defined(__GNUC__)
 | 
			
		||||
unsigned int expected_failures = 4;
 | 
			
		||||
#else
 | 
			
		||||
unsigned int expected_failures = 0;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										148
									
								
								cast.htm
									
									
									
									
									
								
							
							
						
						
									
										148
									
								
								cast.htm
									
									
									
									
									
								
							@@ -1,148 +0,0 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
<title>Header boost/cast.hpp Documentation</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Header
 | 
			
		||||
<a href="../../boost/cast.hpp">boost/cast.hpp</a></h1>
 | 
			
		||||
<h2><a name="Cast Functions">Cast Functions</a></h2>
 | 
			
		||||
<p>The <code>header <a href="../../boost/cast.hpp">boost/cast.hpp</a></code>
 | 
			
		||||
provides <a href="#Polymorphic_cast"><b>polymorphic_cast</b></a>, <a href="#Polymorphic_cast"><b>polymorphic_downcast</b></a>,
 | 
			
		||||
and <a href="#numeric_cast"><b>numeric_cast</b></a> template functions designed
 | 
			
		||||
to complement the C++ Standard's built-in casts.</p>
 | 
			
		||||
<p>The program <a href="cast_test.cpp">cast_test.cpp</a> can be used to
 | 
			
		||||
verify these function templates work as expected.</p>
 | 
			
		||||
<p><b>polymorphic_cast</b> was suggested by Bjarne Stroustrup in "The C++
 | 
			
		||||
Programming Language".<br>
 | 
			
		||||
<b>polymorphic_downcast</b> was contributed by <a href="../../people/dave_abrahams.htm">Dave
 | 
			
		||||
Abrahams</a>.<b><br>
 | 
			
		||||
numeric_cast</b> was contributed by <a href="../../people/kevlin_henney.htm">Kevlin
 | 
			
		||||
Henney</a>.</p>
 | 
			
		||||
<h3>Namespace synopsis</h3>
 | 
			
		||||
<blockquote>
 | 
			
		||||
  <pre>namespace boost {
 | 
			
		||||
    namespace cast {
 | 
			
		||||
        // all synopsis below included here
 | 
			
		||||
    }
 | 
			
		||||
  using ::boost::cast::polymorphic_cast;
 | 
			
		||||
  using ::boost::cast::polymorphic_downcast;
 | 
			
		||||
  using ::boost::cast::bad_numeric_cast;
 | 
			
		||||
  using ::boost::cast::numeric_cast;
 | 
			
		||||
}</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
<h3><a name="Polymorphic_cast">Polymorphic casts</a></h3>
 | 
			
		||||
<p>Pointers to polymorphic objects (objects of classes which define at least one
 | 
			
		||||
virtual function) are sometimes downcast or crosscast.  Downcasting means
 | 
			
		||||
casting from a base class to a derived class.  Crosscasting means casting
 | 
			
		||||
across an inheritance hierarchy diagram, such as from one base to the other in a
 | 
			
		||||
<b>Y</b> diagram hierarchy.</p>
 | 
			
		||||
<p>Such casts can be done with old-style casts, but this approach is never to be
 | 
			
		||||
recommended.  Old-style casts are sorely lacking in type safety, suffer
 | 
			
		||||
poor readability, and are difficult to locate with search tools.</p>
 | 
			
		||||
<p>The C++ built-in <b>static_cast</b> can be used for efficiently downcasting
 | 
			
		||||
pointers to polymorphic objects, but provides no error detection for the case
 | 
			
		||||
where the pointer being cast actually points to the wrong derived class. The <b>polymorphic_downcast</b>
 | 
			
		||||
template retains the efficiency of <b>static_cast</b> for non-debug
 | 
			
		||||
compilations, but for debug compilations adds safety via an assert() that a <b>dynamic_cast</b>
 | 
			
		||||
succeeds. <b> </b></p>
 | 
			
		||||
<p>The C++ built-in <b>dynamic_cast</b> can be used for downcasts and crosscasts
 | 
			
		||||
of pointers to polymorphic objects, but error notification in the form of a
 | 
			
		||||
returned value of 0 is inconvenient to test, or worse yet, easy to forget to
 | 
			
		||||
test.  The <b>polymorphic_cast</b> template performs a <b>dynamic_cast</b>,
 | 
			
		||||
and throws an exception if the <b>dynamic_cast</b> returns 0.</p>
 | 
			
		||||
<p>A <b>polymorphic_downcast</b> is preferred when debug-mode tests will cover
 | 
			
		||||
100% of the object types possibly cast and when non-debug-mode efficiency is an
 | 
			
		||||
issue. If these two conditions are not present, <b>polymorphic_cast</b> is
 | 
			
		||||
preferred.  It must also be used for crosscasts.  It does an assert(
 | 
			
		||||
dynamic_cast<Derived>(x) == x ) where x is the base pointer, ensuring that
 | 
			
		||||
not only is a non-zero pointer returned, but also that it correct in the
 | 
			
		||||
presence of multiple inheritance. .<b> Warning:</b>: Because <b>polymorphic_downcast</b>
 | 
			
		||||
uses assert(), it violates the One Definition Rule if NDEBUG is inconsistently
 | 
			
		||||
defined across translation units.</p>
 | 
			
		||||
<p>The C++ built-in <b>dynamic_cast</b> must be used to cast references rather
 | 
			
		||||
than pointers.  It is also the only cast that can be used to check whether
 | 
			
		||||
a given interface is supported; in that case a return of 0 isn't an error
 | 
			
		||||
condition.</p>
 | 
			
		||||
<h3>polymorphic_cast and polymorphic_downcast synopsis</h3>
 | 
			
		||||
<blockquote>
 | 
			
		||||
  <pre>template <class Derived, class Base>
 | 
			
		||||
inline Derived polymorphic_cast(Base* x);
 | 
			
		||||
// Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 )
 | 
			
		||||
// Returns: dynamic_cast<Derived>(x)
 | 
			
		||||
 | 
			
		||||
template <class Derived, class Base>
 | 
			
		||||
inline Derived polymorphic_downcast(Base* x);
 | 
			
		||||
// Effects: assert( dynamic_cast<Derived>(x) == x );
 | 
			
		||||
// Returns: static_cast<Derived>(x)</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
<h3>polymorphic_downcast example</h3>
 | 
			
		||||
<blockquote>
 | 
			
		||||
  <pre>#include <boost/cast.hpp>
 | 
			
		||||
...
 | 
			
		||||
class Fruit { public: virtual ~Fruit(){}; ... };
 | 
			
		||||
class Banana : public Fruit { ... };
 | 
			
		||||
...
 | 
			
		||||
void f( Fruit * fruit ) {
 | 
			
		||||
// ... logic which leads us to believe it is a Banana
 | 
			
		||||
  Banana * banana = boost::polymorphic_downcast<Banana*>(fruit);
 | 
			
		||||
  ...</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
<h3><a name="numeric_cast">numeric_cast</a></h3>
 | 
			
		||||
<p>A <b>static_cast</b>, <b>implicit_cast</b> or implicit conversion will not
 | 
			
		||||
detect failure to preserve range for numeric casts. The <b>numeric_cast</b>
 | 
			
		||||
template function are similar to <b>static_cast</b> and certain (dubious)
 | 
			
		||||
implicit conversions in this respect, except that they detect loss of numeric
 | 
			
		||||
range. An exception is thrown when a runtime value preservation check fails.</p>
 | 
			
		||||
<p>The requirements on the argument and result types are:</p>
 | 
			
		||||
<blockquote>
 | 
			
		||||
  <ul>
 | 
			
		||||
    <li>Both argument and result types are CopyConstructible [20.1.3].</li>
 | 
			
		||||
    <li>Both argument and result types are Numeric, defined by <code>std::numeric_limits<>::is_specialized</code>
 | 
			
		||||
      being true.</li>
 | 
			
		||||
    <li>The argument can be converted to the result type using <b>static_cast</b>.</li>
 | 
			
		||||
  </ul>
 | 
			
		||||
</blockquote>
 | 
			
		||||
<h3>numeric_cast synopsis</h3>
 | 
			
		||||
<blockquote>
 | 
			
		||||
  <pre>class bad_numeric_cast : public std::bad_cast {...};
 | 
			
		||||
 | 
			
		||||
template<typename Target, typename Source>
 | 
			
		||||
  inline Target numeric_cast(Source arg);
 | 
			
		||||
    // Throws:  bad_numeric_cast unless, in converting arg from Source to Target,
 | 
			
		||||
    //          there is no loss of negative range, and no underflow, and no
 | 
			
		||||
    //          overflow, as determined by std::numeric_limits
 | 
			
		||||
    // Returns: static_cast<Target>(arg)</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
<h3>numeric_cast example</h3>
 | 
			
		||||
<blockquote>
 | 
			
		||||
  <pre>#include <boost/cast.hpp>
 | 
			
		||||
using namespace boost::cast;
 | 
			
		||||
 | 
			
		||||
void ariane(double vx)
 | 
			
		||||
{
 | 
			
		||||
    ...
 | 
			
		||||
    unsigned short dx = numeric_cast<unsigned short>(vx);
 | 
			
		||||
    ...
 | 
			
		||||
}</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
<h3>numeric_cast rationale</h3>
 | 
			
		||||
<p>The form of the throws condition is specified so that != is not a required
 | 
			
		||||
operation.</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised  <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan
 | 
			
		||||
-->28 June, 2000<!--webbot bot="Timestamp" endspan i-checksum="19846"
 | 
			
		||||
--></p>
 | 
			
		||||
<p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and
 | 
			
		||||
distribute this document is granted provided this copyright notice appears in
 | 
			
		||||
all copies. This document is provided "as is" without express or
 | 
			
		||||
implied warranty, and with no claim as to its suitability for any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										153
									
								
								cast_test.cpp
									
									
									
									
									
								
							
							
						
						
									
										153
									
								
								cast_test.cpp
									
									
									
									
									
								
							@@ -1,153 +0,0 @@
 | 
			
		||||
//  boost utility cast test program  -----------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright boost.org 1999. Permission to copy, use, modify, sell
 | 
			
		||||
//  and distribute this software is granted provided this copyright
 | 
			
		||||
//  notice appears in all copies. This software is provided "as is" without
 | 
			
		||||
//  express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
//  any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//   28 Jun 00  implicit_cast removed (Beman Dawes)
 | 
			
		||||
//   30 Aug 99  value_cast replaced by numeric_cast
 | 
			
		||||
//    3 Aug 99  Initial Version
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <climits>
 | 
			
		||||
#include <limits>
 | 
			
		||||
#include <boost/cast.hpp>
 | 
			
		||||
 | 
			
		||||
#  if SCHAR_MAX == LONG_MAX
 | 
			
		||||
#      error "This test program doesn't work if SCHAR_MAX == LONG_MAX"
 | 
			
		||||
#  endif 
 | 
			
		||||
 | 
			
		||||
using namespace boost;
 | 
			
		||||
using std::cout;
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
    struct Base
 | 
			
		||||
    { 
 | 
			
		||||
        virtual char kind() { return 'B'; }
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    struct Base2
 | 
			
		||||
    { 
 | 
			
		||||
        virtual char kind2() { return '2'; }
 | 
			
		||||
    };
 | 
			
		||||
    
 | 
			
		||||
    struct Derived : public Base, Base2
 | 
			
		||||
    {
 | 
			
		||||
        virtual char kind() { return 'D'; }
 | 
			
		||||
    }; 
 | 
			
		||||
}   
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int main( int argc, char * argv[] )
 | 
			
		||||
{
 | 
			
		||||
    cout << "Usage: test_casts [n], where n omitted or is:\n"
 | 
			
		||||
            "  1 = execute #1 assert failure (#ifndef NDEBUG)\n"
 | 
			
		||||
            "  2 = execute #2 assert failure (#ifndef NDEBUG)\n"
 | 
			
		||||
            "Example: test_casts 2\n\n";
 | 
			
		||||
 | 
			
		||||
#   ifdef NDEBUG
 | 
			
		||||
        cout << "NDEBUG is defined\n";
 | 
			
		||||
#   else
 | 
			
		||||
        cout << "NDEBUG is not defined\n";
 | 
			
		||||
#   endif
 | 
			
		||||
 | 
			
		||||
    cout << "\nBeginning tests...\n";        
 | 
			
		||||
 | 
			
		||||
//  test polymorphic_cast  ---------------------------------------------------//
 | 
			
		||||
    
 | 
			
		||||
    //  tests which should succeed
 | 
			
		||||
    Base *    base = new Derived;
 | 
			
		||||
    Base2 *   base2 = 0;
 | 
			
		||||
    Derived * derived = 0;
 | 
			
		||||
    derived = polymorphic_downcast<Derived*>( base );  // downcast
 | 
			
		||||
    assert( derived->kind() == 'D' );
 | 
			
		||||
 | 
			
		||||
    derived = 0;
 | 
			
		||||
    derived = polymorphic_cast<Derived*>( base ); // downcast, throw on error
 | 
			
		||||
    assert( derived->kind() == 'D' );
 | 
			
		||||
 | 
			
		||||
    base2 = polymorphic_cast<Base2*>( base ); // crosscast
 | 
			
		||||
    assert( base2->kind2() == '2' );
 | 
			
		||||
 | 
			
		||||
     //  tests which should result in errors being detected
 | 
			
		||||
    int err_count = 0;
 | 
			
		||||
    base = new Base;
 | 
			
		||||
 | 
			
		||||
    if ( argc > 1 && *argv[1] == '1' )
 | 
			
		||||
        { derived = polymorphic_downcast<Derived*>( base ); } // #1 assert failure
 | 
			
		||||
 | 
			
		||||
    bool caught_exception = false;
 | 
			
		||||
    try { derived = polymorphic_cast<Derived*>( base ); }
 | 
			
		||||
    catch (std::bad_cast)
 | 
			
		||||
        { cout<<"caught bad_cast\n"; caught_exception = true; }
 | 
			
		||||
    if ( !caught_exception ) ++err_count;
 | 
			
		||||
    //  the following is just so generated code can be inspected
 | 
			
		||||
    if ( derived->kind() == 'B' ) ++err_count;
 | 
			
		||||
 | 
			
		||||
//  test implicit_cast and numeric_cast  -------------------------------------//
 | 
			
		||||
    
 | 
			
		||||
    //  tests which should succeed
 | 
			
		||||
    long small_value = 1;
 | 
			
		||||
    long small_negative_value = -1;
 | 
			
		||||
    long large_value = std::numeric_limits<long>::max();
 | 
			
		||||
    long large_negative_value = std::numeric_limits<long>::min();
 | 
			
		||||
    signed char c = 0;
 | 
			
		||||
 | 
			
		||||
    c = large_value;  // see if compiler generates warning
 | 
			
		||||
 | 
			
		||||
    c = numeric_cast<signed char>( small_value );
 | 
			
		||||
    assert( c == 1 );
 | 
			
		||||
    c = 0;
 | 
			
		||||
    c = numeric_cast<signed char>( small_value );
 | 
			
		||||
    assert( c == 1 );
 | 
			
		||||
    c = 0;
 | 
			
		||||
    c = numeric_cast<signed char>( small_negative_value );
 | 
			
		||||
    assert( c == -1 );
 | 
			
		||||
 | 
			
		||||
    // These tests courtesy of Joe R NWP Swatosh<joe.r.swatosh@usace.army.mil>
 | 
			
		||||
    assert( 0.0f == numeric_cast<float>( 0.0 ) );
 | 
			
		||||
    assert( 0.0 == numeric_cast<double>( 0.0 ) );
 | 
			
		||||
    
 | 
			
		||||
    //  tests which should result in errors being detected
 | 
			
		||||
 | 
			
		||||
    caught_exception = false;
 | 
			
		||||
    try { c = numeric_cast<signed char>( large_value ); }
 | 
			
		||||
    catch (bad_numeric_cast)
 | 
			
		||||
        { cout<<"caught bad_numeric_cast #1\n"; caught_exception = true; }
 | 
			
		||||
    if ( !caught_exception ) ++err_count;
 | 
			
		||||
 | 
			
		||||
    caught_exception = false;
 | 
			
		||||
    try { c = numeric_cast<signed char>( large_negative_value ); }
 | 
			
		||||
    catch (bad_numeric_cast)
 | 
			
		||||
        { cout<<"caught bad_numeric_cast #2\n"; caught_exception = true; }
 | 
			
		||||
    if ( !caught_exception ) ++err_count;
 | 
			
		||||
 | 
			
		||||
    unsigned long ul;
 | 
			
		||||
    caught_exception = false;
 | 
			
		||||
    try { ul = numeric_cast<unsigned long>( large_negative_value ); }
 | 
			
		||||
    catch (bad_numeric_cast)
 | 
			
		||||
        { cout<<"caught bad_numeric_cast #3\n"; caught_exception = true; }
 | 
			
		||||
    if ( !caught_exception ) ++err_count;
 | 
			
		||||
 | 
			
		||||
    caught_exception = false;
 | 
			
		||||
    try { ul = numeric_cast<unsigned long>( small_negative_value ); }
 | 
			
		||||
    catch (bad_numeric_cast)
 | 
			
		||||
        { cout<<"caught bad_numeric_cast #4\n"; caught_exception = true; }
 | 
			
		||||
    if ( !caught_exception ) ++err_count;
 | 
			
		||||
 | 
			
		||||
    caught_exception = false;
 | 
			
		||||
    try { numeric_cast<int>( std::numeric_limits<double>::max() ); }
 | 
			
		||||
    catch (bad_numeric_cast)
 | 
			
		||||
        { cout<<"caught bad_numeric_cast #5\n"; caught_exception = true; }
 | 
			
		||||
    if ( !caught_exception ) ++err_count;
 | 
			
		||||
 | 
			
		||||
    cout << err_count << " errors detected\nTest "
 | 
			
		||||
         << (err_count==0 ? "passed\n" : "failed\n");
 | 
			
		||||
    return err_count;
 | 
			
		||||
}   // main
 | 
			
		||||
							
								
								
									
										31
									
								
								checked_delete_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								checked_delete_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
//  Boost checked_delete test program  ---------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Beman Dawes 2001. Permission to copy, use, modify, sell
 | 
			
		||||
//  and distribute this software is granted provided this copyright
 | 
			
		||||
//  notice appears in all copies. This software is provided "as is" without
 | 
			
		||||
//  express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
//  any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  21 May 01  Initial version (Beman Dawes)
 | 
			
		||||
 | 
			
		||||
#include <boost/utility.hpp>  // for checked_delete
 | 
			
		||||
 | 
			
		||||
//  This program demonstrates compiler errors when trying to delete an
 | 
			
		||||
//  incomplete type.
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
{
 | 
			
		||||
    class Incomplete;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    Incomplete * p;
 | 
			
		||||
    boost::checked_delete(p);          // should cause compile time error
 | 
			
		||||
    Incomplete ** pa;
 | 
			
		||||
    boost::checked_array_delete(pa);   // should cause compile time error
 | 
			
		||||
    return 0;
 | 
			
		||||
}   // main
 | 
			
		||||
@@ -6,14 +6,15 @@ content="text/html; charset=iso-8859-1">
 | 
			
		||||
<meta name="Template"
 | 
			
		||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
 | 
			
		||||
<title>Header <boost/compressed_pair.hpp></title>
 | 
			
		||||
<title>Header </title>
 | 
			
		||||
<boost/compressed_pair.hpp>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
 | 
			
		||||
vlink="#800080">
 | 
			
		||||
 | 
			
		||||
<h2><img src="../../c++boost.gif" width="276" height="86">Header
 | 
			
		||||
<<a href="../../boost/detail/call_traits.hpp">boost/compressed_pair.hpp</a>></h2>
 | 
			
		||||
<<a href="../../boost/detail/compressed_pair.hpp">boost/compressed_pair.hpp</a>></h2>
 | 
			
		||||
 | 
			
		||||
<p>All of the contents of <boost/compressed_pair.hpp> are
 | 
			
		||||
defined inside namespace boost.</p>
 | 
			
		||||
@@ -41,6 +42,8 @@ public:
 | 
			
		||||
	explicit compressed_pair(first_param_type x);
 | 
			
		||||
	explicit compressed_pair(second_param_type y);
 | 
			
		||||
 | 
			
		||||
	compressed_pair& operator=(const compressed_pair&);
 | 
			
		||||
 | 
			
		||||
	first_reference       first();
 | 
			
		||||
	first_const_reference first() const;
 | 
			
		||||
 | 
			
		||||
@@ -61,17 +64,19 @@ constructor, and this constructor initialises both values in the
 | 
			
		||||
pair to the passed value.</p>
 | 
			
		||||
 | 
			
		||||
<p>Note that compressed_pair can not be instantiated if either of
 | 
			
		||||
the template arguments is an enumerator type, unless there is
 | 
			
		||||
compiler support for boost::is_enum, or if boost::is_enum is
 | 
			
		||||
specialised for the enumerator type.</p>
 | 
			
		||||
the template arguments is a union type, unless there is compiler
 | 
			
		||||
support for boost::is_union, or if boost::is_union is specialised
 | 
			
		||||
for the union type.</p>
 | 
			
		||||
 | 
			
		||||
<p>Finally, compressed_pair requires compiler support for partial
 | 
			
		||||
specialisation of class templates - without that support
 | 
			
		||||
compressed_pair behaves just like std::pair.</p>
 | 
			
		||||
<p>Finally, a word of caution for Visual C++ 6 users: if either
 | 
			
		||||
argument is an empty type, then assigning to that member will
 | 
			
		||||
produce memory corruption, unless the empty type has a "do
 | 
			
		||||
nothing" assignment operator defined. This is due to a bug
 | 
			
		||||
in the way VC6 generates implicit assignment operators.</p>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
<p>Revised 08 March 2000</p>
 | 
			
		||||
<p>Revised 08 May 2001</p>
 | 
			
		||||
 | 
			
		||||
<p><EFBFBD> Copyright boost.org 2000. Permission to copy, use, modify,
 | 
			
		||||
sell and distribute this document is granted provided this
 | 
			
		||||
@@ -85,7 +90,8 @@ Hinnant and John Maddock.</p>
 | 
			
		||||
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
 | 
			
		||||
Maddock</a>, the latest version of this file can be found at <a
 | 
			
		||||
href="http://www.boost.org">www.boost.org</a>, and the boost
 | 
			
		||||
discussion list at <a href="http://www.egroups.com/list/boost">www.egroups.com/list/boost</a>.</p>
 | 
			
		||||
discussion list at <a
 | 
			
		||||
href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
</body>
 | 
			
		||||
 
 | 
			
		||||
@@ -14,15 +14,12 @@
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 | 
			
		||||
#include <boost/compressed_pair.hpp>
 | 
			
		||||
#include "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;
 | 
			
		||||
 | 
			
		||||
struct empty_POD_UDT{};
 | 
			
		||||
struct empty_UDT
 | 
			
		||||
{
 | 
			
		||||
  ~empty_UDT(){};
 | 
			
		||||
};
 | 
			
		||||
namespace boost {
 | 
			
		||||
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
 | 
			
		||||
template <> struct is_empty<empty_UDT>
 | 
			
		||||
@@ -59,97 +56,345 @@ struct non_empty2
 | 
			
		||||
   { return a.i == b.i; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
   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<empty_UDT, int> cp2(2);
 | 
			
		||||
   assert(cp2.second() == 2);
 | 
			
		||||
   compressed_pair<int, empty_UDT> cp3(1);
 | 
			
		||||
   assert(cp3.first() ==1);
 | 
			
		||||
   compressed_pair<empty_UDT, empty_UDT> cp4;
 | 
			
		||||
   compressed_pair<empty_UDT, empty_POD_UDT> cp5;
 | 
			
		||||
   compressed_pair<int, empty_UDT> cp9(empty_UDT());
 | 
			
		||||
   compressed_pair<int, empty_UDT> cp10(1);
 | 
			
		||||
   assert(cp10.first() == 1);
 | 
			
		||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) || !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
 | 
			
		||||
   int i = 0;
 | 
			
		||||
   compressed_pair<int&, int&> cp6(i,i);
 | 
			
		||||
   assert(cp6.first() == i);
 | 
			
		||||
   assert(cp6.second() == i);
 | 
			
		||||
   assert(&cp6.first() == &i);
 | 
			
		||||
   assert(&cp6.second() == &i);
 | 
			
		||||
   compressed_pair<int, double[2]> cp7;
 | 
			
		||||
   cp7.first();
 | 
			
		||||
   double* pd = cp7.second();
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
using std::swap;
 | 
			
		||||
#endif
 | 
			
		||||
   value_test(true, (sizeof(compressed_pair<empty_UDT, int>) < sizeof(std::pair<empty_UDT, int>)))
 | 
			
		||||
   value_test(true, (sizeof(compressed_pair<int, empty_UDT>) < sizeof(std::pair<int, empty_UDT>)))
 | 
			
		||||
   value_test(true, (sizeof(compressed_pair<empty_UDT, empty_UDT>) < sizeof(std::pair<empty_UDT, empty_UDT>)))
 | 
			
		||||
   value_test(true, (sizeof(compressed_pair<empty_UDT, empty_POD_UDT>) < sizeof(std::pair<empty_UDT, empty_POD_UDT>)))
 | 
			
		||||
   value_test(true, (sizeof(compressed_pair<empty_UDT, compressed_pair<empty_POD_UDT, int> >) < sizeof(std::pair<empty_UDT, std::pair<empty_POD_UDT, int> >)))
 | 
			
		||||
 | 
			
		||||
   std::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit";
 | 
			
		||||
   std::cin.get();
 | 
			
		||||
   return failures;
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
struct compressed_pair_tester
 | 
			
		||||
{
 | 
			
		||||
   // define the types we need:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   // define our test proc:
 | 
			
		||||
   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
 | 
			
		||||
{
 | 
			
		||||
#ifndef __GNUC__
 | 
			
		||||
   // gcc 2.90 can't cope with function scope using
 | 
			
		||||
   // declarations, and generates an internal compiler error...
 | 
			
		||||
   using std::swap;
 | 
			
		||||
#endif
 | 
			
		||||
   // default construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp1;
 | 
			
		||||
   // first param construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp2(p1);
 | 
			
		||||
   cp2.second() = p2;
 | 
			
		||||
   BOOST_TEST(cp2.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp2.second() == p2);
 | 
			
		||||
   // second param construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp3(p2);
 | 
			
		||||
   cp3.first() = p1;
 | 
			
		||||
   BOOST_TEST(cp3.second() == p2);
 | 
			
		||||
   BOOST_TEST(cp3.first() == p1);
 | 
			
		||||
   // both param construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp4(p1, p2);
 | 
			
		||||
   BOOST_TEST(cp4.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp4.second() == p2);
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp5(p3, p4);
 | 
			
		||||
   BOOST_TEST(cp5.first() == p3);
 | 
			
		||||
   BOOST_TEST(cp5.second() == p4);
 | 
			
		||||
   // check const members:
 | 
			
		||||
   const boost::compressed_pair<T1,T2>& cpr1 = cp4;
 | 
			
		||||
   BOOST_TEST(cpr1.first() == p1);
 | 
			
		||||
   BOOST_TEST(cpr1.second() == p2);
 | 
			
		||||
 | 
			
		||||
   // copy construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp6(cp4);
 | 
			
		||||
   BOOST_TEST(cp6.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp6.second() == p2);
 | 
			
		||||
   // assignment:
 | 
			
		||||
   cp1 = cp4;
 | 
			
		||||
   BOOST_TEST(cp1.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp1.second() == p2);
 | 
			
		||||
   cp1 = cp5;
 | 
			
		||||
   BOOST_TEST(cp1.first() == p3);
 | 
			
		||||
   BOOST_TEST(cp1.second() == p4);
 | 
			
		||||
   // swap:
 | 
			
		||||
   cp4.swap(cp5);
 | 
			
		||||
   BOOST_TEST(cp4.first() == p3);
 | 
			
		||||
   BOOST_TEST(cp4.second() == p4);
 | 
			
		||||
   BOOST_TEST(cp5.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp5.second() == p2);
 | 
			
		||||
   swap(cp4,cp5);
 | 
			
		||||
   BOOST_TEST(cp4.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp4.second() == p2);
 | 
			
		||||
   BOOST_TEST(cp5.first() == p3);
 | 
			
		||||
   BOOST_TEST(cp5.second() == p4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// instanciate some compressed pairs:
 | 
			
		||||
#ifdef __MWERKS__
 | 
			
		||||
template class compressed_pair<int, double>;
 | 
			
		||||
template class compressed_pair<int, int>;
 | 
			
		||||
template class compressed_pair<empty_UDT, int>;
 | 
			
		||||
template class compressed_pair<int, empty_UDT>;
 | 
			
		||||
template class compressed_pair<empty_UDT, empty_UDT>;
 | 
			
		||||
template class compressed_pair<empty_UDT, empty_POD_UDT>;
 | 
			
		||||
#else
 | 
			
		||||
template class boost::compressed_pair<int, double>;
 | 
			
		||||
template class boost::compressed_pair<int, int>;
 | 
			
		||||
template class boost::compressed_pair<empty_UDT, int>;
 | 
			
		||||
template class boost::compressed_pair<int, empty_UDT>;
 | 
			
		||||
template class boost::compressed_pair<empty_UDT, empty_UDT>;
 | 
			
		||||
template class boost::compressed_pair<empty_UDT, empty_POD_UDT>;
 | 
			
		||||
#endif
 | 
			
		||||
// tests for case where one or both 
 | 
			
		||||
// parameters are reference types:
 | 
			
		||||
//
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
struct compressed_pair_reference_tester
 | 
			
		||||
{
 | 
			
		||||
   // define the types we need:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   // define our test proc:
 | 
			
		||||
   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_reference_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
 | 
			
		||||
{
 | 
			
		||||
#ifndef __GNUC__
 | 
			
		||||
   // gcc 2.90 can't cope with function scope using
 | 
			
		||||
   // declarations, and generates an internal compiler error...
 | 
			
		||||
   using std::swap;
 | 
			
		||||
#endif
 | 
			
		||||
   // both param construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp4(p1, p2);
 | 
			
		||||
   BOOST_TEST(cp4.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp4.second() == p2);
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp5(p3, p4);
 | 
			
		||||
   BOOST_TEST(cp5.first() == p3);
 | 
			
		||||
   BOOST_TEST(cp5.second() == p4);
 | 
			
		||||
   // check const members:
 | 
			
		||||
   const boost::compressed_pair<T1,T2>& cpr1 = cp4;
 | 
			
		||||
   BOOST_TEST(cpr1.first() == p1);
 | 
			
		||||
   BOOST_TEST(cpr1.second() == p2);
 | 
			
		||||
 | 
			
		||||
   // copy construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp6(cp4);
 | 
			
		||||
   BOOST_TEST(cp6.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp6.second() == p2);
 | 
			
		||||
   // assignment:
 | 
			
		||||
   // VC6 bug:
 | 
			
		||||
   // When second() is an empty class, VC6 performs the
 | 
			
		||||
   // assignment by doing a memcpy - even though the empty
 | 
			
		||||
   // class is really a zero sized base class, the result
 | 
			
		||||
   // is that the memory of first() gets trampled over.
 | 
			
		||||
   // Similar arguments apply to the case that first() is 
 | 
			
		||||
   // an empty base class.
 | 
			
		||||
   // Strangely the problem is dependent upon the compiler
 | 
			
		||||
   // settings - some generate the problem others do not.
 | 
			
		||||
   cp4.first() = p3;
 | 
			
		||||
   cp4.second() = p4;
 | 
			
		||||
   BOOST_TEST(cp4.first() == p3);
 | 
			
		||||
   BOOST_TEST(cp4.second() == p4);
 | 
			
		||||
}
 | 
			
		||||
//
 | 
			
		||||
// supplimentary tests for case where first arg only is a reference type:
 | 
			
		||||
//
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
struct compressed_pair_reference1_tester
 | 
			
		||||
{
 | 
			
		||||
   // define the types we need:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   // define our test proc:
 | 
			
		||||
   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_reference1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
 | 
			
		||||
{
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
#ifndef __MWERKS__
 | 
			
		||||
   // first param construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp2(p1);
 | 
			
		||||
   cp2.second() = p2;
 | 
			
		||||
   BOOST_TEST(cp2.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp2.second() == p2);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
//
 | 
			
		||||
// now some for which only a few specific members can be instantiated,
 | 
			
		||||
// first references:
 | 
			
		||||
template double& compressed_pair<double, int&>::first();
 | 
			
		||||
template int& compressed_pair<double, int&>::second();
 | 
			
		||||
#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95))
 | 
			
		||||
template compressed_pair<double, int&>::compressed_pair(int&);
 | 
			
		||||
#endif
 | 
			
		||||
template compressed_pair<double, int&>::compressed_pair(call_traits<double>::param_type,int&);
 | 
			
		||||
// supplimentary tests for case where second arg only is a reference type:
 | 
			
		||||
//
 | 
			
		||||
// and then arrays:
 | 
			
		||||
#ifndef __BORLANDC__
 | 
			
		||||
template call_traits<int[2]>::reference compressed_pair<double, int[2]>::second();
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
struct compressed_pair_reference2_tester
 | 
			
		||||
{
 | 
			
		||||
   // define the types we need:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   // define our test proc:
 | 
			
		||||
   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_reference2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
 | 
			
		||||
{
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
   // second param construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp3(p2);
 | 
			
		||||
   cp3.first() = p1;
 | 
			
		||||
   BOOST_TEST(cp3.second() == p2);
 | 
			
		||||
   BOOST_TEST(cp3.first() == p1);
 | 
			
		||||
#endif
 | 
			
		||||
template call_traits<double>::reference compressed_pair<double, int[2]>::first();
 | 
			
		||||
#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95))
 | 
			
		||||
template compressed_pair<double, int[2]>::compressed_pair(call_traits<double>::param_type);
 | 
			
		||||
#endif
 | 
			
		||||
template compressed_pair<double, int[2]>::compressed_pair();
 | 
			
		||||
#endif // __MWERKS__
 | 
			
		||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
unsigned int expected_failures = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										325
									
								
								counting_iterator.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										325
									
								
								counting_iterator.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,325 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
<title>Counting Iterator Adaptor Documentation</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
 | 
			
		||||
align="center" width="277" height="86">
 | 
			
		||||
 | 
			
		||||
<h1>Counting Iterator Adaptor</h1>
 | 
			
		||||
 | 
			
		||||
Defined in header
 | 
			
		||||
<a href="../../boost/counting_iterator.hpp">boost/counting_iterator.hpp</a>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
How would you fill up a vector with the numbers zero
 | 
			
		||||
through one hundred using <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/copy.html"><tt>std::copy()</tt></a>? The
 | 
			
		||||
only iterator operation missing from builtin integer types is an
 | 
			
		||||
<tt>operator*()</tt> that returns the current
 | 
			
		||||
value of the integer.  The counting iterator adaptor adds this crucial piece of
 | 
			
		||||
functionality to whatever type it wraps. One can use the
 | 
			
		||||
counting iterator adaptor not only with integer types, but with any
 | 
			
		||||
type that is <tt>Incrementable</tt> (see type requirements <a href="#requirements">below</a>).  The
 | 
			
		||||
following <b>pseudo-code</b> shows the general idea of how the
 | 
			
		||||
counting iterator is implemented.
 | 
			
		||||
</p>
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
  // inside a hypothetical counting_iterator class...
 | 
			
		||||
  typedef Incrementable value_type;
 | 
			
		||||
  value_type counting_iterator::operator*() const {
 | 
			
		||||
    return this->base; // no dereference!
 | 
			
		||||
  }
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
All of the other operators of the counting iterator behave in the same
 | 
			
		||||
fashion as the <tt>Incrementable</tt> base type.
 | 
			
		||||
 | 
			
		||||
<h2>Synopsis</h2>
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
namespace boost {
 | 
			
		||||
  template <class Incrementable>
 | 
			
		||||
  struct <a href="#counting_iterator_traits">counting_iterator_traits</a>;
 | 
			
		||||
 | 
			
		||||
  template <class Incrementable>
 | 
			
		||||
  struct <a href="#counting_iterator_generator">counting_iterator_generator</a>;
 | 
			
		||||
 | 
			
		||||
  template <class Incrementable>
 | 
			
		||||
  typename counting_iterator_generator<Incrementable>::type
 | 
			
		||||
  <a href="#make_counting_iterator">make_counting_iterator</a>(Incrementable x);
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
<h2><a name="counting_iterator_generator">The Counting Iterator Type
 | 
			
		||||
Generator</a></h2>
 | 
			
		||||
 | 
			
		||||
The class template <tt>counting_iterator_generator<Incrementable></tt> is a <a href="../../more/generic_programming.html#type_generator">type generator</a> for counting iterators.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
template <class Incrementable>
 | 
			
		||||
class counting_iterator_generator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    typedef <a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...> type;
 | 
			
		||||
};
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<h3>Example</h3>
 | 
			
		||||
 | 
			
		||||
In this example we use the counting iterator generator to create a
 | 
			
		||||
counting iterator, and count from zero to four.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <boost/counting_iterator.hpp>
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  // Example of using counting_iterator_generator
 | 
			
		||||
  std::cout << "counting from 0 to 4:" << std::endl;
 | 
			
		||||
  boost::counting_iterator_generator<int>::type first(0), last(4);
 | 
			
		||||
  std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // to be continued...
 | 
			
		||||
</pre>
 | 
			
		||||
The output from this part is:
 | 
			
		||||
<pre>
 | 
			
		||||
counting from 0 to 4:
 | 
			
		||||
0 1 2 3 
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<h3>Template Parameters</h3>
 | 
			
		||||
 | 
			
		||||
<Table border>
 | 
			
		||||
<TR>
 | 
			
		||||
<TH>Parameter</TH><TH>Description</TH>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><tt>Incrementable</tt></TD>
 | 
			
		||||
<TD>The type being wrapped by the adaptor.</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
</Table>
 | 
			
		||||
 | 
			
		||||
<h3>Model of</h3>
 | 
			
		||||
 | 
			
		||||
If the <tt>Incrementable</tt> type has all of the functionality of a
 | 
			
		||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
 | 
			
		||||
Access Iterator</a> except the <tt>operator*()</tt>, then the counting
 | 
			
		||||
iterator will be a model of <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
 | 
			
		||||
Access Iterator</a>. If the <tt>Incrementable</tt> type has less
 | 
			
		||||
functionality, then the counting iterator will have correspondingly
 | 
			
		||||
less functionality.
 | 
			
		||||
 | 
			
		||||
<h3><a name="requirements">Type Requirements</a></h3>
 | 
			
		||||
 | 
			
		||||
The <tt>Incrementable</tt> type must be <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default
 | 
			
		||||
Constructible</a>, <a href="./CopyConstructible.html">Copy
 | 
			
		||||
Constructible</a>, and <a href="./Assignable.html">Assignable</a>.
 | 
			
		||||
Also, the <tt>Incrementable</tt> type must provide access to an
 | 
			
		||||
associated <tt>difference_type</tt> and <tt>iterator_category</tt>
 | 
			
		||||
through the <a
 | 
			
		||||
href="#counting_iterator_traits"><tt>counting_iterator_traits</tt></a>
 | 
			
		||||
class.
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
Furthermore, if you wish to create a counting iterator that is a <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/ForwardIterator.html"> Forward
 | 
			
		||||
Iterator</a>, then the following expressions must be valid:
 | 
			
		||||
<pre>
 | 
			
		||||
Incrementable i, j;
 | 
			
		||||
++i         // pre-increment
 | 
			
		||||
i == j      // operator equal
 | 
			
		||||
</pre>
 | 
			
		||||
If you wish to create a counting iterator that is a <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">
 | 
			
		||||
Bidirectional Iterator</a>, then pre-decrement is also required:
 | 
			
		||||
<pre>
 | 
			
		||||
--i
 | 
			
		||||
</pre>
 | 
			
		||||
If you wish to create a counting iterator that is a <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html"> Random
 | 
			
		||||
Access Iterator</a>, then these additional expressions are also required:
 | 
			
		||||
<pre>
 | 
			
		||||
<a href="#counting_iterator_traits">counting_iterator_traits</a><Incrementable>::difference_type n;
 | 
			
		||||
i += n
 | 
			
		||||
n = i - j
 | 
			
		||||
i < j
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Members</h3>
 | 
			
		||||
 | 
			
		||||
The counting iterator type implements the member functions and
 | 
			
		||||
operators required of the <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
 | 
			
		||||
Access Iterator</a> concept. In addition it has the following
 | 
			
		||||
constructor:
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
counting_iterator_generator::type(const Incrementable& i)
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h2><a name="make_counting_iterator">The Counting Iterator Object Generator</a></h2>
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
template <class Incrementable>
 | 
			
		||||
typename counting_iterator_generator<Incrementable>::type
 | 
			
		||||
make_counting_iterator(Incrementable base);
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
An <a href="../../more/generic_programming.html#object_generator">object
 | 
			
		||||
generator</a> function that provides a convenient way to create counting
 | 
			
		||||
iterators.<p>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Example</h3>
 | 
			
		||||
 | 
			
		||||
In this example we count from negative five to positive five, this
 | 
			
		||||
time using the <tt>make_counting_iterator()</tt> function to save some
 | 
			
		||||
typing.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
  // continuing from previous example...
 | 
			
		||||
 | 
			
		||||
  std::cout << "counting from -5 to 4:" << std::endl;
 | 
			
		||||
  std::copy(boost::make_counting_iterator(-5),
 | 
			
		||||
	    boost::make_counting_iterator(5),
 | 
			
		||||
	    std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // to be continued...
 | 
			
		||||
</pre>
 | 
			
		||||
The output from this part is:
 | 
			
		||||
<pre>
 | 
			
		||||
counting from -5 to 4:
 | 
			
		||||
-5 -4 -3 -2 -1 0 1 2 3 4 
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
In the next example we create an array of numbers, and then create a
 | 
			
		||||
second array of pointers, where each pointer is the address of a
 | 
			
		||||
number in the first array. The counting iterator makes it easy to do
 | 
			
		||||
this since dereferencing a counting iterator that is wrapping an
 | 
			
		||||
iterator over the array of numbers just returns a pointer to the
 | 
			
		||||
current location in the array. We then use the <a
 | 
			
		||||
href="./indirect_iterator.htm">indirect iterator adaptor</a> to print
 | 
			
		||||
out the number in the array by accessing the numbers through the array
 | 
			
		||||
of pointers.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
  // continuing from previous example...
 | 
			
		||||
 | 
			
		||||
  const int N = 7;
 | 
			
		||||
  std::vector<int> numbers;
 | 
			
		||||
  // Fill "numbers" array with [0,N)
 | 
			
		||||
  std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N),
 | 
			
		||||
	    std::back_inserter(numbers));
 | 
			
		||||
 | 
			
		||||
  std::vector<std::vector<int>::iterator> pointers;
 | 
			
		||||
 | 
			
		||||
  // Use counting iterator to fill in the array of pointers.
 | 
			
		||||
  std::copy(boost::make_counting_iterator(numbers.begin()),
 | 
			
		||||
	    boost::make_counting_iterator(numbers.end()),
 | 
			
		||||
	    std::back_inserter(pointers));
 | 
			
		||||
 | 
			
		||||
  // Use indirect iterator to print out numbers by accessing
 | 
			
		||||
  // them through the array of pointers.
 | 
			
		||||
  std::cout << "indirectly printing out the numbers from 0 to " 
 | 
			
		||||
	    << N << std::endl;
 | 
			
		||||
  std::copy(boost::make_indirect_iterator(pointers.begin()),
 | 
			
		||||
	    boost::make_indirect_iterator(pointers.end()),
 | 
			
		||||
	    std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
</pre>
 | 
			
		||||
The output is:
 | 
			
		||||
<pre>
 | 
			
		||||
indirectly printing out the numbers from 0 to 7
 | 
			
		||||
0 1 2 3 4 5 6 
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
<h2><a name="counting_iterator_traits">Counting Iterator Traits</a></h2>
 | 
			
		||||
 | 
			
		||||
The counting iterator adaptor needs to determine the appropriate
 | 
			
		||||
<tt>difference_type</tt> and <tt>iterator_category</tt> to use based on the
 | 
			
		||||
<tt>Incrementable</tt> type supplied by the user.  The
 | 
			
		||||
<tt>counting_iterator_traits</tt> class provides these types.  If the
 | 
			
		||||
<tt>Incrementable</tt> type is an integral type or an iterator, these types
 | 
			
		||||
will be correctly deduced by the <tt>counting_iterator_traits</tt> provided by
 | 
			
		||||
the library. Otherwise, the user must specialize
 | 
			
		||||
<tt>counting_iterator_traits</tt> for her type or add nested typedefs to
 | 
			
		||||
her type to fulfill the needs of
 | 
			
		||||
<a href="http://www.sgi.com/tech/stl/iterator_traits.html">
 | 
			
		||||
<tt>std::iterator_traits</tt></a>.
 | 
			
		||||
 | 
			
		||||
<p>The following pseudocode describes how the <tt>counting_iterator_traits</tt> are determined:
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
template <class Incrementable>
 | 
			
		||||
struct counting_iterator_traits
 | 
			
		||||
{
 | 
			
		||||
  if (numeric_limits<Incrementable>::is_specialized) {
 | 
			
		||||
    if (!numeric_limits<Incrementable>::is_integer)
 | 
			
		||||
       COMPILE_TIME_ERROR;
 | 
			
		||||
 | 
			
		||||
    if (!numeric_limits<Incrementable>::is_bounded
 | 
			
		||||
        && numeric_limits<Incrementable>::is_signed) {
 | 
			
		||||
        typedef Incrementable difference_type;
 | 
			
		||||
    }
 | 
			
		||||
    else if (numeric_limits<Incrementable>::is_integral) {
 | 
			
		||||
        typedef <i>next-larger-signed-type-or-intmax_t</i> difference_type;
 | 
			
		||||
    }
 | 
			
		||||
    typedef std::random_access_iterator_tag iterator_category;   
 | 
			
		||||
  } else {
 | 
			
		||||
    typedef std::iterator_traits<Incrementable>::difference_type difference_type;
 | 
			
		||||
    typedef std::iterator_traits<Incrementable>::iterator_category iterator_category;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<p>The italicized sections above are implementation details, but it is important
 | 
			
		||||
to know that the <tt>difference_type</tt> for integral types is selected so that
 | 
			
		||||
it can always represent the difference between two values if such a built-in
 | 
			
		||||
integer exists. On platforms with a working <tt>std::numeric_limits</tt>
 | 
			
		||||
implementation, the <tt>difference_type</tt> for any variable-length signed
 | 
			
		||||
integer type <tt>T</tt> is <tt>T</tt> itself.
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->17 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14763" --></p>
 | 
			
		||||
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
<!--  LocalWords:  html charset alt gif hpp incrementable const namespace htm
 | 
			
		||||
 -->
 | 
			
		||||
<!--  LocalWords:  struct  typename iostream int Siek CopyConstructible pre
 | 
			
		||||
 -->
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										53
									
								
								counting_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								counting_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <boost/counting_iterator.hpp>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  // Example of using counting_iterator_generator
 | 
			
		||||
  std::cout << "counting from 0 to 4:" << std::endl;
 | 
			
		||||
  boost::counting_iterator_generator<int>::type first(0), last(4);
 | 
			
		||||
  std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Example of using make_counting_iterator()
 | 
			
		||||
  std::cout << "counting from -5 to 4:" << std::endl;
 | 
			
		||||
  std::copy(boost::make_counting_iterator(-5),
 | 
			
		||||
	    boost::make_counting_iterator(5),
 | 
			
		||||
	    std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Example of using counting iterator to create an array of pointers.
 | 
			
		||||
  const int N = 7;
 | 
			
		||||
  std::vector<int> numbers;
 | 
			
		||||
  // Fill "numbers" array with [0,N)
 | 
			
		||||
  std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N),
 | 
			
		||||
	    std::back_inserter(numbers));
 | 
			
		||||
 | 
			
		||||
  std::vector<std::vector<int>::iterator> pointers;
 | 
			
		||||
 | 
			
		||||
  // Use counting iterator to fill in the array of pointers.
 | 
			
		||||
  std::copy(boost::make_counting_iterator(numbers.begin()),
 | 
			
		||||
	    boost::make_counting_iterator(numbers.end()),
 | 
			
		||||
	    std::back_inserter(pointers));
 | 
			
		||||
 | 
			
		||||
  // Use indirect iterator to print out numbers by accessing
 | 
			
		||||
  // them through the array of pointers.
 | 
			
		||||
  std::cout << "indirectly printing out the numbers from 0 to " 
 | 
			
		||||
	    << N << std::endl;
 | 
			
		||||
  std::copy(boost::make_indirect_iterator(pointers.begin()),
 | 
			
		||||
	    boost::make_indirect_iterator(pointers.end()),
 | 
			
		||||
	    std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										263
									
								
								counting_iterator_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								counting_iterator_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,263 @@
 | 
			
		||||
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears in
 | 
			
		||||
// all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
//
 | 
			
		||||
// Revision History
 | 
			
		||||
// 16 Feb 2001  Added a missing const. Made the tests run (somewhat) with
 | 
			
		||||
//              plain MSVC again. (David Abrahams)
 | 
			
		||||
// 11 Feb 2001  #if 0'd out use of counting_iterator on non-numeric types in
 | 
			
		||||
//              MSVC without STLport, so that the other tests may proceed
 | 
			
		||||
//              (David Abrahams)
 | 
			
		||||
// 04 Feb 2001  Added use of iterator_tests.hpp (David Abrahams)
 | 
			
		||||
// 28 Jan 2001  Removed not_an_iterator detritus (David Abrahams)
 | 
			
		||||
// 24 Jan 2001  Initial revision (David Abrahams)
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
# pragma warning(disable:4786) // identifier truncated in debug info
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <boost/pending/iterator_tests.hpp>
 | 
			
		||||
#include <boost/counting_iterator.hpp>
 | 
			
		||||
#include <boost/detail/iterator.hpp>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <climits>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <boost/utility.hpp>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#ifndef BOOST_NO_LIMITS
 | 
			
		||||
# include <limits>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_NO_SLIST
 | 
			
		||||
# include <slist>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template <class T> struct is_numeric
 | 
			
		||||
{
 | 
			
		||||
    enum { value = 
 | 
			
		||||
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
 | 
			
		||||
        std::numeric_limits<T>::is_specialized
 | 
			
		||||
#else
 | 
			
		||||
        // Causes warnings with GCC, but how else can I detect numeric types at
 | 
			
		||||
        // compile-time?
 | 
			
		||||
        (boost::is_convertible<int,T>::value &&
 | 
			
		||||
         boost::is_convertible<T,int>::value)
 | 
			
		||||
#endif
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Special tests for RandomAccess CountingIterators.
 | 
			
		||||
template <class CountingIterator>
 | 
			
		||||
void category_test(
 | 
			
		||||
    CountingIterator start,
 | 
			
		||||
    CountingIterator finish,
 | 
			
		||||
    std::random_access_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
    typedef typename
 | 
			
		||||
        boost::detail::iterator_traits<CountingIterator>::difference_type
 | 
			
		||||
        difference_type;
 | 
			
		||||
    difference_type distance = boost::detail::distance(start, finish);
 | 
			
		||||
 | 
			
		||||
    // Pick a random position internal to the range
 | 
			
		||||
    difference_type offset = (unsigned)rand() % distance;
 | 
			
		||||
    assert(offset >= 0);
 | 
			
		||||
    CountingIterator internal = start;
 | 
			
		||||
    std::advance(internal, offset);
 | 
			
		||||
 | 
			
		||||
    // Try some binary searches on the range to show that it's ordered
 | 
			
		||||
    assert(std::binary_search(start, finish, *internal));
 | 
			
		||||
    CountingIterator x,y;
 | 
			
		||||
    boost::tie(x,y) = std::equal_range(start, finish, *internal);
 | 
			
		||||
    assert(boost::detail::distance(x, y) == 1);
 | 
			
		||||
 | 
			
		||||
    // Show that values outside the range can't be found
 | 
			
		||||
    assert(!std::binary_search(start, boost::prior(finish), *finish));
 | 
			
		||||
 | 
			
		||||
    // Do the generic random_access_iterator_test
 | 
			
		||||
    typedef typename CountingIterator::value_type value_type;
 | 
			
		||||
    std::vector<value_type> v;
 | 
			
		||||
    for (value_type z = *start; z != *finish; ++z)
 | 
			
		||||
        v.push_back(z);
 | 
			
		||||
    if (v.size() >= 2)
 | 
			
		||||
    {
 | 
			
		||||
        // Note that this test requires a that the first argument is
 | 
			
		||||
        // dereferenceable /and/ a valid iterator prior to the first argument
 | 
			
		||||
        boost::random_access_iterator_test(start + 1, v.size() - 1, v.begin() + 1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Special tests for bidirectional CountingIterators
 | 
			
		||||
template <class CountingIterator>
 | 
			
		||||
void category_test(CountingIterator start, CountingIterator finish, std::bidirectional_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
    if (finish != start
 | 
			
		||||
        && finish != boost::next(start)
 | 
			
		||||
        && finish != boost::next(boost::next(start)))
 | 
			
		||||
    {
 | 
			
		||||
        // Note that this test requires a that the first argument is
 | 
			
		||||
        // dereferenceable /and/ a valid iterator prior to the first argument
 | 
			
		||||
        boost::bidirectional_iterator_test(boost::next(start), boost::next(*start), boost::next(boost::next(*start)));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class CountingIterator>
 | 
			
		||||
void category_test(CountingIterator start, CountingIterator finish, std::forward_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
    if (finish != start && finish != boost::next(start))
 | 
			
		||||
        boost::forward_iterator_test(start, *start, boost::next(*start));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class CountingIterator>
 | 
			
		||||
void test_aux(CountingIterator start, CountingIterator finish)
 | 
			
		||||
{
 | 
			
		||||
    typedef typename CountingIterator::iterator_category category;
 | 
			
		||||
    typedef typename CountingIterator::value_type value_type;
 | 
			
		||||
 | 
			
		||||
    // If it's a RandomAccessIterator we can do a few delicate tests
 | 
			
		||||
    category_test(start, finish, category());
 | 
			
		||||
    
 | 
			
		||||
    // Okay, brute force...
 | 
			
		||||
    for (CountingIterator p = start; p != finish && boost::next(p) != finish; ++p)
 | 
			
		||||
    {
 | 
			
		||||
        assert(boost::next(*p) == *boost::next(p));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // prove that a reference can be formed to these values
 | 
			
		||||
    typedef typename CountingIterator::value_type value;
 | 
			
		||||
    const value* q = &*start;
 | 
			
		||||
    (void)q; // suppress unused variable warning
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Incrementable>
 | 
			
		||||
void test(Incrementable start, Incrementable finish)
 | 
			
		||||
{
 | 
			
		||||
    test_aux(boost::make_counting_iterator(start), boost::make_counting_iterator(finish));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Integer>
 | 
			
		||||
void test_integer(Integer* = 0) // default arg works around MSVC bug
 | 
			
		||||
{
 | 
			
		||||
    Integer start = 0;
 | 
			
		||||
    Integer finish = 120;
 | 
			
		||||
    test(start, finish);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Container>
 | 
			
		||||
void test_container(Container* = 0)  // default arg works around MSVC bug
 | 
			
		||||
{
 | 
			
		||||
    Container c(1 + (unsigned)rand() % 1673);
 | 
			
		||||
 | 
			
		||||
    const typename Container::iterator start = c.begin();
 | 
			
		||||
    
 | 
			
		||||
    // back off by 1 to leave room for dereferenceable value at the end
 | 
			
		||||
    typename Container::iterator finish = start;
 | 
			
		||||
    std::advance(finish, c.size() - 1);
 | 
			
		||||
    
 | 
			
		||||
    test(start, finish);
 | 
			
		||||
 | 
			
		||||
    typedef typename Container::const_iterator const_iterator;
 | 
			
		||||
    test(const_iterator(start), const_iterator(finish));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class my_int1 {
 | 
			
		||||
public:
 | 
			
		||||
  my_int1() { }
 | 
			
		||||
  my_int1(int x) : m_int(x) { }
 | 
			
		||||
  my_int1& operator++() { ++m_int; return *this; }
 | 
			
		||||
  bool operator==(const my_int1& x) const { return m_int == x.m_int; }
 | 
			
		||||
private:
 | 
			
		||||
  int m_int;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
  template <>
 | 
			
		||||
  struct counting_iterator_traits<my_int1> {
 | 
			
		||||
    typedef std::ptrdiff_t difference_type;
 | 
			
		||||
    typedef std::forward_iterator_tag iterator_category;
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class my_int2 {
 | 
			
		||||
public:
 | 
			
		||||
  typedef void value_type;
 | 
			
		||||
  typedef void pointer;
 | 
			
		||||
  typedef void reference;
 | 
			
		||||
  typedef std::ptrdiff_t difference_type;
 | 
			
		||||
  typedef std::bidirectional_iterator_tag iterator_category;
 | 
			
		||||
 | 
			
		||||
  my_int2() { }
 | 
			
		||||
  my_int2(int x) : m_int(x) { }
 | 
			
		||||
  my_int2& operator++() { ++m_int; return *this; }
 | 
			
		||||
  my_int2& operator--() { --m_int; return *this; }
 | 
			
		||||
  bool operator==(const my_int2& x) const { return m_int == x.m_int; }
 | 
			
		||||
private:
 | 
			
		||||
  int m_int;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class my_int3 {
 | 
			
		||||
public:
 | 
			
		||||
  typedef void value_type;
 | 
			
		||||
  typedef void pointer;
 | 
			
		||||
  typedef void reference;
 | 
			
		||||
  typedef std::ptrdiff_t difference_type;
 | 
			
		||||
  typedef std::random_access_iterator_tag iterator_category;
 | 
			
		||||
 | 
			
		||||
  my_int3() { }
 | 
			
		||||
  my_int3(int x) : m_int(x) { }
 | 
			
		||||
  my_int3& operator++() { ++m_int; return *this; }
 | 
			
		||||
  my_int3& operator+=(std::ptrdiff_t n) { m_int += n; return *this; }
 | 
			
		||||
  std::ptrdiff_t operator-(const my_int3& x) const { return m_int - x.m_int; }
 | 
			
		||||
  my_int3& operator--() { --m_int; return *this; }
 | 
			
		||||
  bool operator==(const my_int3& x) const { return m_int == x.m_int; }
 | 
			
		||||
  bool operator!=(const my_int3& x) const { return m_int != x.m_int; }
 | 
			
		||||
  bool operator<(const my_int3& x) const { return m_int < x.m_int; }
 | 
			
		||||
private:
 | 
			
		||||
  int m_int;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    // Test the built-in integer types.
 | 
			
		||||
    test_integer<char>();
 | 
			
		||||
    test_integer<unsigned char>();
 | 
			
		||||
    test_integer<signed char>();
 | 
			
		||||
    test_integer<wchar_t>();
 | 
			
		||||
    test_integer<short>();
 | 
			
		||||
    test_integer<unsigned short>();
 | 
			
		||||
    test_integer<int>();
 | 
			
		||||
    test_integer<unsigned int>();
 | 
			
		||||
    test_integer<long>();
 | 
			
		||||
    test_integer<unsigned long>();
 | 
			
		||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
 | 
			
		||||
    test_integer<long long>();
 | 
			
		||||
    test_integer<unsigned long long>();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   // wrapping an iterator or non-built-in integer type causes an INTERNAL
 | 
			
		||||
   // COMPILER ERROR in MSVC without STLport. I'm clueless as to why.
 | 
			
		||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
 | 
			
		||||
    // Test user-defined type.
 | 
			
		||||
    test_integer<my_int1>();
 | 
			
		||||
    test_integer<my_int2>();
 | 
			
		||||
    test_integer<my_int3>();
 | 
			
		||||
    
 | 
			
		||||
   // Some tests on container iterators, to prove we handle a few different categories
 | 
			
		||||
    test_container<std::vector<int> >();
 | 
			
		||||
    test_container<std::list<int> >();
 | 
			
		||||
# ifndef BOOST_NO_SLIST
 | 
			
		||||
    test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
 | 
			
		||||
# endif
 | 
			
		||||
    
 | 
			
		||||
    // Also prove that we can handle raw pointers.
 | 
			
		||||
    int array[2000];
 | 
			
		||||
    test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1));
 | 
			
		||||
#endif
 | 
			
		||||
    std::cout << "test successful " << std::endl;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										273
									
								
								filter_iterator.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										273
									
								
								filter_iterator.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,273 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
<title>Filter Iterator Adaptor Documentation</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
 | 
			
		||||
align="center" width="277" height="86">
 | 
			
		||||
 | 
			
		||||
<h1>Filter Iterator Adaptor</h1>
 | 
			
		||||
 | 
			
		||||
Defined in header
 | 
			
		||||
<a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
The filter iterator adaptor creates a view of an iterator range in
 | 
			
		||||
which some elements of the range are skipped over. A <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a>
 | 
			
		||||
function object controls which elements are skipped. When the
 | 
			
		||||
predicate is applied to an element, if it returns <tt>true</tt> then
 | 
			
		||||
the element is retained and if it returns <tt>false</tt> then the
 | 
			
		||||
element is skipped over.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h2>Synopsis</h2>
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
namespace boost {
 | 
			
		||||
  template <class Predicate, class BaseIterator, ...>
 | 
			
		||||
  class filter_iterator_generator;
 | 
			
		||||
 | 
			
		||||
  template <class Predicate, class BaseIterator>
 | 
			
		||||
  typename filter_iterator_generator<Predicate, BaseIterator>::type
 | 
			
		||||
  make_filter_iterator(BaseIterator first, BaseIterator last, const Predicate& p = Predicate());
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
<h2><a name="filter_iterator_generator">The Filter Iterator Type
 | 
			
		||||
Generator</a></h2>
 | 
			
		||||
 | 
			
		||||
The class <tt>filter_iterator_generator</tt> is a helper class whose
 | 
			
		||||
purpose is to construct a filter iterator type.  The template
 | 
			
		||||
parameters for this class are the <tt>Predicate</tt> function object
 | 
			
		||||
type and the <tt>BaseIterator</tt> type that is being wrapped.  In
 | 
			
		||||
most cases the associated types for the wrapped iterator can be
 | 
			
		||||
deduced from <tt>std::iterator_traits</tt>, but in some situations the
 | 
			
		||||
user may want to override these types, so there are also template
 | 
			
		||||
parameters for each of the iterator's associated types.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
template <class Predicate, class BaseIterator,
 | 
			
		||||
          class Value, class Reference, class Pointer, class Category, class Distance>
 | 
			
		||||
class filter_iterator_generator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  typedef <tt><a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> type; // the resulting filter iterator type 
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Example</h3>
 | 
			
		||||
 | 
			
		||||
The following example uses filter iterator to print out all the
 | 
			
		||||
positive integers in an array. 
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
struct is_positive_number {
 | 
			
		||||
  bool operator()(int x) { return 0 < x; }
 | 
			
		||||
};
 | 
			
		||||
int main() {
 | 
			
		||||
  int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
 | 
			
		||||
  const int N = sizeof(numbers)/sizeof(int);
 | 
			
		||||
 | 
			
		||||
  typedef boost::filter_iterator_generator<is_positive_number, int*, int>::type FilterIter;
 | 
			
		||||
  is_positive_number predicate;
 | 
			
		||||
  FilterIter::policies_type policies(predicate, numbers + N);
 | 
			
		||||
  FilterIter filter_iter_first(numbers, policies);
 | 
			
		||||
  FilterIter filter_iter_last(numbers + N, policies);
 | 
			
		||||
 | 
			
		||||
  std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
The output is:
 | 
			
		||||
<pre>
 | 
			
		||||
4 5 8
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Template Parameters</h3>
 | 
			
		||||
 | 
			
		||||
<Table border>
 | 
			
		||||
<TR>
 | 
			
		||||
<TH>Parameter</TH><TH>Description</TH>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><a href="http://www.sgi.com/tech/stl/Predicate.html"><tt>Predicate</tt></a></TD>
 | 
			
		||||
<TD>The function object that determines which elements are retained and which elements are skipped.
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><tt>BaseIterator</tt></TD>
 | 
			
		||||
<TD>The iterator type being wrapped. This type must at least be a model
 | 
			
		||||
 of the <a href="http://www.sgi.com/tech/stl/InputIterator">InputIterator</a> concept.</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><tt>Value</tt></TD>
 | 
			
		||||
<TD>The <tt>value_type</tt> of the resulting iterator,
 | 
			
		||||
unless const. If const, a conforming compiler strips constness for the
 | 
			
		||||
<tt>value_type</tt>. Typically the default for this parameter is the
 | 
			
		||||
appropriate type<a href="#1">[1]</a>.<br> <b>Default:</b>
 | 
			
		||||
<tt>std::iterator_traits<BaseIterator>::value_type</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><tt>Reference</tt></TD>
 | 
			
		||||
<TD>The <tt>reference</tt> type of the resulting iterator, and in
 | 
			
		||||
particular, the result type of <tt>operator*()</tt>. Typically the default for
 | 
			
		||||
this parameter is the appropriate type.<br> <b>Default:</b> If
 | 
			
		||||
<tt>Value</tt> is supplied, <tt>Value&</tt> is used. Otherwise
 | 
			
		||||
<tt>std::iterator_traits<BaseIterator>::reference</tt> is
 | 
			
		||||
used.</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><tt>Pointer</tt></TD>
 | 
			
		||||
<TD>The <tt>pointer</tt> type of the resulting iterator, and in
 | 
			
		||||
 particular, the result type of <tt>operator->()</tt>. 
 | 
			
		||||
 Typically the default for
 | 
			
		||||
this parameter is the appropriate type.<br>
 | 
			
		||||
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
 | 
			
		||||
otherwise <tt>std::iterator_traits<BaseIterator>::pointer</tt>.</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><tt>Category</tt></TD>
 | 
			
		||||
<TD>The <tt>iterator_category</tt> type for the resulting iterator.
 | 
			
		||||
Typically the
 | 
			
		||||
default for this parameter is the appropriate type. If you override
 | 
			
		||||
this parameter, do not use <tt>bidirectional_iterator_tag</tt>
 | 
			
		||||
because filter iterators can not go in reverse.<br>
 | 
			
		||||
<b>Default:</b> <tt>std::iterator_traits<BaseIterator>::iterator_category</tt></TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><tt>Distance</tt></TD>
 | 
			
		||||
<TD>The <tt>difference_type</tt> for the resulting iterator. Typically the default for
 | 
			
		||||
this parameter is the appropriate type.<br>
 | 
			
		||||
<b>Default:</b> <tt>std::iterator_traits<BaseIterator>::difference_type</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Model of</h3>
 | 
			
		||||
 | 
			
		||||
The filter iterator adaptor (the type
 | 
			
		||||
<tt>filter_iterator_generator<...>::type</tt>) may be a model of <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> or <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>
 | 
			
		||||
depending on the adapted iterator type.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Members</h3>
 | 
			
		||||
 | 
			
		||||
The filter iterator type implements all of the member functions and
 | 
			
		||||
operators required of the <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>
 | 
			
		||||
concept.  In addition it has the following constructor:
 | 
			
		||||
 | 
			
		||||
<pre>filter_iterator_generator::type(const BaseIterator& it, const Policies& p = Policies())</pre>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
The policies type has only one public function, which is its constructor:
 | 
			
		||||
 | 
			
		||||
<pre>filter_iterator_generator::policies_type(const Predicate& p, const BaseIterator& end)</pre>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>
 | 
			
		||||
 | 
			
		||||
<h2><a name="make_filter_iterator">The Make Filter Iterator Function</a></h2>
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
template <class Predicate, class BaseIterator>
 | 
			
		||||
typename detail::filter_generator<Predicate, BaseIterator>::type
 | 
			
		||||
make_filter_iterator(BaseIterator first, BaseIterator last, const Predicate& p = Predicate())
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
This function provides a convenient way to create filter iterators.
 | 
			
		||||
 | 
			
		||||
<h3>Example</h3>
 | 
			
		||||
 | 
			
		||||
In this example we print out all numbers in the array that are
 | 
			
		||||
greater than negative two.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
  int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
 | 
			
		||||
  const int N = sizeof(numbers)/sizeof(int);
 | 
			
		||||
 | 
			
		||||
  std::copy(boost::make_filter_iterator(numbers, numbers + N, 
 | 
			
		||||
					std::bind2nd(std::greater<int>(), -2)),
 | 
			
		||||
	    boost::make_filter_iterator(numbers + N, numbers + N, 
 | 
			
		||||
					std::bind2nd(std::greater<int>(), -2)),
 | 
			
		||||
	    std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
The output is:
 | 
			
		||||
<pre>
 | 
			
		||||
0 -1 4 5 8 
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
In the next example we print the positive numbers using the
 | 
			
		||||
<tt>make_filter_iterator()</tt> function.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
struct is_positive_number {
 | 
			
		||||
  bool operator()(int x) { return 0 < x; }
 | 
			
		||||
};
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
  int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
 | 
			
		||||
  const int N = sizeof(numbers)/sizeof(int);
 | 
			
		||||
 | 
			
		||||
  std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
 | 
			
		||||
	    boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
 | 
			
		||||
	    std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
The output is:
 | 
			
		||||
<pre>
 | 
			
		||||
4 5 8
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Notes</h3>
 | 
			
		||||
 | 
			
		||||
<a name="1">[1]</a> If the compiler does not support partial
 | 
			
		||||
specialization and the wrapped iterator type is a builtin pointer then
 | 
			
		||||
the <tt>Value</tt> type must be explicitly specified (don't use the
 | 
			
		||||
default).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->09 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14894" --></p>
 | 
			
		||||
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										53
									
								
								filter_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								filter_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
// Example of using the filter iterator adaptor from
 | 
			
		||||
// boost/iterator_adaptors.hpp.
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
struct is_positive_number {
 | 
			
		||||
  bool operator()(int x) { return 0 < x; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
  int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
 | 
			
		||||
  const int N = sizeof(numbers)/sizeof(int);
 | 
			
		||||
 | 
			
		||||
  // Example using make_filter_iterator()
 | 
			
		||||
  std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
 | 
			
		||||
	    boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
 | 
			
		||||
	    std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Example using filter_iterator_generator
 | 
			
		||||
  typedef boost::filter_iterator_generator<is_positive_number, int*, int>::type
 | 
			
		||||
    FilterIter;
 | 
			
		||||
  is_positive_number predicate;
 | 
			
		||||
  FilterIter::policies_type policies(predicate, numbers + N);
 | 
			
		||||
  FilterIter filter_iter_first(numbers, policies);
 | 
			
		||||
  FilterIter filter_iter_last(numbers + N, policies);
 | 
			
		||||
 | 
			
		||||
  std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Another example using make_filter_iterator()
 | 
			
		||||
  std::copy(boost::make_filter_iterator(numbers, numbers + N, 
 | 
			
		||||
					std::bind2nd(std::greater<int>(), -2)),
 | 
			
		||||
	    boost::make_filter_iterator(numbers + N, numbers + N, 
 | 
			
		||||
					std::bind2nd(std::greater<int>(), -2)),
 | 
			
		||||
	    std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										41
									
								
								fun_out_iter_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										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>
 | 
			
		||||
							
								
								
									
										366
									
								
								half_open_range_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										366
									
								
								half_open_range_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,366 @@
 | 
			
		||||
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears in
 | 
			
		||||
// all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
//
 | 
			
		||||
// Revision History
 | 
			
		||||
// 11 Feb 2001  Compile with Borland, re-enable failing tests (David Abrahams)
 | 
			
		||||
// 29 Jan 2001  Initial revision (David Abrahams)
 | 
			
		||||
 | 
			
		||||
#include <boost/half_open_range.hpp>
 | 
			
		||||
#include <boost/utility.hpp>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#ifndef BOOST_NO_LIMITS
 | 
			
		||||
# include <limits>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_NO_SLIST
 | 
			
		||||
# include <slist>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
inline unsigned unsigned_random(unsigned max)
 | 
			
		||||
{
 | 
			
		||||
    return (max > 0) ? (unsigned)rand() % max : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Special tests for ranges supporting random access
 | 
			
		||||
template <class T>
 | 
			
		||||
void category_test_1(
 | 
			
		||||
    const boost::half_open_range<T>& r, std::random_access_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
    typedef boost::half_open_range<T> range;
 | 
			
		||||
    typedef typename range::size_type size_type;
 | 
			
		||||
    size_type size = r.size();
 | 
			
		||||
 | 
			
		||||
    // pick a random offset
 | 
			
		||||
    size_type offset = unsigned_random(size);
 | 
			
		||||
 | 
			
		||||
    typename range::value_type x = *(r.begin() + offset);
 | 
			
		||||
    // test contains(value_type)
 | 
			
		||||
    assert(r.contains(r.start()) == !r.empty());
 | 
			
		||||
    assert(!r.contains(r.finish()));
 | 
			
		||||
    assert(r.contains(x) == (offset != size));
 | 
			
		||||
 | 
			
		||||
    range::const_iterator p = r.find(x);
 | 
			
		||||
    assert((p == r.end()) == (x == r.finish()));
 | 
			
		||||
    assert(r.find(r.finish()) == r.end());
 | 
			
		||||
 | 
			
		||||
    if (offset != size)
 | 
			
		||||
    {
 | 
			
		||||
        assert(x == r[offset]);
 | 
			
		||||
        assert(x == r.at(offset));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool caught_out_of_range = false;
 | 
			
		||||
    try {
 | 
			
		||||
        bool never_initialized = x == r.at(size);
 | 
			
		||||
        (void)never_initialized;
 | 
			
		||||
    }
 | 
			
		||||
    catch(std::out_of_range&)
 | 
			
		||||
    {
 | 
			
		||||
        caught_out_of_range = true;
 | 
			
		||||
    }
 | 
			
		||||
    catch(...)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    assert(caught_out_of_range);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Those tests must be skipped for other ranges
 | 
			
		||||
template <class T>
 | 
			
		||||
void category_test_1(
 | 
			
		||||
    const boost::half_open_range<T>&, std::forward_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned indices[][2] = { {0,0},{0,1},{0,2},{0,3},
 | 
			
		||||
                                {1,1},{1,2},{1,3},
 | 
			
		||||
                                      {2,2},{2,3},
 | 
			
		||||
                                            {3,3}};
 | 
			
		||||
 | 
			
		||||
template <class Range>
 | 
			
		||||
void category_test_2(
 | 
			
		||||
    const std::vector<Range>& ranges, unsigned i, unsigned j, std::random_access_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
    typedef Range range;
 | 
			
		||||
    const range& ri = ranges[i];
 | 
			
		||||
    const range& rj = ranges[j];
 | 
			
		||||
 | 
			
		||||
    if (indices[i][0] <= indices[j][0] && indices[i][1] >= indices[j][1])
 | 
			
		||||
        assert(ri.contains(rj));
 | 
			
		||||
 | 
			
		||||
    if (ri.contains(rj))
 | 
			
		||||
        assert((ri & rj) == rj);
 | 
			
		||||
    assert(boost::intersects(ri, rj) == !(ri & rj).empty());
 | 
			
		||||
 | 
			
		||||
    range t1(ri);
 | 
			
		||||
    t1 &= rj;
 | 
			
		||||
    assert(t1 == range(indices[i][0] > indices[j][0] ? ri.start() : rj.start(),
 | 
			
		||||
                       indices[i][1] < indices[j][1] ? ri.finish() : rj.finish()));
 | 
			
		||||
    assert(t1 == (ri & rj));
 | 
			
		||||
    
 | 
			
		||||
    range t2(ri);
 | 
			
		||||
    t2 |= rj;
 | 
			
		||||
    
 | 
			
		||||
    if (ri.empty())
 | 
			
		||||
        assert(t2 == rj);
 | 
			
		||||
    else if (rj.empty())
 | 
			
		||||
        assert(t2 == ri);
 | 
			
		||||
    else
 | 
			
		||||
        assert(t2 == range(indices[i][0] < indices[j][0] ? ri.start() : rj.start(),
 | 
			
		||||
                           indices[i][1] > indices[j][1] ? ri.finish() : rj.finish()));
 | 
			
		||||
    assert(t2 == (ri | rj));
 | 
			
		||||
    if (i == j)
 | 
			
		||||
        assert(ri == rj);
 | 
			
		||||
    
 | 
			
		||||
    if (ri.empty() || rj.empty())
 | 
			
		||||
        assert((ri == rj) == (ri.empty() && rj.empty()));
 | 
			
		||||
    else
 | 
			
		||||
        assert((ri == rj) == (ri.start() == rj.start() && ri.finish() == rj.finish()));
 | 
			
		||||
 | 
			
		||||
    assert((ri == rj) == !(ri != rj));
 | 
			
		||||
 | 
			
		||||
    bool same = ri == rj;
 | 
			
		||||
    bool one_empty = ri.empty() != rj.empty();
 | 
			
		||||
 | 
			
		||||
    std::less<range> less;
 | 
			
		||||
    std::less_equal<range> less_equal;
 | 
			
		||||
    std::greater<range> greater;
 | 
			
		||||
    std::greater_equal<range> greater_equal;
 | 
			
		||||
    
 | 
			
		||||
    if (same)
 | 
			
		||||
    {
 | 
			
		||||
        assert(greater_equal(ri,rj));
 | 
			
		||||
        assert(less_equal(ri,rj));
 | 
			
		||||
        assert(!greater(ri,rj));
 | 
			
		||||
        assert(!less(ri,rj));
 | 
			
		||||
    }
 | 
			
		||||
    else if (one_empty)
 | 
			
		||||
    {
 | 
			
		||||
        const range& empty = ri.empty() ? ri : rj;
 | 
			
		||||
        const range& non_empty = rj.empty() ? ri : rj;
 | 
			
		||||
        
 | 
			
		||||
        assert(less(empty,non_empty));
 | 
			
		||||
        assert(less_equal(empty,non_empty));
 | 
			
		||||
        assert(!greater(empty,non_empty));
 | 
			
		||||
        assert(!greater_equal(empty,non_empty));
 | 
			
		||||
        assert(!less(non_empty,empty));
 | 
			
		||||
        assert(!less_equal(non_empty,empty));
 | 
			
		||||
        assert(greater(non_empty,empty));
 | 
			
		||||
        assert(greater_equal(non_empty,empty));
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        if (indices[i][0] < indices[j][0] ||
 | 
			
		||||
            indices[i][0] == indices[j][0] && indices[i][1] < indices[j][1])
 | 
			
		||||
        {
 | 
			
		||||
            assert(!greater_equal(ri,rj));
 | 
			
		||||
            assert(less(ri,rj));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (indices[i][0] < indices[j][0] ||
 | 
			
		||||
            indices[i][0] == indices[j][0] && indices[i][1] <= indices[j][1])
 | 
			
		||||
        {
 | 
			
		||||
            assert(!greater(ri,rj));
 | 
			
		||||
            assert(less_equal(ri,rj));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (indices[i][0] > indices[j][0] ||
 | 
			
		||||
            indices[i][0] == indices[j][0] && indices[i][1] > indices[j][1])
 | 
			
		||||
        {
 | 
			
		||||
            assert(!less_equal(ri,rj));
 | 
			
		||||
            assert(greater(ri,rj));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (indices[i][0] > indices[j][0] ||
 | 
			
		||||
            indices[i][0] == indices[j][0] && indices[i][1] >= indices[j][1])
 | 
			
		||||
        {
 | 
			
		||||
            assert(!less(ri,rj));
 | 
			
		||||
            assert(greater_equal(ri,rj));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <class Range>
 | 
			
		||||
void category_test_2(
 | 
			
		||||
    const std::vector<Range>&, unsigned, unsigned, std::forward_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
void category_test_2(
 | 
			
		||||
    const std::vector<boost::half_open_range<T> >&, unsigned, unsigned, std::bidirectional_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Range>
 | 
			
		||||
void test_back(Range& x, std::bidirectional_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
    assert(x.back() == boost::prior(x.finish()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Range>
 | 
			
		||||
void test_back(Range& x, std::forward_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
boost::half_open_range<T> range_identity(const boost::half_open_range<T>& x)
 | 
			
		||||
{
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
void test(T x0, T x1, T x2, T x3)
 | 
			
		||||
{
 | 
			
		||||
    std::vector<boost::half_open_range<T> > ranges;
 | 
			
		||||
    typedef boost::half_open_range<T> range;
 | 
			
		||||
 | 
			
		||||
    T bounds[4] = { x0, x1, x2, x3 };
 | 
			
		||||
 | 
			
		||||
    const std::size_t num_ranges = sizeof(indices)/sizeof(*indices);
 | 
			
		||||
    // test construction
 | 
			
		||||
    for (std::size_t n = 0; n < num_ranges;++n)
 | 
			
		||||
    {
 | 
			
		||||
        T start = bounds[indices[n][0]];
 | 
			
		||||
        T finish = bounds[indices[n][1]];
 | 
			
		||||
        boost::half_open_range<T> r(start, finish);
 | 
			
		||||
        ranges.push_back(r);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // test implicit conversion from std::pair<T,T>
 | 
			
		||||
    range converted = std::pair<T,T>(x0,x0);
 | 
			
		||||
    (void)converted;
 | 
			
		||||
 | 
			
		||||
    // test assignment, equality and inequality
 | 
			
		||||
    range r00 = range(x0, x0);
 | 
			
		||||
    assert(r00 == range(x0,x0));
 | 
			
		||||
    assert(r00 == range(x1,x1)); // empty ranges are all equal
 | 
			
		||||
    if (x3 != x0)
 | 
			
		||||
        assert(r00 != range(x0, x3));
 | 
			
		||||
    r00 = range(x0, x3);
 | 
			
		||||
    assert(r00 == range(x0, x3));
 | 
			
		||||
    if (x3 != x0)
 | 
			
		||||
        assert(r00 != range(x0, x0));
 | 
			
		||||
 | 
			
		||||
    typedef typename range::iterator iterator;
 | 
			
		||||
    typedef typename iterator::iterator_category category;
 | 
			
		||||
    
 | 
			
		||||
    for (unsigned i = 0; i < num_ranges; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        const range& r = ranges[i];
 | 
			
		||||
            
 | 
			
		||||
        // test begin(), end(), basic iteration.
 | 
			
		||||
        unsigned count = 0;
 | 
			
		||||
        for (range::const_iterator p = r.begin(), finish = r.end();
 | 
			
		||||
             p != finish;
 | 
			
		||||
             ++p, ++count)
 | 
			
		||||
        {
 | 
			
		||||
            assert(count < 2100);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // test size(), empty(), front(), back()
 | 
			
		||||
        assert((unsigned)r.size() == count);
 | 
			
		||||
        if (indices[i][0] == indices[i][1])
 | 
			
		||||
            assert(r.empty());
 | 
			
		||||
        if (r.empty())
 | 
			
		||||
            assert(r.size() == 0);
 | 
			
		||||
        if (!r.empty())
 | 
			
		||||
        {
 | 
			
		||||
            assert(r.front() == r.start());
 | 
			
		||||
            test_back(r, category());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            // test swap
 | 
			
		||||
        range r1(r);
 | 
			
		||||
        range r2(x0,x3);
 | 
			
		||||
        const bool same = r1 == r2;
 | 
			
		||||
        r1.swap(r2);
 | 
			
		||||
        assert(r1 == range(x0,x3));
 | 
			
		||||
        assert(r2 == r);
 | 
			
		||||
        if (!same) {
 | 
			
		||||
            assert(r1 != r);
 | 
			
		||||
            assert(r2 != range(x0,x3));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // do individual tests for random-access iterators
 | 
			
		||||
        category_test_1(r, category());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (unsigned j = 0; j < num_ranges; ++j) {
 | 
			
		||||
        for (unsigned k = 0; k < num_ranges; ++k) {
 | 
			
		||||
            category_test_2(ranges, j, k, category());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Integer>
 | 
			
		||||
void test_integer(Integer* = 0) // default arg works around MSVC bug
 | 
			
		||||
{
 | 
			
		||||
    Integer a = 0;
 | 
			
		||||
    Integer b = a + unsigned_random(128 - a);
 | 
			
		||||
    Integer c = b + unsigned_random(128 - b);
 | 
			
		||||
    Integer d = c + unsigned_random(128 - c);
 | 
			
		||||
 | 
			
		||||
    test(a, b, c, d);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Container>
 | 
			
		||||
void test_container(Container* = 0)  // default arg works around MSVC bug
 | 
			
		||||
{
 | 
			
		||||
    Container c(unsigned_random(1673));
 | 
			
		||||
 | 
			
		||||
    const typename Container::size_type offset1 = unsigned_random(c.size());
 | 
			
		||||
    const typename Container::size_type offset2 = unsigned_random(c.size() - offset1);
 | 
			
		||||
    typename Container::iterator internal1 = c.begin();
 | 
			
		||||
    std::advance(internal1, offset1);
 | 
			
		||||
    typename Container::iterator internal2 = internal1;
 | 
			
		||||
    std::advance(internal2, offset2);
 | 
			
		||||
    
 | 
			
		||||
    test(c.begin(), internal1, internal2, c.end());
 | 
			
		||||
 | 
			
		||||
    typedef typename Container::const_iterator const_iterator;
 | 
			
		||||
    test(const_iterator(c.begin()),
 | 
			
		||||
         const_iterator(internal1),
 | 
			
		||||
         const_iterator(internal2),
 | 
			
		||||
         const_iterator(c.end()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    // Test the built-in integer types.
 | 
			
		||||
    test_integer<char>();
 | 
			
		||||
    test_integer<unsigned char>();
 | 
			
		||||
    test_integer<signed char>();
 | 
			
		||||
    test_integer<wchar_t>();
 | 
			
		||||
    test_integer<short>();
 | 
			
		||||
    test_integer<unsigned short>();
 | 
			
		||||
    test_integer<int>();
 | 
			
		||||
    test_integer<unsigned int>();
 | 
			
		||||
    test_integer<long>();
 | 
			
		||||
    test_integer<unsigned long>();
 | 
			
		||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
 | 
			
		||||
    test_integer<long long>();
 | 
			
		||||
    test_integer<unsigned long long>();
 | 
			
		||||
#endif
 | 
			
		||||
    // Some tests on container iterators, to prove we handle a few different categories
 | 
			
		||||
    test_container<std::vector<int> >();
 | 
			
		||||
    test_container<std::list<int> >();
 | 
			
		||||
#ifndef BOOST_NO_SLIST
 | 
			
		||||
    test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
 | 
			
		||||
#endif
 | 
			
		||||
    // Also prove that we can handle raw pointers.
 | 
			
		||||
    int array[2000];
 | 
			
		||||
    const std::size_t a = 0;
 | 
			
		||||
    const std::size_t b = a + unsigned_random(2000 - a);
 | 
			
		||||
    const std::size_t c = b + unsigned_random(2000 - b);
 | 
			
		||||
    test(array, array+b, array+c, array+2000);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -23,8 +23,11 @@
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits.hpp>
 | 
			
		||||
#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/arithmetic_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/composite_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace boost{
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,11 @@
 | 
			
		||||
#define BOOST_DETAIL_COMPRESSED_PAIR_HPP
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#ifndef BOOST_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits.hpp>
 | 
			
		||||
#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/object_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_SAME_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/same_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_CALL_TRAITS_HPP
 | 
			
		||||
#include <boost/call_traits.hpp>
 | 
			
		||||
@@ -422,3 +425,4 @@ swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
 | 
			
		||||
#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -24,8 +24,11 @@
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits.hpp>
 | 
			
		||||
#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/arithmetic_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/composite_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace boost{
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,8 @@
 | 
			
		||||
//  see libs/utility/compressed_pair.hpp
 | 
			
		||||
//
 | 
			
		||||
/* Release notes:
 | 
			
		||||
   20 Jan 2001:
 | 
			
		||||
        Fixed obvious bugs (David Abrahams)
 | 
			
		||||
	07 Oct 2000:
 | 
			
		||||
		Added better single argument constructor support.
 | 
			
		||||
   03 Oct 2000:
 | 
			
		||||
@@ -24,8 +26,11 @@
 | 
			
		||||
#define BOOST_OB_COMPRESSED_PAIR_HPP
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#ifndef BOOST_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits.hpp>
 | 
			
		||||
#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/object_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_SAME_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/same_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_CALL_TRAITS_HPP
 | 
			
		||||
#include <boost/call_traits.hpp>
 | 
			
		||||
@@ -42,10 +47,14 @@ namespace boost
 | 
			
		||||
// have one template single-argument constructor
 | 
			
		||||
// in place of two specific constructors:
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair;
 | 
			
		||||
 | 
			
		||||
namespace detail{
 | 
			
		||||
 | 
			
		||||
template <class A, class T1, class T2>
 | 
			
		||||
struct best_convertion_traits
 | 
			
		||||
struct best_conversion_traits
 | 
			
		||||
{
 | 
			
		||||
   typedef char one;
 | 
			
		||||
   typedef char (&two)[2];
 | 
			
		||||
@@ -102,8 +111,20 @@ public:
 | 
			
		||||
   template <class A>
 | 
			
		||||
   explicit compressed_pair_0(const A& val)
 | 
			
		||||
   {
 | 
			
		||||
      init_one<best_convertion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
 | 
			
		||||
      init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
 | 
			
		||||
   }
 | 
			
		||||
   compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x)
 | 
			
		||||
      : _first(x.first()), _second(x.second()) {}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  compressed_pair_0& operator=(const compressed_pair_0& x) {
 | 
			
		||||
    cout << "assigning compressed pair 0" << endl;
 | 
			
		||||
    _first = x._first;
 | 
			
		||||
    _second = x._second;
 | 
			
		||||
    cout << "finished assigning compressed pair 0" << endl;
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       { return _first; }
 | 
			
		||||
   first_const_reference first() const { return _first; }
 | 
			
		||||
@@ -137,12 +158,27 @@ public:
 | 
			
		||||
 | 
			
		||||
            compressed_pair_1() : T2(), _first() {}
 | 
			
		||||
            compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
 | 
			
		||||
 | 
			
		||||
   template <class A>
 | 
			
		||||
   explicit compressed_pair_1(const A& val)
 | 
			
		||||
   {
 | 
			
		||||
      init_one<best_convertion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
 | 
			
		||||
      init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
 | 
			
		||||
      : T2(x.second()), _first(x.first()) {}
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
  // Total weirdness. If the assignment to _first is moved after
 | 
			
		||||
  // the call to the inherited operator=, then this breaks graph/test/graph.cpp
 | 
			
		||||
  // by way of iterator_adaptor.
 | 
			
		||||
  compressed_pair_1& operator=(const compressed_pair_1& x) {
 | 
			
		||||
    _first = x._first;
 | 
			
		||||
    T2::operator=(x);
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       { return _first; }
 | 
			
		||||
   first_const_reference first() const { return _first; }
 | 
			
		||||
 | 
			
		||||
@@ -178,9 +214,20 @@ public:
 | 
			
		||||
   template <class A>
 | 
			
		||||
   explicit compressed_pair_2(const A& val)
 | 
			
		||||
   {
 | 
			
		||||
      init_one<best_convertion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
 | 
			
		||||
      init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
 | 
			
		||||
   }
 | 
			
		||||
   compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x)
 | 
			
		||||
      : T1(x.first()), _second(x.second()) {}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  compressed_pair_2& operator=(const compressed_pair_2& x) {
 | 
			
		||||
    cout << "assigning compressed pair 2" << endl;
 | 
			
		||||
    T1::operator=(x);
 | 
			
		||||
    _second = x._second;
 | 
			
		||||
    cout << "finished assigning compressed pair 2" << endl;
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
   first_reference       first()       { return *this; }
 | 
			
		||||
   first_const_reference first() const { return *this; }
 | 
			
		||||
 | 
			
		||||
@@ -214,8 +261,10 @@ public:
 | 
			
		||||
   template <class A>
 | 
			
		||||
   explicit compressed_pair_3(const A& val)
 | 
			
		||||
   {
 | 
			
		||||
      init_one<best_convertion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
 | 
			
		||||
      init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
 | 
			
		||||
   }
 | 
			
		||||
   compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x)
 | 
			
		||||
      : T1(x.first()), T2(x.second()) {}
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       { return *this; }
 | 
			
		||||
   first_const_reference first() const { return *this; }
 | 
			
		||||
@@ -247,6 +296,8 @@ public:
 | 
			
		||||
            compressed_pair_4(first_param_type x, second_param_type) : T1(x) {}
 | 
			
		||||
   // only one single argument constructor since T1 == T2
 | 
			
		||||
   explicit compressed_pair_4(first_param_type x) : T1(x) {}
 | 
			
		||||
   compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
 | 
			
		||||
      : T1(x.first()){}
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       { return *this; }
 | 
			
		||||
   first_const_reference first() const { return *this; }
 | 
			
		||||
@@ -280,7 +331,9 @@ public:
 | 
			
		||||
            compressed_pair_5() : _first(), _second() {}
 | 
			
		||||
            compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
 | 
			
		||||
   // only one single argument constructor since T1 == T2
 | 
			
		||||
   explicit compressed_pair_5(first_param_type x) : _first(x), _second() {}
 | 
			
		||||
   explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
 | 
			
		||||
   compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c) 
 | 
			
		||||
      : _first(c.first()), _second(c.second()) {}
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       { return _first; }
 | 
			
		||||
   first_const_reference first() const { return _first; }
 | 
			
		||||
@@ -453,3 +506,4 @@ inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
 | 
			
		||||
#endif // BOOST_OB_COMPRESSED_PAIR_HPP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,20 +1,25 @@
 | 
			
		||||
//  Boost operators.hpp header file  ----------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright David Abrahams 1999. Permission to copy, use,
 | 
			
		||||
//  modify, sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
//  (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-2001.
 | 
			
		||||
//  Permission to copy, use, modify, sell and distribute this software is
 | 
			
		||||
//  granted provided this copyright notice appears in all copies.  This
 | 
			
		||||
//  software is provided "as is" without express or implied warranty, and
 | 
			
		||||
//  with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  25 Jun 01 output_iterator_helper changes: removed default template 
 | 
			
		||||
//            parameters, added support for self-proxying, additional 
 | 
			
		||||
//            documentation and tests (Aleksey Gurtovoy)
 | 
			
		||||
//  29 May 01 Added operator classes for << and >>.  Added input and output
 | 
			
		||||
//            iterator helper classes.  Added classes to connect equality and
 | 
			
		||||
//            relational operators.  Added classes for groups of related
 | 
			
		||||
//            operators.  Reimplemented example operator and iterator helper
 | 
			
		||||
//            classes in terms of the new groups.  (Daryle Walker, with help
 | 
			
		||||
//            from Alexy Gurtovoy)
 | 
			
		||||
//  11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
 | 
			
		||||
//            supplied arguments from actually being used (Dave Abrahams)
 | 
			
		||||
//  04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
 | 
			
		||||
//            refactoring of compiler workarounds, additional documentation
 | 
			
		||||
//            (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
 | 
			
		||||
@@ -280,12 +285,190 @@ struct indexable : B
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//  More operator classes (contributed by Daryle Walker) --------------------//
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct left_shiftable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator<<(T x, const U& y) { return x <<= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct left_shiftable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator<<(T x, const T& y) { return x <<= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct right_shiftable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator>>(T x, const U& y) { return x >>= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct right_shiftable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend T operator>>(T x, const T& y) { return x >>= y; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct equivalent2 : B
 | 
			
		||||
{
 | 
			
		||||
  friend bool operator==(const T& x, const U& y)
 | 
			
		||||
  {
 | 
			
		||||
    return !(x < y) && !(x > y);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct equivalent1 : B
 | 
			
		||||
{
 | 
			
		||||
  friend bool operator==(const T&x, const T&y)
 | 
			
		||||
  {
 | 
			
		||||
    return !(x < y) && !(y < x);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct partially_ordered2 : B
 | 
			
		||||
{
 | 
			
		||||
  friend bool operator<=(const T& x, const U& y)
 | 
			
		||||
    { return (x < y) || (x == y); }
 | 
			
		||||
  friend bool operator>=(const T& x, const U& y)
 | 
			
		||||
    { return (x > y) || (x == y); }
 | 
			
		||||
  friend bool operator>(const U& x, const T& y)
 | 
			
		||||
    { return y < x; }
 | 
			
		||||
  friend bool operator<(const U& x, const T& y)
 | 
			
		||||
    { return y > x; }
 | 
			
		||||
  friend bool operator<=(const U& x, const T& y)
 | 
			
		||||
    { return (y > x) || (y == x); }
 | 
			
		||||
  friend bool operator>=(const U& x, const T& y)
 | 
			
		||||
    { return (y < x) || (y == x); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct partially_ordered1 : B
 | 
			
		||||
{
 | 
			
		||||
  friend bool operator>(const T& x, const T& y)
 | 
			
		||||
    { return y < x; }
 | 
			
		||||
  friend bool operator<=(const T& x, const T& y)
 | 
			
		||||
    { return (x < y) || (x == y); }
 | 
			
		||||
  friend bool operator>=(const T& x, const T& y)
 | 
			
		||||
    { return (y < x) || (x == y); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//  Combined operator classes (contributed by Daryle Walker) ----------------//
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct totally_ordered2
 | 
			
		||||
    : less_than_comparable2<T, U
 | 
			
		||||
    , equality_comparable2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct totally_ordered1
 | 
			
		||||
    : less_than_comparable1<T
 | 
			
		||||
    , equality_comparable1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct additive2
 | 
			
		||||
    : addable2<T, U
 | 
			
		||||
    , subtractable2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct additive1
 | 
			
		||||
    : addable1<T
 | 
			
		||||
    , subtractable1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct multiplicative2
 | 
			
		||||
    : multipliable2<T, U
 | 
			
		||||
    , dividable2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct multiplicative1
 | 
			
		||||
    : multipliable1<T
 | 
			
		||||
    , dividable1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct integer_multiplicative2
 | 
			
		||||
    : multiplicative2<T, U
 | 
			
		||||
    , modable2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct integer_multiplicative1
 | 
			
		||||
    : multiplicative1<T
 | 
			
		||||
    , modable1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct arithmetic2
 | 
			
		||||
    : additive2<T, U
 | 
			
		||||
    , multiplicative2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct arithmetic1
 | 
			
		||||
    : additive1<T
 | 
			
		||||
    , multiplicative1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct integer_arithmetic2
 | 
			
		||||
    : additive2<T, U
 | 
			
		||||
    , integer_multiplicative2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct integer_arithmetic1
 | 
			
		||||
    : additive1<T
 | 
			
		||||
    , integer_multiplicative1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct bitwise2
 | 
			
		||||
    : xorable2<T, U
 | 
			
		||||
    , andable2<T, U
 | 
			
		||||
    , orable2<T, U, B
 | 
			
		||||
      > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct bitwise1
 | 
			
		||||
    : xorable1<T
 | 
			
		||||
    , andable1<T
 | 
			
		||||
    , orable1<T, B
 | 
			
		||||
      > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct unit_steppable
 | 
			
		||||
    : incrementable<T
 | 
			
		||||
    , decrementable<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct shiftable2
 | 
			
		||||
    : left_shiftable2<T, U
 | 
			
		||||
    , right_shiftable2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct shiftable1
 | 
			
		||||
    : left_shiftable1<T
 | 
			
		||||
    , right_shiftable1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
} // namespace boost
 | 
			
		||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// BOOST_IMPORT_TEMPLATE1/BOOST_IMPORT_TEMPLATE2 -
 | 
			
		||||
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE3 -
 | 
			
		||||
//
 | 
			
		||||
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
 | 
			
		||||
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
 | 
			
		||||
@@ -293,12 +476,31 @@ struct indexable : B
 | 
			
		||||
// two-argument forms. Note that these macros expect to be invoked from within
 | 
			
		||||
// boost.
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_NO_OPERATORS_IN_NAMESPACE)
 | 
			
		||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#  if defined(BOOST_NO_USING_TEMPLATE)
 | 
			
		||||
  // The template is already in boost so we have nothing to do.
 | 
			
		||||
# define BOOST_IMPORT_TEMPLATE3(template_name)
 | 
			
		||||
# define BOOST_IMPORT_TEMPLATE2(template_name)
 | 
			
		||||
# define BOOST_IMPORT_TEMPLATE1(template_name)
 | 
			
		||||
 | 
			
		||||
#else // BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#  ifndef BOOST_NO_USING_TEMPLATE
 | 
			
		||||
 | 
			
		||||
     // Bring the names in with a using-declaration
 | 
			
		||||
     // to avoid stressing the compiler.
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
 | 
			
		||||
 | 
			
		||||
#  else
 | 
			
		||||
 | 
			
		||||
     // Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
 | 
			
		||||
     // from working, we are forced to use inheritance for that compiler.
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE3(template_name)                                 \
 | 
			
		||||
     template <class T, class U, class V, class B = ::boost::detail::empty_base>  \
 | 
			
		||||
     struct template_name : ::template_name<T, U, V, B> {};
 | 
			
		||||
 | 
			
		||||
     // Because a Borland C++ 5.5 bug prevents a using declaration from working,
 | 
			
		||||
     // we are forced to use inheritance for that compiler.
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE2(template_name)                              \
 | 
			
		||||
     template <class T, class U, class B = ::boost::detail::empty_base>        \
 | 
			
		||||
     struct template_name : ::template_name<T, U, B> {};
 | 
			
		||||
@@ -307,21 +509,8 @@ struct indexable : B
 | 
			
		||||
     template <class T, class B = ::boost::detail::empty_base>                 \
 | 
			
		||||
     struct template_name : ::template_name<T, B> {};
 | 
			
		||||
 | 
			
		||||
#  else
 | 
			
		||||
 | 
			
		||||
     // Otherwise, bring the names in with a using-declaration to avoid
 | 
			
		||||
     // stressing the compiler
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
 | 
			
		||||
 | 
			
		||||
#  endif // BOOST_NO_USING_TEMPLATE
 | 
			
		||||
 | 
			
		||||
#else // !BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
  // The template is already in boost so we have nothing to do.
 | 
			
		||||
# define BOOST_IMPORT_TEMPLATE2(template_name)
 | 
			
		||||
# define BOOST_IMPORT_TEMPLATE1(template_name)
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
@@ -330,7 +519,7 @@ struct indexable : B
 | 
			
		||||
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
 | 
			
		||||
// neccessary.
 | 
			
		||||
//
 | 
			
		||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
 | 
			
		||||
// is_chained_base<> - a traits class used to distinguish whether an operator
 | 
			
		||||
// template argument is being used for base class chaining, or is specifying a
 | 
			
		||||
@@ -353,6 +542,15 @@ template<class T> struct is_chained_base {
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
// Import a 3-type-argument operator template into boost (if neccessary) and
 | 
			
		||||
// provide a specialization of 'is_chained_base<>' for it.
 | 
			
		||||
# define BOOST_OPERATOR_TEMPLATE3(template_name3)                     \
 | 
			
		||||
  BOOST_IMPORT_TEMPLATE3(template_name3)                              \
 | 
			
		||||
  template<class T, class U, class V, class B>                        \
 | 
			
		||||
  struct is_chained_base< ::boost::template_name3<T, U, V, B> > {     \
 | 
			
		||||
    typedef ::boost::detail::true_t value;                            \
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
// Import a 2-type-argument operator template into boost (if neccessary) and
 | 
			
		||||
// provide a specialization of 'is_chained_base<>' for it.
 | 
			
		||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2)                  \
 | 
			
		||||
@@ -412,6 +610,8 @@ BOOST_OPERATOR_TEMPLATE1(template_name##1)
 | 
			
		||||
 | 
			
		||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
 | 
			
		||||
#  define BOOST_OPERATOR_TEMPLATE3(template_name3) \
 | 
			
		||||
        BOOST_IMPORT_TEMPLATE3(template_name3)
 | 
			
		||||
#  define BOOST_OPERATOR_TEMPLATE2(template_name2) \
 | 
			
		||||
        BOOST_IMPORT_TEMPLATE2(template_name2)
 | 
			
		||||
#  define BOOST_OPERATOR_TEMPLATE1(template_name1) \
 | 
			
		||||
@@ -440,47 +640,41 @@ BOOST_OPERATOR_TEMPLATE(orable)
 | 
			
		||||
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE1(incrementable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE1(decrementable)
 | 
			
		||||
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE3(indexable)
 | 
			
		||||
 | 
			
		||||
// indexable doesn't follow the patterns above (it has 4 template arguments), so
 | 
			
		||||
// we just write out the compiler hacks explicitly.
 | 
			
		||||
#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
# ifdef BOOST_NO_USING_TEMPLATE
 | 
			
		||||
   template <class T, class I, class R, class B = ::boost::detail::empty_base>
 | 
			
		||||
   struct indexable : ::indexable<T,I,R,B> {};
 | 
			
		||||
# else
 | 
			
		||||
   using ::indexable;
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(left_shiftable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(right_shiftable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(equivalent)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(partially_ordered)
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
template <class T, class I, class R, class B>
 | 
			
		||||
struct is_chained_base< ::boost::indexable<T, I, R, B> > {
 | 
			
		||||
  typedef ::boost::detail::true_t operator_template_type;
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(totally_ordered)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(additive)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(multiplicative)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(arithmetic)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(bitwise)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE1(unit_steppable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(shiftable)
 | 
			
		||||
 | 
			
		||||
#undef BOOST_OPERATOR_TEMPLATE
 | 
			
		||||
#undef BOOST_OPERATOR_TEMPLATE3
 | 
			
		||||
#undef BOOST_OPERATOR_TEMPLATE2
 | 
			
		||||
#undef BOOST_OPERATOR_TEMPLATE1
 | 
			
		||||
#undef BOOST_IMPORT_TEMPLATE1
 | 
			
		||||
#undef BOOST_IMPORT_TEMPLATE2
 | 
			
		||||
#undef BOOST_IMPORT_TEMPLATE3
 | 
			
		||||
 | 
			
		||||
// The following 'operators' classes can only be used portably if the derived class
 | 
			
		||||
// declares ALL of the required member operators.
 | 
			
		||||
template <class T, class U>
 | 
			
		||||
struct operators2
 | 
			
		||||
    : less_than_comparable2<T,U
 | 
			
		||||
    , equality_comparable2<T,U
 | 
			
		||||
    , addable2<T,U
 | 
			
		||||
    , subtractable2<T,U
 | 
			
		||||
    , multipliable2<T,U
 | 
			
		||||
    , dividable2<T,U
 | 
			
		||||
    , modable2<T,U
 | 
			
		||||
    , orable2<T,U
 | 
			
		||||
    , andable2<T,U
 | 
			
		||||
    , xorable2<T,U
 | 
			
		||||
      > > > > > > > > > > {};
 | 
			
		||||
    : totally_ordered2<T,U
 | 
			
		||||
    , integer_arithmetic2<T,U
 | 
			
		||||
    , bitwise2<T,U
 | 
			
		||||
      > > > {};
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
template <class T, class U = T>
 | 
			
		||||
@@ -490,31 +684,47 @@ template <class T> struct operators<T, T>
 | 
			
		||||
#else
 | 
			
		||||
template <class T> struct operators
 | 
			
		||||
#endif
 | 
			
		||||
    : less_than_comparable<T
 | 
			
		||||
    , equality_comparable<T
 | 
			
		||||
    , addable<T
 | 
			
		||||
    , subtractable<T
 | 
			
		||||
    , multipliable<T
 | 
			
		||||
    , dividable<T
 | 
			
		||||
    , modable<T
 | 
			
		||||
    , orable<T
 | 
			
		||||
    , andable<T
 | 
			
		||||
    , xorable<T
 | 
			
		||||
    , incrementable<T
 | 
			
		||||
    , decrementable<T
 | 
			
		||||
      > > > > > > > > > > > > {};
 | 
			
		||||
    : totally_ordered<T
 | 
			
		||||
    , integer_arithmetic<T
 | 
			
		||||
    , bitwise<T
 | 
			
		||||
    , unit_steppable<T
 | 
			
		||||
      > > > > {};
 | 
			
		||||
 | 
			
		||||
//  Iterator helper classes (contributed by Jeremy Siek) -------------------//
 | 
			
		||||
//  (Input and output iterator helpers contributed by Daryle Walker) -------//
 | 
			
		||||
//  (Changed to use combined operator classes by Daryle Walker) ------------//
 | 
			
		||||
template <class T,
 | 
			
		||||
          class V,
 | 
			
		||||
          class D = std::ptrdiff_t,
 | 
			
		||||
          class P = V const *,
 | 
			
		||||
          class R = V const &>
 | 
			
		||||
struct input_iterator_helper
 | 
			
		||||
  : equality_comparable1<T
 | 
			
		||||
  , incrementable<T
 | 
			
		||||
  , dereferenceable<T, P
 | 
			
		||||
  , boost::iterator<std::input_iterator_tag, V, D, P, R
 | 
			
		||||
    > > > > {};
 | 
			
		||||
 | 
			
		||||
template<class Derived>
 | 
			
		||||
struct output_iterator_helper
 | 
			
		||||
  : boost::incrementable<Derived
 | 
			
		||||
  , boost::iterator<std::output_iterator_tag, void, void, void, void
 | 
			
		||||
  > >
 | 
			
		||||
{
 | 
			
		||||
  Derived& operator*()  { return static_cast<Derived&>(*this); }
 | 
			
		||||
  Derived& operator++() { return static_cast<Derived&>(*this); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T,
 | 
			
		||||
          class V,
 | 
			
		||||
          class D = std::ptrdiff_t,
 | 
			
		||||
          class P = V*,
 | 
			
		||||
          class R = V&>
 | 
			
		||||
struct forward_iterator_helper
 | 
			
		||||
  : equality_comparable<T
 | 
			
		||||
  : equality_comparable1<T
 | 
			
		||||
  , incrementable<T
 | 
			
		||||
  , dereferenceable<T,P
 | 
			
		||||
  , boost::iterator<std::forward_iterator_tag, V, D
 | 
			
		||||
  , dereferenceable<T, P
 | 
			
		||||
  , boost::iterator<std::forward_iterator_tag, V, D, P, R
 | 
			
		||||
    > > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T,
 | 
			
		||||
@@ -523,12 +733,11 @@ template <class T,
 | 
			
		||||
          class P = V*,
 | 
			
		||||
          class R = V&>
 | 
			
		||||
struct bidirectional_iterator_helper
 | 
			
		||||
  : equality_comparable<T
 | 
			
		||||
  , incrementable<T
 | 
			
		||||
  , decrementable<T
 | 
			
		||||
  , dereferenceable<T,P
 | 
			
		||||
  , boost::iterator<std::bidirectional_iterator_tag, V, D
 | 
			
		||||
    > > > > > {};
 | 
			
		||||
  : equality_comparable1<T
 | 
			
		||||
  , unit_steppable<T
 | 
			
		||||
  , dereferenceable<T, P
 | 
			
		||||
  , boost::iterator<std::bidirectional_iterator_tag, V, D, P, R
 | 
			
		||||
    > > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T,
 | 
			
		||||
          class V, 
 | 
			
		||||
@@ -536,22 +745,17 @@ template <class T,
 | 
			
		||||
          class P = V*,
 | 
			
		||||
          class R = V&>
 | 
			
		||||
struct random_access_iterator_helper
 | 
			
		||||
  : equality_comparable<T
 | 
			
		||||
  , less_than_comparable<T
 | 
			
		||||
  , incrementable<T
 | 
			
		||||
  , decrementable<T
 | 
			
		||||
  , dereferenceable<T,P
 | 
			
		||||
  , addable2<T,D
 | 
			
		||||
  , subtractable2<T,D
 | 
			
		||||
  , indexable<T,D,R
 | 
			
		||||
  , boost::iterator<std::random_access_iterator_tag, V, D
 | 
			
		||||
    > > > > > > > > >
 | 
			
		||||
  : totally_ordered1<T
 | 
			
		||||
  , unit_steppable<T
 | 
			
		||||
  , dereferenceable<T, P
 | 
			
		||||
  , additive2<T, D
 | 
			
		||||
  , indexable<T, D, R
 | 
			
		||||
  , boost::iterator<std::random_access_iterator_tag, V, D, P, R
 | 
			
		||||
    > > > > > >
 | 
			
		||||
{
 | 
			
		||||
#ifndef __BORLANDC__
 | 
			
		||||
  friend D requires_difference_operator(const T& x, const T& y) {
 | 
			
		||||
    return x - y;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}; // random_access_iterator_helper
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,9 @@
 | 
			
		||||
//  Classes appear in alphabetical order
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  21 May 01  checked_delete() and checked_array_delete() added (Beman Dawes,
 | 
			
		||||
//             suggested by Dave Abrahams, generalizing idea from Vladimir Prus)
 | 
			
		||||
//  21 May 01  made next() and prior() inline (Beman Dawes)  
 | 
			
		||||
//  26 Jan 00  protected noncopyable destructor added (Miki Jovanovic)
 | 
			
		||||
//  10 Dec 99  next() and prior() templates added (Dave Abrahams)
 | 
			
		||||
//  30 Aug 99  moved cast templates to cast.hpp (Beman Dawes)
 | 
			
		||||
@@ -22,12 +25,32 @@
 | 
			
		||||
#ifndef BOOST_UTILITY_HPP
 | 
			
		||||
#define BOOST_UTILITY_HPP
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <cstddef>            // for size_t
 | 
			
		||||
#include <utility>            // for std::pair
 | 
			
		||||
#include <boost/config.hpp>        // broken compiler workarounds 
 | 
			
		||||
#include <boost/static_assert.hpp> 
 | 
			
		||||
#include <cstddef>                 // for size_t
 | 
			
		||||
#include <utility>                 // for std::pair
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
//  checked_delete() and checked_array_delete()  -----------------------------//
 | 
			
		||||
 | 
			
		||||
    // verify that types are complete for increased safety
 | 
			
		||||
 | 
			
		||||
    template< typename T >
 | 
			
		||||
    inline void checked_delete(T * x)
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point
 | 
			
		||||
                                               // of instantiation
 | 
			
		||||
        delete x;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template< typename T >
 | 
			
		||||
    inline void checked_array_delete(T  * x)
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_STATIC_ASSERT( sizeof(T) != 0 ); // assert type complete at point
 | 
			
		||||
                                               // of instantiation
 | 
			
		||||
        delete [] x;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
//  next() and prior() template functions  -----------------------------------//
 | 
			
		||||
 | 
			
		||||
@@ -41,10 +64,10 @@ namespace boost
 | 
			
		||||
    //  Contributed by Dave Abrahams
 | 
			
		||||
 | 
			
		||||
    template <class T>
 | 
			
		||||
    T next(T x) { return ++x; }
 | 
			
		||||
    inline T next(T x) { return ++x; }
 | 
			
		||||
 | 
			
		||||
    template <class T>
 | 
			
		||||
    T prior(T x) { return --x; }
 | 
			
		||||
    inline T prior(T x) { return --x; }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//  class noncopyable  -------------------------------------------------------//
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										443
									
								
								indirect_iterator.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										443
									
								
								indirect_iterator.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,443 @@
 | 
			
		||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
 | 
			
		||||
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <meta name="generator" content="HTML Tidy, see www.w3.org">
 | 
			
		||||
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
 | 
			
		||||
    <meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
    <meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
 | 
			
		||||
    <title>Indirect Iterator Adaptor Documentation</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
	
 | 
			
		||||
    <img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
 | 
			
		||||
    "center" width="277" height="86"> 
 | 
			
		||||
 | 
			
		||||
    <h1>Indirect Iterator Adaptor</h1>
 | 
			
		||||
    Defined in header <a href=
 | 
			
		||||
    "../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a> 
 | 
			
		||||
 | 
			
		||||
    <p>The indirect iterator adaptor augments an iterator by applying an
 | 
			
		||||
    <b>extra</b> dereference inside of <tt>operator*()</tt>. For example, this
 | 
			
		||||
    iterator makes it possible to view a container of pointers or
 | 
			
		||||
    smart-pointers (e.g. <tt>std::list<boost::shared_ptr<foo>
 | 
			
		||||
    ></tt>) as if it were a container of the pointed-to type. The following
 | 
			
		||||
    <b>pseudo-code</b> shows the basic idea of the indirect iterator:
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
// inside a hypothetical indirect_iterator class...
 | 
			
		||||
typedef std::iterator_traits<BaseIterator>::value_type Pointer;
 | 
			
		||||
typedef std::iterator_traits<Pointer>::reference reference;
 | 
			
		||||
 | 
			
		||||
reference indirect_iterator::operator*() const {
 | 
			
		||||
  return **this->base_iterator;
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <h2>Synopsis</h2>
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
namespace boost {
 | 
			
		||||
  template <class BaseIterator,
 | 
			
		||||
            class Value, class Reference, class Category, class Pointer>
 | 
			
		||||
  struct indirect_iterator_generator;
 | 
			
		||||
  
 | 
			
		||||
  template <class BaseIterator,
 | 
			
		||||
            class Value, class Reference, class ConstReference, 
 | 
			
		||||
            class Category, class Pointer, class ConstPointer>
 | 
			
		||||
  struct indirect_iterator_pair_generator;
 | 
			
		||||
 | 
			
		||||
  template <class BaseIterator>
 | 
			
		||||
  typename indirect_iterator_generator<BaseIterator>::type
 | 
			
		||||
  make_indirect_iterator(BaseIterator base)  
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <h2><a name="indirect_iterator_generator">The Indirect Iterator Type
 | 
			
		||||
    Generator</a></h2>
 | 
			
		||||
    The <tt>indirect_iterator_generator</tt> template is a <a href=
 | 
			
		||||
    "../../more/generic_programming.html#type_generator">generator</a> of
 | 
			
		||||
    indirect iterator types. The main template parameter for this class is the
 | 
			
		||||
    <tt>BaseIterator</tt> type that is being wrapped. In most cases the type of
 | 
			
		||||
    the elements being pointed to can be deduced using
 | 
			
		||||
    <tt>std::iterator_traits</tt>, but in some situations the user may want to
 | 
			
		||||
    override this type, so there are also template parameters that allow a user
 | 
			
		||||
    to control the <tt>value_type</tt>, <tt>pointer</tt>, and
 | 
			
		||||
    <tt>reference</tt> types of the resulting iterators. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
template <class BaseIterator,
 | 
			
		||||
          class Value, class Reference, class Pointer>
 | 
			
		||||
class indirect_iterator_generator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  typedef <tt><a href=
 | 
			
		||||
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> type; // the resulting indirect iterator type 
 | 
			
		||||
};
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <h3>Example</h3>
 | 
			
		||||
    This example uses the <tt>indirect_iterator_generator</tt> to create
 | 
			
		||||
    indirect iterators which dereference the pointers stored in the
 | 
			
		||||
    <tt>pointers_to_chars</tt> array to access the <tt>char</tt>s in the
 | 
			
		||||
    <tt>characters</tt> array. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  char characters[] = "abcdefg";
 | 
			
		||||
  const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
 | 
			
		||||
  char* pointers_to_chars[N];                        // at the end.
 | 
			
		||||
  for (int i = 0; i < N; ++i)
 | 
			
		||||
    pointers_to_chars[i] = &characters[i];
 | 
			
		||||
  
 | 
			
		||||
  boost::indirect_iterator_generator<char**, char>::type 
 | 
			
		||||
    indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
 | 
			
		||||
 | 
			
		||||
  std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  // to be continued...
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <h3>Template Parameters</h3>
 | 
			
		||||
 | 
			
		||||
    <table border>
 | 
			
		||||
      <tr>
 | 
			
		||||
        <th>Parameter
 | 
			
		||||
 | 
			
		||||
        <th>Description
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>BaseIterator</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The iterator type being wrapped. The <tt>value_type</tt>
 | 
			
		||||
        of the base iterator should itself be dereferenceable.  
 | 
			
		||||
        The return type of the <tt>operator*</tt> for the
 | 
			
		||||
        <tt>value_type</tt> should match the <tt>Reference</tt> type.
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Value</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>value_type</tt> of the resulting iterator, unless const. If
 | 
			
		||||
        Value is <tt>const X</tt>, a conforming compiler makes the
 | 
			
		||||
        <tt>value_type</tt> <tt><i>non-</i>const X</tt><a href=
 | 
			
		||||
        "iterator_adaptors.htm#1">[1]</a>. Note that if the default
 | 
			
		||||
         is used for <tt>Value</tt>, then there must be a valid specialization
 | 
			
		||||
         of <tt>iterator_traits</tt> for the value type of the base iterator.
 | 
			
		||||
         <br>
 | 
			
		||||
         <b>Default:</b> <tt>std::iterator_traits<<br>
 | 
			
		||||
         <20> std::iterator_traits<BaseIterator>::value_type
 | 
			
		||||
        >::value_type</tt><a href="#2">[2]</a> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Reference</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>reference</tt> type of the resulting iterator, and in
 | 
			
		||||
        particular, the result type of <tt>operator*()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> <tt>Value&</tt> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Pointer</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>pointer</tt> type of the resulting iterator, and in
 | 
			
		||||
        particular, the result type of <tt>operator->()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> <tt>Value*</tt> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Category</tt> 
 | 
			
		||||
        <td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
 | 
			
		||||
         <b>Default:</b>
 | 
			
		||||
        <tt>std::iterator_traits<BaseIterator>::iterator_category</tt> 
 | 
			
		||||
 | 
			
		||||
    </table>
 | 
			
		||||
 | 
			
		||||
    <h3>Concept Model</h3>
 | 
			
		||||
    The indirect iterator will model whichever <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/Iterators.html">standard iterator
 | 
			
		||||
    concept category</a> is modeled by the base iterator. Thus, if the
 | 
			
		||||
    base iterator is a model of <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
 | 
			
		||||
    Access Iterator</a> then so is the resulting indirect iterator. If
 | 
			
		||||
    the base iterator models a more restrictive concept, the resulting
 | 
			
		||||
    indirect iterator will model the same concept <a href="#3">[3]</a>.
 | 
			
		||||
 | 
			
		||||
    <h3>Members</h3>
 | 
			
		||||
    The indirect iterator type implements the member functions and operators
 | 
			
		||||
    required of the <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
 | 
			
		||||
    Iterator</a> concept. In addition it has the following constructor: 
 | 
			
		||||
<pre>
 | 
			
		||||
explicit indirect_iterator_generator::type(const BaseIterator& it)
 | 
			
		||||
</pre>
 | 
			
		||||
    <br>
 | 
			
		||||
     <br>
 | 
			
		||||
     
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <p>
 | 
			
		||||
 | 
			
		||||
    <h2><a name="indirect_iterator_pair_generator">The Indirect Iterator Pair
 | 
			
		||||
    Generator</a></h2>
 | 
			
		||||
    Sometimes a pair of <tt>const</tt>/non-<tt>const</tt> pair of iterators is
 | 
			
		||||
    needed, such as when implementing a container. The
 | 
			
		||||
    <tt>indirect_iterator_pair_generator</tt> class makes it more convenient to
 | 
			
		||||
    create this pair of iterator types. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
template <class BaseIterator,
 | 
			
		||||
          class Value, class Pointer, class Reference,
 | 
			
		||||
          class ConstPointer, class ConstReference>
 | 
			
		||||
class indirect_iterator_pair_generator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  typedef <tt><a href=
 | 
			
		||||
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> iterator;       // the mutable indirect iterator type 
 | 
			
		||||
  typedef <tt><a href=
 | 
			
		||||
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> const_iterator; // the immutable indirect iterator type 
 | 
			
		||||
};
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <h3>Example</h3>
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
  // continuing from the last example...
 | 
			
		||||
 | 
			
		||||
  typedef boost::indirect_iterator_pair_generator<char**,
 | 
			
		||||
    char, char*, char&, const char*, const char&> PairGen;
 | 
			
		||||
 | 
			
		||||
  char mutable_characters[N];
 | 
			
		||||
  char* pointers_to_mutable_chars[N];
 | 
			
		||||
  for (int i = 0; i < N; ++i)
 | 
			
		||||
    pointers_to_mutable_chars[i] = &mutable_characters[i];
 | 
			
		||||
 | 
			
		||||
  PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars),
 | 
			
		||||
    mutable_indirect_last(pointers_to_mutable_chars + N);
 | 
			
		||||
  PairGen::const_iterator const_indirect_first(pointers_to_chars),
 | 
			
		||||
    const_indirect_last(pointers_to_chars + N);
 | 
			
		||||
 | 
			
		||||
  std::transform(const_indirect_first, const_indirect_last,
 | 
			
		||||
     mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
 | 
			
		||||
 | 
			
		||||
  std::copy(mutable_indirect_first, mutable_indirect_last,
 | 
			
		||||
      std::ostream_iterator<char>(std::cout, ","));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  // to be continued...
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <p>The output is:
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
b,c,d,e,f,g,h,
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <h3>Template Parameters</h3>
 | 
			
		||||
 | 
			
		||||
    <table border>
 | 
			
		||||
      <tr>
 | 
			
		||||
        <th>Parameter
 | 
			
		||||
 | 
			
		||||
        <th>Description
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>BaseIterator</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The iterator type being wrapped. The <tt>value_type</tt> of the
 | 
			
		||||
        base iterator should itself be dereferenceable.
 | 
			
		||||
        The return type of the <tt>operator*</tt> for the
 | 
			
		||||
        <tt>value_type</tt> should match the <tt>Reference</tt> type.
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Value</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>value_type</tt> of the resulting iterators.
 | 
			
		||||
         If Value is <tt>const X</tt>, a conforming compiler makes the
 | 
			
		||||
         <tt>value_type</tt> <tt><i>non-</i>const X</tt><a href=
 | 
			
		||||
         "iterator_adaptors.htm#1">[1]</a>. Note that if the default
 | 
			
		||||
         is used for <tt>Value</tt>, then there must be a valid
 | 
			
		||||
         specialization of <tt>iterator_traits</tt> for the value type
 | 
			
		||||
         of the base iterator.<br>
 | 
			
		||||
 | 
			
		||||
         <b>Default:</b> <tt>std::iterator_traits<<br>
 | 
			
		||||
         <20> std::iterator_traits<BaseIterator>::value_type
 | 
			
		||||
        >::value_type</tt><a href="#2">[2]</a> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Reference</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>reference</tt> type of the resulting <tt>iterator</tt>, and
 | 
			
		||||
        in particular, the result type of its <tt>operator*()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> <tt>Value&</tt> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Pointer</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>pointer</tt> type of the resulting <tt>iterator</tt>, and
 | 
			
		||||
        in particular, the result type of its <tt>operator->()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> <tt>Value*</tt> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>ConstReference</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>reference</tt> type of the resulting
 | 
			
		||||
        <tt>const_iterator</tt>, and in particular, the result type of its
 | 
			
		||||
        <tt>operator*()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> <tt>const Value&</tt> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>ConstPointer</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>pointer</tt> type of the resulting <tt>const_iterator</tt>,
 | 
			
		||||
        and in particular, the result type of its <tt>operator->()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> <tt>const Value*</tt> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Category</tt> 
 | 
			
		||||
        <td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
 | 
			
		||||
         <b>Default:</b>
 | 
			
		||||
        <tt>std::iterator_traits<BaseIterator>::iterator_category</tt> 
 | 
			
		||||
    </table>
 | 
			
		||||
 | 
			
		||||
    <h3>Concept Model</h3>
 | 
			
		||||
 | 
			
		||||
    The indirect iterators will model whichever <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/Iterators.html">standard iterator
 | 
			
		||||
    concept category</a> is modeled by the base iterator. Thus, if the
 | 
			
		||||
    base iterator is a model of <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
 | 
			
		||||
    Access Iterator</a> then so are the resulting indirect
 | 
			
		||||
    iterators. If the base iterator models a more restrictive concept,
 | 
			
		||||
    the resulting indirect iterators will model the same concept <a
 | 
			
		||||
    href="#3">[3]</a>.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <h3>Members</h3>
 | 
			
		||||
    The resulting <tt>iterator</tt> and <tt>const_iterator</tt> types implement
 | 
			
		||||
    the member functions and operators required of the <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
 | 
			
		||||
    Iterator</a> concept. In addition they support the following constructors: 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
explicit indirect_iterator_pair_generator::iterator(const BaseIterator& it)
 | 
			
		||||
explicit indirect_iterator_pair_generator::const_iterator(const BaseIterator& it)
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
    <br>
 | 
			
		||||
     <br>
 | 
			
		||||
     
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <p>
 | 
			
		||||
 | 
			
		||||
    <h2><a name="make_indirect_iterator">The Indirect Iterator Object
 | 
			
		||||
    Generator</a></h2>
 | 
			
		||||
    The <tt>make_indirect_iterator()</tt> function provides a more convenient
 | 
			
		||||
    way to create indirect iterator objects. The function saves the user the
 | 
			
		||||
    trouble of explicitly writing out the iterator types. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
template <class BaseIterator>
 | 
			
		||||
typename indirect_iterator_generator<BaseIterator>::type
 | 
			
		||||
make_indirect_iterator(BaseIterator base)  
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <h3>Example</h3>
 | 
			
		||||
    Here we again print the <tt>char</tt>s from the array <tt>characters</tt>
 | 
			
		||||
    by accessing them through the array of pointers <tt>pointer_to_chars</tt>,
 | 
			
		||||
    but this time we use the <tt>make_indirect_iterator()</tt> function which
 | 
			
		||||
    saves us some typing. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
  // continuing from the last example...
 | 
			
		||||
 | 
			
		||||
  std::copy(boost::make_indirect_iterator(pointers_to_chars), 
 | 
			
		||||
      boost::make_indirect_iterator(pointers_to_chars + N),
 | 
			
		||||
      std::ostream_iterator<char>(std::cout, ","));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
    The output is: 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
a,b,c,d,e,f,g,
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <h3>Notes</h3>
 | 
			
		||||
 | 
			
		||||
    <p>
 | 
			
		||||
 | 
			
		||||
    <p><a name="2">[2]</a> If your compiler does not support partial
 | 
			
		||||
    specialization and the base iterator or its <tt>value_type</tt> is a
 | 
			
		||||
    builtin pointer type, you will not be able to use the default for
 | 
			
		||||
    <tt>Value</tt> and will need to specify this type explicitly.
 | 
			
		||||
 | 
			
		||||
    <p><a name="3">[3]</a>There is a caveat to which concept the
 | 
			
		||||
    indirect iterator can model.  If the return type of the
 | 
			
		||||
    <tt>operator*</tt> for the base iterator's value type is not a
 | 
			
		||||
    true reference, then strickly speaking, the indirect iterator can
 | 
			
		||||
    not be a model of <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
 | 
			
		||||
    Iterator</a> or any of the concepts that refine it. In this case
 | 
			
		||||
    the <tt>Category</tt> for the indirect iterator should be
 | 
			
		||||
    specified as <tt>std::input_iterator_tag</tt>. However, even in
 | 
			
		||||
    this case, if the base iterator is a random access iterator, the
 | 
			
		||||
    resulting indirect iterator will still satisfy most of the
 | 
			
		||||
    requirements for <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
 | 
			
		||||
    Access Iterator</a>.
 | 
			
		||||
    
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <p>Revised 
 | 
			
		||||
    <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->17 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14763" -->
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <p>© Copyright Jeremy Siek and David Abrahams 2001. Permission to
 | 
			
		||||
    copy, use, modify, sell and distribute this document is granted provided
 | 
			
		||||
    this copyright notice appears in all copies. This document is provided "as
 | 
			
		||||
    is" without express or implied warranty, and with no claim as to its
 | 
			
		||||
    suitability for any purpose. 
 | 
			
		||||
    <!--  LocalWords:  html charset alt gif hpp BaseIterator const namespace struct
 | 
			
		||||
             -->
 | 
			
		||||
     
 | 
			
		||||
    <!--  LocalWords:  ConstPointer ConstReference typename iostream int abcdefg
 | 
			
		||||
             -->
 | 
			
		||||
     <!--  LocalWords:  sizeof  PairGen pre Jeremy Siek David Abrahams
 | 
			
		||||
             -->
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										60
									
								
								indirect_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								indirect_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  char characters[] = "abcdefg";
 | 
			
		||||
  const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
 | 
			
		||||
  char* pointers_to_chars[N];                        // at the end.
 | 
			
		||||
  for (int i = 0; i < N; ++i)
 | 
			
		||||
    pointers_to_chars[i] = &characters[i];
 | 
			
		||||
 | 
			
		||||
  // Example of using indirect_iterator_generator
 | 
			
		||||
  
 | 
			
		||||
  boost::indirect_iterator_generator<char**, char>::type 
 | 
			
		||||
    indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
 | 
			
		||||
 | 
			
		||||
  std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  // Example of using indirect_iterator_pair_generator
 | 
			
		||||
 | 
			
		||||
  typedef boost::indirect_iterator_pair_generator<char**, char> PairGen;
 | 
			
		||||
 | 
			
		||||
  char mutable_characters[N];
 | 
			
		||||
  char* pointers_to_mutable_chars[N];
 | 
			
		||||
  for (int i = 0; i < N; ++i)
 | 
			
		||||
    pointers_to_mutable_chars[i] = &mutable_characters[i];
 | 
			
		||||
 | 
			
		||||
  PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars),
 | 
			
		||||
    mutable_indirect_last(pointers_to_mutable_chars + N);
 | 
			
		||||
  PairGen::const_iterator const_indirect_first(pointers_to_chars),
 | 
			
		||||
    const_indirect_last(pointers_to_chars + N);
 | 
			
		||||
 | 
			
		||||
  std::transform(const_indirect_first, const_indirect_last,
 | 
			
		||||
		 mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
 | 
			
		||||
 | 
			
		||||
  std::copy(mutable_indirect_first, mutable_indirect_last,
 | 
			
		||||
	    std::ostream_iterator<char>(std::cout, ","));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  // Example of using make_indirect_iterator()
 | 
			
		||||
 | 
			
		||||
  std::copy(boost::make_indirect_iterator(pointers_to_chars), 
 | 
			
		||||
	    boost::make_indirect_iterator(pointers_to_chars + N),
 | 
			
		||||
	    std::ostream_iterator<char>(std::cout, ","));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										27
									
								
								iter_adaptor_fail_expected1.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								iter_adaptor_fail_expected1.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
//  Test boost/pending/iterator_adaptors.hpp
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
// Revision History
 | 
			
		||||
// 21 Jan 01 Initial version (Jeremy Siek)
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <boost/pending/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
  typedef boost::iterator_adaptor<std::list<int>::iterator,
 | 
			
		||||
    boost::default_iterator_policies,
 | 
			
		||||
    int,int&,int*,std::bidirectional_iterator_tag> adaptor_type;
 | 
			
		||||
  
 | 
			
		||||
  adaptor_type i;
 | 
			
		||||
  i += 4;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								iter_adaptor_fail_expected2.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								iter_adaptor_fail_expected2.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
//  Test boost/pending/iterator_adaptors.hpp
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
// Revision History
 | 
			
		||||
// 21 Jan 01 Initial version (Jeremy Siek)
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <boost/pending/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
  typedef boost::iterator_adaptor<std::istream_iterator<int>,
 | 
			
		||||
    boost::default_iterator_policies,
 | 
			
		||||
    int,int&,int*,std::input_iterator_tag> adaptor_type;
 | 
			
		||||
  
 | 
			
		||||
  adaptor_type iter;
 | 
			
		||||
  --iter;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										61
									
								
								iter_traits_gen_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								iter_traits_gen_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify,
 | 
			
		||||
// sell and distribute this software is granted provided this
 | 
			
		||||
// copyright notice appears in all copies. This software is provided
 | 
			
		||||
// "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
// to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
// 8 Mar 2001   Jeremy Siek
 | 
			
		||||
//     Initial checkin.
 | 
			
		||||
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
#include <boost/pending/iterator_tests.hpp>
 | 
			
		||||
#include <boost/static_assert.hpp>
 | 
			
		||||
 | 
			
		||||
class bar { };
 | 
			
		||||
void foo(bar) { }
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main()
 | 
			
		||||
{
 | 
			
		||||
  using boost::dummyT;
 | 
			
		||||
  dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), 
 | 
			
		||||
		     dummyT(3), dummyT(4), dummyT(5) };
 | 
			
		||||
  typedef boost::iterator_adaptor<dummyT*, 
 | 
			
		||||
    boost::default_iterator_policies, dummyT> my_iter;
 | 
			
		||||
  my_iter mi(array);
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    typedef boost::iterator_adaptor<my_iter, boost::default_iterator_policies,
 | 
			
		||||
      boost::iterator_traits_generator
 | 
			
		||||
      ::reference<dummyT>
 | 
			
		||||
      ::iterator_category<std::input_iterator_tag> > iter_type;
 | 
			
		||||
 | 
			
		||||
    BOOST_STATIC_ASSERT((boost::is_same<iter_type::iterator_category*,
 | 
			
		||||
       std::input_iterator_tag*>::value));
 | 
			
		||||
 | 
			
		||||
    BOOST_STATIC_ASSERT(( ! boost::is_convertible<iter_type::iterator_category*,
 | 
			
		||||
       std::forward_iterator_tag*>::value));
 | 
			
		||||
 | 
			
		||||
    iter_type i(mi);
 | 
			
		||||
    boost::input_iterator_test(i, dummyT(0), dummyT(1));
 | 
			
		||||
  }
 | 
			
		||||
  {
 | 
			
		||||
    typedef boost::iterator_adaptor<dummyT*,
 | 
			
		||||
      boost::default_iterator_policies,
 | 
			
		||||
      boost::iterator_traits_generator
 | 
			
		||||
        ::value_type<dummyT>
 | 
			
		||||
        ::reference<const dummyT&>
 | 
			
		||||
        ::pointer<const dummyT*> 
 | 
			
		||||
        ::iterator_category<std::forward_iterator_tag>
 | 
			
		||||
        ::difference_type<std::ptrdiff_t> > adaptor_type;
 | 
			
		||||
 | 
			
		||||
    adaptor_type i(array);
 | 
			
		||||
 | 
			
		||||
    boost::input_iterator_test(i, dummyT(0), dummyT(1));
 | 
			
		||||
    int zero = 0;
 | 
			
		||||
    if (zero) // don't do this, just make sure it compiles
 | 
			
		||||
      assert((*i).m_x == i->foo());      
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
//  Demonstrate and test boost/operators.hpp on std::iterators  -------------//
 | 
			
		||||
//  Test boost/iterator_adaptors.hpp
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
@@ -9,6 +9,36 @@
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  08 Mar 01 Moved indirect and transform tests to separate files.
 | 
			
		||||
//            (Jeremy Siek)
 | 
			
		||||
//  19 Feb 01 Take adavantage of improved iterator_traits to do more tests
 | 
			
		||||
//            on MSVC. Hack around an MSVC-with-STLport internal compiler
 | 
			
		||||
//            error. (David Abrahams)
 | 
			
		||||
//  11 Feb 01 Added test of operator-> for forward and input iterators.
 | 
			
		||||
//            (Jeremy Siek)
 | 
			
		||||
//  11 Feb 01 Borland fixes (David Abrahams)
 | 
			
		||||
//  10 Feb 01 Use new adaptors interface. (David Abrahams)
 | 
			
		||||
//  10 Feb 01 Use new filter_ interface. (David Abrahams)
 | 
			
		||||
//  09 Feb 01 Use new reverse_ and indirect_ interfaces. Replace
 | 
			
		||||
//            BOOST_NO_STD_ITERATOR_TRAITS with
 | 
			
		||||
//            BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION to prove we've
 | 
			
		||||
//            normalized to core compiler capabilities (David Abrahams)
 | 
			
		||||
//  08 Feb 01 Use Jeremy's new make_reverse_iterator form; add more
 | 
			
		||||
//            comprehensive testing. Force-decay array function arguments to
 | 
			
		||||
//            pointers.
 | 
			
		||||
//  07 Feb 01 Added tests for the make_xxx_iterator() helper functions.
 | 
			
		||||
//            (Jeremy Siek)
 | 
			
		||||
//  07 Feb 01 Replaced use of xxx_pair_generator with xxx_generator where
 | 
			
		||||
//            possible (which was all but the projection iterator).
 | 
			
		||||
//            (Jeremy Siek)
 | 
			
		||||
//  06 Feb 01 Removed now-defaulted template arguments where possible
 | 
			
		||||
//            Updated names to correspond to new generator naming convention.
 | 
			
		||||
//            Added a trivial test for make_transform_iterator().
 | 
			
		||||
//            Gave traits for const iterators a mutable value_type, per std.
 | 
			
		||||
//            Resurrected my original tests for indirect iterators.
 | 
			
		||||
//            (David Abrahams)
 | 
			
		||||
//  04 Feb 01 Fix for compilers without standard iterator_traits
 | 
			
		||||
//            (David Abrahams)
 | 
			
		||||
//  13 Jun 00 Added const version of the iterator tests (Jeremy Siek)
 | 
			
		||||
//  12 Dec 99 Initial version with iterator operators (Jeremy Siek)
 | 
			
		||||
 | 
			
		||||
@@ -17,34 +47,20 @@
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <boost/pending/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
#include <boost/pending/iterator_tests.hpp>
 | 
			
		||||
#include <boost/pending/integer_range.hpp>
 | 
			
		||||
#include <boost/concept_archetype.hpp>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <deque>
 | 
			
		||||
#include <set>
 | 
			
		||||
 | 
			
		||||
struct my_iterator_tag : public std::random_access_iterator_tag { };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
using boost::dummyT;
 | 
			
		||||
 | 
			
		||||
struct my_iter_traits {
 | 
			
		||||
  typedef dummyT value_type;
 | 
			
		||||
  typedef dummyT* pointer;
 | 
			
		||||
  typedef dummyT& reference;
 | 
			
		||||
  typedef my_iterator_tag iterator_category;
 | 
			
		||||
  typedef std::ptrdiff_t difference_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct my_const_iter_traits {
 | 
			
		||||
  typedef dummyT value_type;
 | 
			
		||||
  typedef const dummyT* pointer;
 | 
			
		||||
  typedef const dummyT& reference;
 | 
			
		||||
  typedef my_iterator_tag iterator_category;
 | 
			
		||||
  typedef std::ptrdiff_t difference_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef boost::iterator_adaptors
 | 
			
		||||
  <dummyT*, const dummyT*, 
 | 
			
		||||
   my_iter_traits, my_const_iter_traits> My;
 | 
			
		||||
 | 
			
		||||
struct mult_functor {
 | 
			
		||||
  typedef int result_type;
 | 
			
		||||
@@ -71,6 +87,16 @@ struct select1st_
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct one_or_four {
 | 
			
		||||
  bool operator()(dummyT x) const {
 | 
			
		||||
    return x.foo() == 1 || x.foo() == 4;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef std::deque<int> storage;
 | 
			
		||||
typedef std::deque<int*> pointer_deque;
 | 
			
		||||
typedef std::set<storage::iterator> iterator_set;
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main()
 | 
			
		||||
{
 | 
			
		||||
@@ -81,88 +107,121 @@ main()
 | 
			
		||||
  // sanity check, if this doesn't pass the test is buggy
 | 
			
		||||
  boost::random_access_iterator_test(array,N,array);
 | 
			
		||||
 | 
			
		||||
  // Test the iterator_adaptors
 | 
			
		||||
  // Check that the policy concept checks and the default policy
 | 
			
		||||
  // implementation match up.
 | 
			
		||||
  boost::function_requires< 
 | 
			
		||||
     boost::RandomAccessIteratorPoliciesConcept<
 | 
			
		||||
       boost::default_iterator_policies, int*,
 | 
			
		||||
       boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
 | 
			
		||||
                      int*, int&>
 | 
			
		||||
      > >();
 | 
			
		||||
 | 
			
		||||
  // 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);
 | 
			
		||||
    
 | 
			
		||||
    My::const_iterator j = array;
 | 
			
		||||
    boost::iterator_adaptor<const dummyT*, boost::default_iterator_policies, const dummyT> j(array);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);
 | 
			
		||||
  }
 | 
			
		||||
  // Test transform_iterator
 | 
			
		||||
  {
 | 
			
		||||
    int x[N], y[N];
 | 
			
		||||
    for (int k = 0; k < N; ++k)
 | 
			
		||||
      x[k] = k;
 | 
			
		||||
    std::copy(x, x + N, y);
 | 
			
		||||
 | 
			
		||||
    for (int k2 = 0; k2 < N; ++k2)
 | 
			
		||||
      x[k2] = x[k2] * 2;
 | 
			
		||||
 | 
			
		||||
    boost::transform_iterator<mult_functor, int*,
 | 
			
		||||
      boost::iterator<std::random_access_iterator_tag,int> >::type
 | 
			
		||||
      i(y, mult_functor(2));
 | 
			
		||||
    boost::random_access_iterator_test(i, N, x);
 | 
			
		||||
  }
 | 
			
		||||
  // Test indirect_iterators
 | 
			
		||||
  {
 | 
			
		||||
    dummyT* ptr[N];
 | 
			
		||||
    for (int k = 0; k < N; ++k)
 | 
			
		||||
      ptr[k] = array + k;
 | 
			
		||||
    typedef boost::indirect_iterators<dummyT**, dummyT*, const dummyT*,
 | 
			
		||||
      boost::iterator<std::random_access_iterator_tag, dummyT*>,
 | 
			
		||||
      boost::iterator<std::random_access_iterator_tag, dummyT>,
 | 
			
		||||
      boost::iterator<std::random_access_iterator_tag, const dummyT>
 | 
			
		||||
      > Indirect;
 | 
			
		||||
    Indirect::iterator i = ptr;
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
 | 
			
		||||
    Indirect::const_iterator j = ptr;
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);    
 | 
			
		||||
  }
 | 
			
		||||
  // Test projection_iterators
 | 
			
		||||
  // Test projection_iterator_pair_generator
 | 
			
		||||
  {    
 | 
			
		||||
    typedef std::pair<dummyT,dummyT> Pair;
 | 
			
		||||
    Pair pair_array[N];
 | 
			
		||||
    for (int k = 0; k < N; ++k)
 | 
			
		||||
      pair_array[k].first = array[k];
 | 
			
		||||
 | 
			
		||||
    typedef boost::projection_iterators<select1st_<Pair>,
 | 
			
		||||
      Pair*, const Pair*,
 | 
			
		||||
      boost::iterator<std::random_access_iterator_tag, Pair>,
 | 
			
		||||
      boost::iterator<std::random_access_iterator_tag, const Pair>
 | 
			
		||||
    typedef boost::projection_iterator_pair_generator<select1st_<Pair>,
 | 
			
		||||
      Pair*, const Pair*
 | 
			
		||||
      > Projection;
 | 
			
		||||
    
 | 
			
		||||
    Projection::iterator i = pair_array;
 | 
			
		||||
    Projection::iterator i(pair_array);
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
 | 
			
		||||
    Projection::const_iterator j = pair_array;
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_projection_iterator(pair_array, select1st_<Pair>()), N, array);    
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_projection_iterator< select1st_<Pair> >(pair_array), N, array);    
 | 
			
		||||
 | 
			
		||||
    Projection::const_iterator j(pair_array);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_const_projection_iterator(pair_array, select1st_<Pair>()), N, array);
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_const_projection_iterator<select1st_<Pair> >(pair_array), N, array);
 | 
			
		||||
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);
 | 
			
		||||
  }
 | 
			
		||||
  // Test reverse_iterators
 | 
			
		||||
 | 
			
		||||
  // Test reverse_iterator_generator
 | 
			
		||||
  {
 | 
			
		||||
    dummyT reversed[N];
 | 
			
		||||
    std::copy(array, array + N, reversed);
 | 
			
		||||
    std::reverse(reversed, reversed + N);
 | 
			
		||||
    
 | 
			
		||||
    typedef boost::reverse_iterators<dummyT*, const dummyT*,
 | 
			
		||||
      boost::iterator<std::random_access_iterator_tag,dummyT>,
 | 
			
		||||
      boost::iterator<std::random_access_iterator_tag,const dummyT>
 | 
			
		||||
      > Reverse;
 | 
			
		||||
    Reverse::iterator i = reversed + N;
 | 
			
		||||
    typedef boost::reverse_iterator_generator<dummyT*
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , dummyT
 | 
			
		||||
#endif
 | 
			
		||||
      >::type reverse_iterator;
 | 
			
		||||
    
 | 
			
		||||
    reverse_iterator i(reversed + N);
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
 | 
			
		||||
    Reverse::const_iterator j = reversed + N;
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    typedef boost::reverse_iterator_generator<const dummyT*
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , const dummyT
 | 
			
		||||
#endif
 | 
			
		||||
      >::type const_reverse_iterator;
 | 
			
		||||
    
 | 
			
		||||
    const_reverse_iterator j(reversed + N);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
 | 
			
		||||
    const dummyT* const_reversed = reversed;
 | 
			
		||||
    
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);    
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Test reverse_iterator_generator again, with traits fully deducible on all platforms
 | 
			
		||||
  {
 | 
			
		||||
    std::deque<dummyT> reversed_container;
 | 
			
		||||
    std::reverse_copy(array, array + N, std::back_inserter(reversed_container));
 | 
			
		||||
    const std::deque<dummyT>::iterator reversed = reversed_container.begin();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    typedef boost::reverse_iterator_generator<
 | 
			
		||||
        std::deque<dummyT>::iterator>::type reverse_iterator;
 | 
			
		||||
    typedef boost::reverse_iterator_generator<
 | 
			
		||||
        std::deque<dummyT>::const_iterator, const dummyT>::type const_reverse_iterator;
 | 
			
		||||
 | 
			
		||||
    // MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation
 | 
			
		||||
    // (e.g. "reversed + N") is used in the constructor below.
 | 
			
		||||
    const std::deque<dummyT>::iterator finish = reversed_container.end();
 | 
			
		||||
    reverse_iterator i(finish);
 | 
			
		||||
    
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
 | 
			
		||||
 | 
			
		||||
    const_reverse_iterator j = reverse_iterator(finish);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
 | 
			
		||||
    const std::deque<dummyT>::const_iterator const_reversed = reversed;
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
 | 
			
		||||
    
 | 
			
		||||
    // Many compilers' builtin deque iterators don't interoperate well, though
 | 
			
		||||
    // STLport fixes that problem.
 | 
			
		||||
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && !defined(BOOST_MSVC)
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Test integer_range's iterators
 | 
			
		||||
  {
 | 
			
		||||
    int int_array[] = { 0, 1, 2, 3, 4, 5 };
 | 
			
		||||
@@ -170,7 +229,107 @@ main()
 | 
			
		||||
    boost::random_access_iterator_test(r.begin(), r.size(), int_array);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::cout << "test successful " << std::endl;
 | 
			
		||||
  // Test filter iterator
 | 
			
		||||
  {
 | 
			
		||||
    // Using typedefs for filter_gen::type confused Borland terribly.
 | 
			
		||||
    typedef boost::detail::non_bidirectional_category<dummyT*>::type category;
 | 
			
		||||
    
 | 
			
		||||
    typedef boost::filter_iterator_generator<one_or_four, dummyT*
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , dummyT
 | 
			
		||||
#endif
 | 
			
		||||
        >::type filter_iter;
 | 
			
		||||
 | 
			
		||||
#if defined(__BORLANDC__)
 | 
			
		||||
    // Borland is choking on accessing the policies_type explicitly
 | 
			
		||||
    // from the filter_iter. 
 | 
			
		||||
    boost::forward_iterator_test(make_filter_iterator(array, array+N, 
 | 
			
		||||
						      one_or_four()),
 | 
			
		||||
				 dummyT(1), dummyT(4));
 | 
			
		||||
#else
 | 
			
		||||
    filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N));
 | 
			
		||||
    boost::forward_iterator_test(i, dummyT(1), dummyT(4));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(__BORLANDC__)
 | 
			
		||||
    // 
 | 
			
		||||
    enum { is_forward = boost::is_same<
 | 
			
		||||
           filter_iter::iterator_category,
 | 
			
		||||
           std::forward_iterator_tag>::value };
 | 
			
		||||
    BOOST_STATIC_ASSERT(is_forward);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    // On compilers not supporting partial specialization, we can do more type
 | 
			
		||||
    // deduction with deque iterators than with pointers... unless the library
 | 
			
		||||
    // is broken ;-(
 | 
			
		||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
 | 
			
		||||
    std::deque<dummyT> array2;
 | 
			
		||||
    std::copy(array+0, array+N, std::back_inserter(array2));
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator(array2.begin(), array2.end(), one_or_four()),
 | 
			
		||||
        dummyT(1), dummyT(4));
 | 
			
		||||
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator<one_or_four>(array2.begin(), array2.end()),
 | 
			
		||||
        dummyT(1), dummyT(4));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(BOOST_MSVC) // This just freaks MSVC out completely
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator<one_or_four>(
 | 
			
		||||
            boost::make_reverse_iterator(array2.end()),
 | 
			
		||||
            boost::make_reverse_iterator(array2.begin())
 | 
			
		||||
            ),
 | 
			
		||||
        dummyT(4), dummyT(1));
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator(array+0, array+N, one_or_four()),
 | 
			
		||||
        dummyT(1), dummyT(4));
 | 
			
		||||
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator<one_or_four>(array, array + N),
 | 
			
		||||
        dummyT(1), dummyT(4));
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // check operator-> with a forward iterator
 | 
			
		||||
  {
 | 
			
		||||
    boost::forward_iterator_archetype<dummyT> forward_iter;
 | 
			
		||||
#if defined(__BORLANDC__)
 | 
			
		||||
    typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
 | 
			
		||||
      boost::default_iterator_policies,
 | 
			
		||||
      dummyT, const dummyT&, const dummyT*, 
 | 
			
		||||
      std::forward_iterator_tag, std::ptrdiff_t> adaptor_type;
 | 
			
		||||
#else
 | 
			
		||||
    typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
 | 
			
		||||
      boost::default_iterator_policies,
 | 
			
		||||
      boost::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);
 | 
			
		||||
    int zero = 0;
 | 
			
		||||
    if (zero) // don't do this, just make sure it compiles
 | 
			
		||||
      assert((*i).m_x == i->foo());      
 | 
			
		||||
  }
 | 
			
		||||
  // check operator-> with an input iterator
 | 
			
		||||
  {
 | 
			
		||||
    boost::input_iterator_archetype<dummyT> input_iter;
 | 
			
		||||
    typedef boost::iterator_adaptor<boost::input_iterator_archetype<dummyT>,
 | 
			
		||||
      boost::default_iterator_policies,
 | 
			
		||||
      dummyT, const dummyT&, const dummyT*, 
 | 
			
		||||
      std::input_iterator_tag, std::ptrdiff_t> adaptor_type;
 | 
			
		||||
    adaptor_type i(input_iter);
 | 
			
		||||
    int zero = 0;
 | 
			
		||||
    if (zero) // don't do this, just make sure it compiles
 | 
			
		||||
      assert((*i).m_x == i->foo());      
 | 
			
		||||
  }
 | 
			
		||||
  std::cout << "test successful " << std::endl;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										210
									
								
								iterator_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								iterator_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,210 @@
 | 
			
		||||
//  (C) Copyright David Abrahams 2001. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  04 Mar 2001 Patches for Intel C++ (Dave Abrahams)
 | 
			
		||||
//  19 Feb 2001 Take advantage of improved iterator_traits to do more tests
 | 
			
		||||
//              on MSVC. Reordered some #ifdefs for coherency.
 | 
			
		||||
//              (David Abrahams)
 | 
			
		||||
//  13 Feb 2001 Test new VC6 workarounds (David Abrahams)
 | 
			
		||||
//  11 Feb 2001 Final fixes for Borland (David Abrahams)
 | 
			
		||||
//  11 Feb 2001 Some fixes for Borland get it closer on that compiler
 | 
			
		||||
//              (David Abrahams)
 | 
			
		||||
//  07 Feb 2001 More comprehensive testing; factored out static tests for
 | 
			
		||||
//              better reuse (David Abrahams)
 | 
			
		||||
//  21 Jan 2001 Quick fix to my_iterator, which wasn't returning a
 | 
			
		||||
//              reference type from operator* (David Abrahams)
 | 
			
		||||
//  19 Jan 2001 Initial version with iterator operators (David Abrahams)
 | 
			
		||||
 | 
			
		||||
#include <boost/detail/iterator.hpp>
 | 
			
		||||
#include <boost/type_traits.hpp>
 | 
			
		||||
#include <boost/operators.hpp>
 | 
			
		||||
#include <boost/static_assert.hpp>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
// An iterator for which we can get traits.
 | 
			
		||||
struct my_iterator1
 | 
			
		||||
    : boost::forward_iterator_helper<my_iterator1, char, long, const char*, const char&>
 | 
			
		||||
{
 | 
			
		||||
    my_iterator1(const char* p) : m_p(p) {}
 | 
			
		||||
    
 | 
			
		||||
    bool operator==(const my_iterator1& rhs) const
 | 
			
		||||
        { return this->m_p == rhs.m_p; }
 | 
			
		||||
 | 
			
		||||
    my_iterator1& operator++() { ++this->m_p; return *this; }
 | 
			
		||||
    const char& operator*() { return *m_p; }
 | 
			
		||||
 private:
 | 
			
		||||
    const char* m_p;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Used to prove that we don't require std::iterator<> in the hierarchy under
 | 
			
		||||
// MSVC6, and that we can compute all the traits for a standard-conforming UDT
 | 
			
		||||
// iterator.
 | 
			
		||||
struct my_iterator2
 | 
			
		||||
    : boost::equality_comparable<my_iterator2
 | 
			
		||||
    , boost::incrementable<my_iterator2
 | 
			
		||||
    , boost::dereferenceable<my_iterator2,const char*> > >
 | 
			
		||||
{
 | 
			
		||||
    typedef char value_type;
 | 
			
		||||
    typedef long difference_type;
 | 
			
		||||
    typedef const char* pointer;
 | 
			
		||||
    typedef const char& reference;
 | 
			
		||||
    typedef std::forward_iterator_tag iterator_category;
 | 
			
		||||
    
 | 
			
		||||
    my_iterator2(const char* p) : m_p(p) {}
 | 
			
		||||
    
 | 
			
		||||
    bool operator==(const my_iterator2& rhs) const
 | 
			
		||||
        { return this->m_p == rhs.m_p; }
 | 
			
		||||
 | 
			
		||||
    my_iterator2& operator++() { ++this->m_p; return *this; }
 | 
			
		||||
    const char& operator*() { return *m_p; }
 | 
			
		||||
 private:
 | 
			
		||||
    const char* m_p;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Used to prove that we're not overly confused by the existence of
 | 
			
		||||
// std::iterator<> in the hierarchy under MSVC6 - we should find that
 | 
			
		||||
// boost::detail::iterator_traits<my_iterator3>::difference_type is int.
 | 
			
		||||
struct my_iterator3 : my_iterator1
 | 
			
		||||
{
 | 
			
		||||
    typedef int difference_type;
 | 
			
		||||
    my_iterator3(const char* p) : my_iterator1(p) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Iterator,
 | 
			
		||||
    class value_type, class difference_type, class pointer, class reference, class category>
 | 
			
		||||
struct non_portable_tests
 | 
			
		||||
{
 | 
			
		||||
    // Unfortunately, the VC6 standard library doesn't supply these :(
 | 
			
		||||
    BOOST_STATIC_ASSERT((
 | 
			
		||||
        boost::is_same<
 | 
			
		||||
        typename boost::detail::iterator_traits<Iterator>::pointer,
 | 
			
		||||
        pointer
 | 
			
		||||
        >::value));
 | 
			
		||||
    
 | 
			
		||||
    BOOST_STATIC_ASSERT((
 | 
			
		||||
        boost::is_same<
 | 
			
		||||
        typename boost::detail::iterator_traits<Iterator>::reference,
 | 
			
		||||
        reference
 | 
			
		||||
        >::value));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Iterator,
 | 
			
		||||
    class value_type, class difference_type, class pointer, class reference, class category>
 | 
			
		||||
struct portable_tests
 | 
			
		||||
{
 | 
			
		||||
    BOOST_STATIC_ASSERT((
 | 
			
		||||
        boost::is_same<
 | 
			
		||||
        typename boost::detail::iterator_traits<Iterator>::difference_type,
 | 
			
		||||
        difference_type
 | 
			
		||||
        >::value));
 | 
			
		||||
    
 | 
			
		||||
    BOOST_STATIC_ASSERT((
 | 
			
		||||
        boost::is_same<
 | 
			
		||||
        typename boost::detail::iterator_traits<Iterator>::iterator_category,
 | 
			
		||||
        category
 | 
			
		||||
        >::value));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Test iterator_traits
 | 
			
		||||
template <class Iterator,
 | 
			
		||||
    class value_type, class difference_type, class pointer, class reference, class category>
 | 
			
		||||
struct input_iterator_test
 | 
			
		||||
    : portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
 | 
			
		||||
{
 | 
			
		||||
    BOOST_STATIC_ASSERT((
 | 
			
		||||
        boost::is_same<
 | 
			
		||||
        typename boost::detail::iterator_traits<Iterator>::value_type,
 | 
			
		||||
        value_type
 | 
			
		||||
        >::value));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Iterator,
 | 
			
		||||
    class value_type, class difference_type, class pointer, class reference, class category>
 | 
			
		||||
struct non_pointer_test
 | 
			
		||||
    : input_iterator_test<Iterator,value_type,difference_type,pointer,reference,category>
 | 
			
		||||
      , non_portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
 | 
			
		||||
{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Iterator,
 | 
			
		||||
    class value_type, class difference_type, class pointer, class reference, class category>
 | 
			
		||||
struct maybe_pointer_test
 | 
			
		||||
    : portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
      , non_portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
 | 
			
		||||
#endif
 | 
			
		||||
{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
input_iterator_test<std::istream_iterator<int>, int, std::ptrdiff_t, int*, int&, std::input_iterator_tag>
 | 
			
		||||
        istream_iterator_test;
 | 
			
		||||
 | 
			
		||||
// 
 | 
			
		||||
#if defined(__BORLANDC__) && !defined(__SGI_STL_PORT)
 | 
			
		||||
typedef ::std::char_traits<char>::off_type distance;
 | 
			
		||||
non_pointer_test<std::ostream_iterator<int>,int,
 | 
			
		||||
    distance,int*,int&,std::output_iterator_tag> ostream_iterator_test;
 | 
			
		||||
#elif defined(BOOST_MSVC_STD_ITERATOR)
 | 
			
		||||
non_pointer_test<std::ostream_iterator<int>,
 | 
			
		||||
    int, void, void, void, std::output_iterator_tag>
 | 
			
		||||
        ostream_iterator_test;
 | 
			
		||||
#else
 | 
			
		||||
non_pointer_test<std::ostream_iterator<int>,
 | 
			
		||||
    void, void, void, void, std::output_iterator_tag>
 | 
			
		||||
        ostream_iterator_test;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __KCC
 | 
			
		||||
  typedef long std_list_diff_type;
 | 
			
		||||
#else
 | 
			
		||||
  typedef std::ptrdiff_t std_list_diff_type;
 | 
			
		||||
#endif
 | 
			
		||||
non_pointer_test<std::list<int>::iterator, int, std_list_diff_type, int*, int&, std::bidirectional_iterator_tag>
 | 
			
		||||
        list_iterator_test;
 | 
			
		||||
 | 
			
		||||
maybe_pointer_test<std::vector<int>::iterator, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag>
 | 
			
		||||
        vector_iterator_test;
 | 
			
		||||
 | 
			
		||||
maybe_pointer_test<int*, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag>
 | 
			
		||||
        int_pointer_test;
 | 
			
		||||
 | 
			
		||||
non_pointer_test<my_iterator1, char, long, const char*, const char&, std::forward_iterator_tag>
 | 
			
		||||
       my_iterator1_test;
 | 
			
		||||
                    
 | 
			
		||||
non_pointer_test<my_iterator2, char, long, const char*, const char&, std::forward_iterator_tag>
 | 
			
		||||
       my_iterator2_test;
 | 
			
		||||
                    
 | 
			
		||||
non_pointer_test<my_iterator3, char, int, const char*, const char&, std::forward_iterator_tag>
 | 
			
		||||
       my_iterator3_test;
 | 
			
		||||
                    
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    char chars[100];
 | 
			
		||||
    int ints[100];
 | 
			
		||||
    
 | 
			
		||||
    for (std::ptrdiff_t length = 3; length < 100; length += length / 3)
 | 
			
		||||
    {
 | 
			
		||||
        std::list<int> l(length);
 | 
			
		||||
        assert(boost::detail::distance(l.begin(), l.end()) == length);
 | 
			
		||||
        
 | 
			
		||||
        std::vector<int> v(length);
 | 
			
		||||
        assert(boost::detail::distance(v.begin(), v.end()) == length);
 | 
			
		||||
 | 
			
		||||
        assert(boost::detail::distance(&ints[0], ints + length) == length);
 | 
			
		||||
        assert(boost::detail::distance(my_iterator1(chars), my_iterator1(chars + length)) == length);
 | 
			
		||||
        assert(boost::detail::distance(my_iterator2(chars), my_iterator2(chars + length)) == length);
 | 
			
		||||
        assert(boost::detail::distance(my_iterator3(chars), my_iterator3(chars + length)) == length);
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -9,16 +9,29 @@
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  29 May 01 Factored implementation, added comparison tests, use Test Tools
 | 
			
		||||
//            library (Daryle Walker)
 | 
			
		||||
//  12 Dec 99 Initial version with iterator operators (Jeremy Siek)
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
using namespace std;
 | 
			
		||||
#define  BOOST_INCLUDE_MAIN
 | 
			
		||||
#include <boost/test/test_tools.hpp>  // for main
 | 
			
		||||
 | 
			
		||||
#include <boost/operators.hpp>
 | 
			
		||||
using namespace boost;
 | 
			
		||||
#include <boost/config.hpp>     // for BOOST_STATIC_CONSTANT
 | 
			
		||||
#include <boost/cstdlib.hpp>    // for boost::exit_success
 | 
			
		||||
#include <boost/operators.hpp>  // for boost::random_access_iterator_helper
 | 
			
		||||
 | 
			
		||||
#include <cstddef>    // for std::ptrdiff_t, std::size_t
 | 
			
		||||
#include <cstring>    // for std::strcmp
 | 
			
		||||
#include <iostream>   // for std::cout (std::endl, ends, and flush indirectly)
 | 
			
		||||
#include <string>     // for std::string
 | 
			
		||||
#include <strstream>  // for std::ostrstream
 | 
			
		||||
 | 
			
		||||
# ifdef BOOST_NO_STDC_NAMESPACE
 | 
			
		||||
    namespace std { using ::strcmp; }
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Iterator test class
 | 
			
		||||
template <class T, class R, class P>
 | 
			
		||||
struct test_iter
 | 
			
		||||
  : public boost::random_access_iterator_helper<
 | 
			
		||||
@@ -29,7 +42,7 @@ struct test_iter
 | 
			
		||||
  typedef std::ptrdiff_t Distance;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  test_iter(T* i) : _i(i) { }
 | 
			
		||||
  explicit test_iter(T* i =0) : _i(i) { }
 | 
			
		||||
  test_iter(const self& x) : _i(x._i) { }
 | 
			
		||||
  self& operator=(const self& x) { _i = x._i; return *this; }
 | 
			
		||||
  Reference operator*() const { return *_i; }
 | 
			
		||||
@@ -43,127 +56,280 @@ public:
 | 
			
		||||
    return x._i - y._i; 
 | 
			
		||||
  }
 | 
			
		||||
protected:
 | 
			
		||||
  T* _i;
 | 
			
		||||
  P _i;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main()
 | 
			
		||||
// Iterator operator testing classes
 | 
			
		||||
class test_opr_base
 | 
			
		||||
{
 | 
			
		||||
  string array[] = { "apple", "orange", "pear", "peach", "grape", "plum"  };
 | 
			
		||||
  {
 | 
			
		||||
    test_iter<string,string&,string*> i = array, 
 | 
			
		||||
      ie = array + sizeof(array)/sizeof(string);
 | 
			
		||||
protected:
 | 
			
		||||
    // Test data and types
 | 
			
		||||
    BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u );
 | 
			
		||||
    BOOST_STATIC_CONSTANT( std::size_t, scratch_length = 40u );
 | 
			
		||||
 | 
			
		||||
    // Tests for all of the operators added by random_access_iterator_helper
 | 
			
		||||
    typedef std::string  fruit_array_type[ fruit_length ];
 | 
			
		||||
    typedef char         scratch_array_type[ scratch_length ];
 | 
			
		||||
 | 
			
		||||
    // test i++
 | 
			
		||||
    while (i != ie)
 | 
			
		||||
      cout << *i++ << " ";
 | 
			
		||||
    cout << endl;
 | 
			
		||||
    i = array;
 | 
			
		||||
    static  fruit_array_type    fruit;
 | 
			
		||||
    static  scratch_array_type  scratch;
 | 
			
		||||
 | 
			
		||||
    // test i--
 | 
			
		||||
    while (ie != i) {
 | 
			
		||||
      ie--;
 | 
			
		||||
      cout << *ie << " ";
 | 
			
		||||
    }
 | 
			
		||||
    cout << endl;
 | 
			
		||||
    ie = array + sizeof(array)/sizeof(string);
 | 
			
		||||
};  // test_opr_base
 | 
			
		||||
 | 
			
		||||
    // test i->m
 | 
			
		||||
    while (i != ie) {
 | 
			
		||||
      cout << i->size() << " ";
 | 
			
		||||
      ++i;
 | 
			
		||||
    }
 | 
			
		||||
    cout << endl;
 | 
			
		||||
    i = array;
 | 
			
		||||
template <typename T, typename R = T&, typename P = T*>
 | 
			
		||||
class test_opr
 | 
			
		||||
    : public test_opr_base
 | 
			
		||||
{
 | 
			
		||||
    typedef test_opr<T, R, P>  self_type;
 | 
			
		||||
 | 
			
		||||
    // test i + n
 | 
			
		||||
    while (i < ie) {
 | 
			
		||||
      cout << *i << " ";
 | 
			
		||||
      i = i + 2;
 | 
			
		||||
    }
 | 
			
		||||
    cout << endl;
 | 
			
		||||
    i = array;
 | 
			
		||||
public:
 | 
			
		||||
    // Types
 | 
			
		||||
    typedef T  value_type;
 | 
			
		||||
    typedef R  reference;
 | 
			
		||||
    typedef P  pointer;
 | 
			
		||||
 | 
			
		||||
    // test n + i
 | 
			
		||||
    while (i < ie) {
 | 
			
		||||
      cout << *i << " ";
 | 
			
		||||
      i = ptrdiff_t(2) + i;
 | 
			
		||||
    }
 | 
			
		||||
    cout << endl;
 | 
			
		||||
    i = array;
 | 
			
		||||
    typedef test_iter<T, R, P>  iter_type;
 | 
			
		||||
 | 
			
		||||
    // test i - n
 | 
			
		||||
    while (ie > i) {
 | 
			
		||||
      ie = ie - 2;
 | 
			
		||||
      cout << *ie << " ";
 | 
			
		||||
    }
 | 
			
		||||
    cout << endl;
 | 
			
		||||
    ie = array + sizeof(array)/sizeof(string);
 | 
			
		||||
    // Test controller
 | 
			
		||||
    static  void  master_test( char const name[] );
 | 
			
		||||
 | 
			
		||||
    // test i[n]
 | 
			
		||||
    for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j)
 | 
			
		||||
      cout << i[j] << " ";
 | 
			
		||||
    cout << endl;
 | 
			
		||||
  }
 | 
			
		||||
  {
 | 
			
		||||
    test_iter<string, const string&, const string*> i = array, 
 | 
			
		||||
      ie = array + sizeof(array)/sizeof(string);
 | 
			
		||||
private:
 | 
			
		||||
    // Test data
 | 
			
		||||
    static  iter_type const  fruit_begin, fruit_end;
 | 
			
		||||
 | 
			
		||||
    // Tests for all of the operators added by random_access_iterator_helper
 | 
			
		||||
    // Test parts
 | 
			
		||||
    static  void  post_increment_test();
 | 
			
		||||
    static  void  post_decrement_test();
 | 
			
		||||
    static  void  indirect_referral_test();
 | 
			
		||||
    static  void  offset_addition_test();
 | 
			
		||||
    static  void  reverse_offset_addition_test();
 | 
			
		||||
    static  void  offset_subtraction_test();
 | 
			
		||||
    static  void  comparison_test();
 | 
			
		||||
    static  void  indexing_test();
 | 
			
		||||
 | 
			
		||||
    // test i++
 | 
			
		||||
    while (i != ie)
 | 
			
		||||
      cout << *i++ << " ";
 | 
			
		||||
    cout << endl;
 | 
			
		||||
    i = array;
 | 
			
		||||
};  // test_opr
 | 
			
		||||
 | 
			
		||||
    // test i--
 | 
			
		||||
    while (ie != i) {
 | 
			
		||||
      ie--;
 | 
			
		||||
      cout << *ie << " ";
 | 
			
		||||
    }
 | 
			
		||||
    cout << endl;
 | 
			
		||||
    ie = array + sizeof(array)/sizeof(string);
 | 
			
		||||
 | 
			
		||||
    // test i->m
 | 
			
		||||
    while (i != ie) {
 | 
			
		||||
      cout << i->size() << " ";
 | 
			
		||||
      ++i;
 | 
			
		||||
    }
 | 
			
		||||
    cout << endl;
 | 
			
		||||
    i = array;
 | 
			
		||||
// Class-static data definitions
 | 
			
		||||
test_opr_base::fruit_array_type
 | 
			
		||||
 test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" };
 | 
			
		||||
 | 
			
		||||
    // test i + n
 | 
			
		||||
    while (i < ie) {
 | 
			
		||||
      cout << *i << " ";
 | 
			
		||||
      i = i + 2;
 | 
			
		||||
    }
 | 
			
		||||
    cout << endl;
 | 
			
		||||
    i = array;
 | 
			
		||||
test_opr_base::scratch_array_type
 | 
			
		||||
 test_opr_base::scratch = "";
 | 
			
		||||
 | 
			
		||||
    // test n + i
 | 
			
		||||
    while (i < ie) {
 | 
			
		||||
      cout << *i << " ";
 | 
			
		||||
      i = ptrdiff_t(2) + i;
 | 
			
		||||
    }
 | 
			
		||||
    cout << endl;
 | 
			
		||||
    i = array;
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
typename test_opr<T, R, P>::iter_type const
 | 
			
		||||
 test_opr<T, R, P>::fruit_begin( fruit );
 | 
			
		||||
 | 
			
		||||
    // test i - n
 | 
			
		||||
    while (ie > i) {
 | 
			
		||||
      ie = ie - 2;
 | 
			
		||||
      cout << *ie << " ";
 | 
			
		||||
    }
 | 
			
		||||
    cout << endl;
 | 
			
		||||
    ie = array + sizeof(array)/sizeof(string);
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
typename test_opr<T, R, P>::iter_type const
 | 
			
		||||
 test_opr<T, R, P>::fruit_end( fruit + fruit_length );
 | 
			
		||||
 | 
			
		||||
    // test i[n]
 | 
			
		||||
    for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j)
 | 
			
		||||
      cout << i[j] << " ";
 | 
			
		||||
    cout << endl;
 | 
			
		||||
  }
 | 
			
		||||
  return 0;
 | 
			
		||||
 | 
			
		||||
// Main testing function
 | 
			
		||||
int
 | 
			
		||||
test_main( int , char * [] )
 | 
			
		||||
{
 | 
			
		||||
    using std::string;
 | 
			
		||||
 | 
			
		||||
    typedef test_opr<string, string &, string *>              test1_type;
 | 
			
		||||
    typedef test_opr<string, string const &, string const *>  test2_type;
 | 
			
		||||
 | 
			
		||||
    test1_type::master_test( "non-const string" );
 | 
			
		||||
    test2_type::master_test( "const string" );
 | 
			
		||||
 | 
			
		||||
    return boost::exit_success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tests for all of the operators added by random_access_iterator_helper
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::master_test
 | 
			
		||||
(
 | 
			
		||||
    char const  name[]
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "Doing test run for " << name << '.' << std::endl;
 | 
			
		||||
 | 
			
		||||
    post_increment_test();
 | 
			
		||||
    post_decrement_test();
 | 
			
		||||
    indirect_referral_test();
 | 
			
		||||
    offset_addition_test();
 | 
			
		||||
    reverse_offset_addition_test();
 | 
			
		||||
    offset_subtraction_test();
 | 
			
		||||
    comparison_test();
 | 
			
		||||
    indexing_test();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test post-increment
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::post_increment_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing post-increment test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ostrstream  oss( scratch, scratch_length );
 | 
			
		||||
    for ( iter_type i = fruit_begin ; i != fruit_end ; )
 | 
			
		||||
    {
 | 
			
		||||
        oss << *i++ << ' ';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ")
 | 
			
		||||
     == 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test post-decrement
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::post_decrement_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing post-decrement test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ostrstream  oss( scratch, scratch_length );
 | 
			
		||||
    for ( iter_type i = fruit_end ; i != fruit_begin ; )
 | 
			
		||||
    {
 | 
			
		||||
        i--;
 | 
			
		||||
        oss << *i << ' ';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "plum grape peach pear orange apple ")
 | 
			
		||||
     == 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test indirect structure referral
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::indirect_referral_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing indirect reference test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ostrstream  oss( scratch, scratch_length );
 | 
			
		||||
    for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
 | 
			
		||||
    {
 | 
			
		||||
        oss << i->size() << ' ';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "5 6 4 5 5 4 ") == 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test offset addition
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::offset_addition_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing offset addition test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ptrdiff_t const  two = 2;
 | 
			
		||||
    std::ostrstream       oss( scratch, scratch_length );
 | 
			
		||||
    for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two )
 | 
			
		||||
    {
 | 
			
		||||
        oss << *i << ' ';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test offset addition, in reverse order
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::reverse_offset_addition_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing reverse offset addition test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ptrdiff_t const  two = 2;
 | 
			
		||||
    std::ostrstream       oss( scratch, scratch_length );
 | 
			
		||||
    for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i )
 | 
			
		||||
    {
 | 
			
		||||
        oss << *i << ' ';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test offset subtraction
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::offset_subtraction_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing offset subtraction test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ptrdiff_t const  two = 2;
 | 
			
		||||
    std::ostrstream       oss( scratch, scratch_length );
 | 
			
		||||
    for ( iter_type i = fruit_end ; fruit_begin < i ; )
 | 
			
		||||
    {
 | 
			
		||||
        i = i - two;
 | 
			
		||||
        if ( (fruit_begin < i) || (fruit_begin == i) )
 | 
			
		||||
        {
 | 
			
		||||
            oss << *i << ' ';
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "grape pear apple ") == 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test comparisons
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::comparison_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    using std::cout;
 | 
			
		||||
    using std::ptrdiff_t;
 | 
			
		||||
 | 
			
		||||
    cout << "\tDoing comparison tests.\n\t\tPass:";
 | 
			
		||||
 | 
			
		||||
    for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
 | 
			
		||||
    {
 | 
			
		||||
        ptrdiff_t const  i_offset = i - fruit_begin;
 | 
			
		||||
 | 
			
		||||
        cout << ' ' << *i << std::flush;
 | 
			
		||||
        for ( iter_type j = fruit_begin ; j != fruit_end ; ++j )
 | 
			
		||||
        {
 | 
			
		||||
            ptrdiff_t const  j_offset = j - fruit_begin;
 | 
			
		||||
 | 
			
		||||
            BOOST_TEST( (i != j) == (i_offset != j_offset) );
 | 
			
		||||
            BOOST_TEST( (i > j) == (i_offset > j_offset) );
 | 
			
		||||
            BOOST_TEST( (i <= j) == (i_offset <= j_offset) );
 | 
			
		||||
            BOOST_TEST( (i >= j) == (i_offset >= j_offset) );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    cout << std::endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test indexing
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::indexing_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing indexing test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ostrstream  oss( scratch, scratch_length );
 | 
			
		||||
    for ( std::size_t k = 0u ; k < fruit_length ; ++k )
 | 
			
		||||
    {
 | 
			
		||||
        oss << fruit_begin[ k ] << ' ';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ")
 | 
			
		||||
     == 0 );
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										387
									
								
								numeric_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										387
									
								
								numeric_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,387 @@
 | 
			
		||||
//  (C) Copyright David Abrahams 2001. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  1  Apr 2001 Fixes for ICL; use BOOST_STATIC_CONSTANT
 | 
			
		||||
//  11 Feb 2001 Fixes for Borland (David Abrahams)
 | 
			
		||||
//  23 Jan 2001 Added test for wchar_t (David Abrahams)
 | 
			
		||||
//  23 Jan 2001 Now statically selecting a test for signed numbers to avoid
 | 
			
		||||
//              warnings with fancy compilers. Added commentary and
 | 
			
		||||
//              additional dumping of traits data for tested types (David
 | 
			
		||||
//              Abrahams).
 | 
			
		||||
//  21 Jan 2001 Initial version (David Abrahams)
 | 
			
		||||
 | 
			
		||||
#include <boost/detail/numeric_traits.hpp>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <boost/type_traits.hpp>
 | 
			
		||||
#include <boost/static_assert.hpp>
 | 
			
		||||
#include <boost/cstdint.hpp>
 | 
			
		||||
#include <boost/utility.hpp>
 | 
			
		||||
#include <boost/lexical_cast.hpp>
 | 
			
		||||
#include <climits>
 | 
			
		||||
#include <typeinfo>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <string>
 | 
			
		||||
#ifndef BOOST_NO_LIMITS
 | 
			
		||||
# include <limits>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// =================================================================================
 | 
			
		||||
// template class complement_traits<Number> --
 | 
			
		||||
//
 | 
			
		||||
//    statically computes the max and min for 1s and 2s-complement binary
 | 
			
		||||
//    numbers. This helps on platforms without <limits> support. It also shows
 | 
			
		||||
//    an example of a recursive template that works with MSVC!
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
template <unsigned size> struct complement; // forward
 | 
			
		||||
 | 
			
		||||
// The template complement, below, does all the real work, using "poor man's
 | 
			
		||||
// partial specialization". We need complement_traits_aux<> so that MSVC doesn't
 | 
			
		||||
// complain about undefined min/max as we're trying to recursively define them. 
 | 
			
		||||
template <class Number, unsigned size>
 | 
			
		||||
struct complement_traits_aux
 | 
			
		||||
{
 | 
			
		||||
    BOOST_STATIC_CONSTANT(Number, max = complement<size>::template traits<Number>::max);
 | 
			
		||||
    BOOST_STATIC_CONSTANT(Number, min = complement<size>::template traits<Number>::min);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <unsigned size>
 | 
			
		||||
struct complement
 | 
			
		||||
{
 | 
			
		||||
    template <class Number>
 | 
			
		||||
    struct traits
 | 
			
		||||
    {
 | 
			
		||||
     private:
 | 
			
		||||
        // indirection through complement_traits_aux neccessary to keep MSVC happy
 | 
			
		||||
        typedef complement_traits_aux<Number, size - 1> prev;
 | 
			
		||||
     public:
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, max =
 | 
			
		||||
                            Number(Number(prev::max) << CHAR_BIT)
 | 
			
		||||
                            + Number(UCHAR_MAX));
 | 
			
		||||
        
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, min = Number(Number(prev::min) << CHAR_BIT));
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Template class complement_base<> -- defines values for min and max for
 | 
			
		||||
// complement<1>, at the deepest level of recursion. Uses "poor man's partial
 | 
			
		||||
// specialization" again.
 | 
			
		||||
template <bool is_signed> struct complement_base;
 | 
			
		||||
 | 
			
		||||
template <> struct complement_base<false>
 | 
			
		||||
{
 | 
			
		||||
    template <class Number>
 | 
			
		||||
    struct values
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, min = 0);
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, max = UCHAR_MAX);
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <> struct complement_base<true>
 | 
			
		||||
{
 | 
			
		||||
    template <class Number>
 | 
			
		||||
    struct values
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, min = SCHAR_MIN);
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, max = SCHAR_MAX);
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Base specialization of complement, puts an end to the recursion.
 | 
			
		||||
template <>
 | 
			
		||||
struct complement<1>
 | 
			
		||||
{
 | 
			
		||||
    template <class Number>
 | 
			
		||||
    struct traits
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_STATIC_CONSTANT(bool, is_signed = boost::detail::is_signed<Number>::value);
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, min =
 | 
			
		||||
                            complement_base<is_signed>::template values<Number>::min);
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, max =
 | 
			
		||||
                            complement_base<is_signed>::template values<Number>::max);
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Now here's the "pretty" template you're intended to actually use.
 | 
			
		||||
//   complement_traits<Number>::min, complement_traits<Number>::max are the
 | 
			
		||||
//   minimum and maximum values of Number if Number is a built-in integer type.
 | 
			
		||||
template <class Number>
 | 
			
		||||
struct complement_traits
 | 
			
		||||
{
 | 
			
		||||
    BOOST_STATIC_CONSTANT(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max));
 | 
			
		||||
    BOOST_STATIC_CONSTANT(Number, min = (complement_traits_aux<Number, sizeof(Number)>::min));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// =================================================================================
 | 
			
		||||
 | 
			
		||||
// Support for streaming various numeric types in exactly the format I want. I
 | 
			
		||||
// needed this in addition to all the assertions so that I could see exactly
 | 
			
		||||
// what was going on.
 | 
			
		||||
//
 | 
			
		||||
// Numbers go through a 2-stage conversion process (by default, though, no real
 | 
			
		||||
// conversion).
 | 
			
		||||
//
 | 
			
		||||
template <class T> struct stream_as {
 | 
			
		||||
    typedef T t1;
 | 
			
		||||
    typedef T t2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// char types first get converted to unsigned char, then to unsigned.
 | 
			
		||||
template <> struct stream_as<char> {
 | 
			
		||||
    typedef unsigned char t1;
 | 
			
		||||
    typedef unsigned t2;
 | 
			
		||||
};
 | 
			
		||||
template <> struct stream_as<unsigned char> {
 | 
			
		||||
    typedef unsigned char t1; typedef unsigned t2;
 | 
			
		||||
};
 | 
			
		||||
template <> struct stream_as<signed char>  {
 | 
			
		||||
    typedef unsigned char t1; typedef unsigned t2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in
 | 
			
		||||
 | 
			
		||||
// With this library implementation, __int64 and __uint64 get streamed as strings
 | 
			
		||||
template <> struct stream_as<boost::uintmax_t> {
 | 
			
		||||
    typedef std::string t1;
 | 
			
		||||
    typedef std::string t2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <> struct stream_as<boost::intmax_t>  {
 | 
			
		||||
    typedef std::string t1;
 | 
			
		||||
    typedef std::string t2;
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Standard promotion process for streaming
 | 
			
		||||
template <class T> struct promote
 | 
			
		||||
{
 | 
			
		||||
    static typename stream_as<T>::t1 from(T x) {
 | 
			
		||||
        typedef typename stream_as<T>::t1 t1;
 | 
			
		||||
        return t1(x);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in
 | 
			
		||||
 | 
			
		||||
// On this platform, stream them as long/unsigned long if they fit.
 | 
			
		||||
// Otherwise, write a string.
 | 
			
		||||
template <> struct promote<boost::uintmax_t> {
 | 
			
		||||
    std::string static from(const boost::uintmax_t x) {
 | 
			
		||||
        if (x > ULONG_MAX)
 | 
			
		||||
            return std::string("large unsigned value");
 | 
			
		||||
        else
 | 
			
		||||
            return boost::lexical_cast<std::string>((unsigned long)x);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
template <> struct promote<boost::intmax_t> {
 | 
			
		||||
    std::string static from(const boost::intmax_t x) {
 | 
			
		||||
        if (x > boost::intmax_t(ULONG_MAX))
 | 
			
		||||
            return std::string("large positive signed value");
 | 
			
		||||
        else if (x >= 0)
 | 
			
		||||
            return boost::lexical_cast<std::string>((unsigned long)x);
 | 
			
		||||
        
 | 
			
		||||
        if (x < boost::intmax_t(LONG_MIN))
 | 
			
		||||
            return std::string("large negative signed value");
 | 
			
		||||
        else
 | 
			
		||||
            return boost::lexical_cast<std::string>((long)x);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// This is the function which converts types to the form I want to stream them in.
 | 
			
		||||
template <class T>
 | 
			
		||||
typename stream_as<T>::t2 stream_number(T x)
 | 
			
		||||
{
 | 
			
		||||
    return promote<T>::from(x);
 | 
			
		||||
}
 | 
			
		||||
// =================================================================================
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Tests for built-in signed and unsigned types
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// Tag types for selecting tests
 | 
			
		||||
struct unsigned_tag {};
 | 
			
		||||
struct signed_tag {};
 | 
			
		||||
 | 
			
		||||
// Tests for unsigned numbers. The extra default Number parameter works around
 | 
			
		||||
// an MSVC bug.
 | 
			
		||||
template <class Number>
 | 
			
		||||
void test_aux(unsigned_tag, Number* = 0)
 | 
			
		||||
{
 | 
			
		||||
    typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
 | 
			
		||||
    BOOST_STATIC_ASSERT(!boost::detail::is_signed<Number>::value);
 | 
			
		||||
    BOOST_STATIC_ASSERT(
 | 
			
		||||
        (sizeof(Number) < sizeof(boost::intmax_t))
 | 
			
		||||
        | (boost::is_same<difference_type, boost::intmax_t>::value));
 | 
			
		||||
 | 
			
		||||
    // Force casting to Number here to work around the fact that it's an enum on MSVC
 | 
			
		||||
    BOOST_STATIC_ASSERT(Number(complement_traits<Number>::max) > Number(0));
 | 
			
		||||
    BOOST_STATIC_ASSERT(Number(complement_traits<Number>::min) == Number(0));
 | 
			
		||||
    
 | 
			
		||||
    const Number max = complement_traits<Number>::max;
 | 
			
		||||
    const Number min = complement_traits<Number>::min;
 | 
			
		||||
    
 | 
			
		||||
    const Number test_max = (sizeof(Number) < sizeof(boost::intmax_t))
 | 
			
		||||
        ? max
 | 
			
		||||
        : max / 2 - 1;
 | 
			
		||||
 | 
			
		||||
    std::cout << std::hex << "(unsigned) min = " << stream_number(min) << ", max = "
 | 
			
		||||
              << stream_number(max) << "..." << std::flush;
 | 
			
		||||
    std::cout << "difference_type = " << typeid(difference_type).name() << "..."
 | 
			
		||||
              << std::flush;
 | 
			
		||||
    
 | 
			
		||||
    difference_type d1 = boost::detail::numeric_distance(Number(0), test_max);
 | 
			
		||||
    difference_type d2 = boost::detail::numeric_distance(test_max, Number(0));
 | 
			
		||||
    
 | 
			
		||||
    std::cout << "0->" << stream_number(test_max) << "==" << std::dec << stream_number(d1) << "; "
 | 
			
		||||
              << std::hex << stream_number(test_max) << "->0==" << std::dec << stream_number(d2) << "..." << std::flush;
 | 
			
		||||
 | 
			
		||||
    assert(d1 == difference_type(test_max));
 | 
			
		||||
    assert(d2 == -difference_type(test_max));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tests for signed numbers. The extra default Number parameter works around an
 | 
			
		||||
// MSVC bug.
 | 
			
		||||
struct out_of_range_tag {};
 | 
			
		||||
struct in_range_tag {};
 | 
			
		||||
 | 
			
		||||
// This test morsel gets executed for numbers whose difference will always be
 | 
			
		||||
// representable in intmax_t
 | 
			
		||||
template <class Number>
 | 
			
		||||
void signed_test(in_range_tag, Number* = 0)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
 | 
			
		||||
    typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
 | 
			
		||||
    const Number max = complement_traits<Number>::max;
 | 
			
		||||
    const Number min = complement_traits<Number>::min;
 | 
			
		||||
    
 | 
			
		||||
    difference_type d1 = boost::detail::numeric_distance(min, max);
 | 
			
		||||
    difference_type d2 = boost::detail::numeric_distance(max, min);
 | 
			
		||||
 | 
			
		||||
    std::cout << stream_number(min) << "->" << stream_number(max) << "==";
 | 
			
		||||
    std::cout << std::dec << stream_number(d1) << "; ";
 | 
			
		||||
    std::cout << std::hex << stream_number(max) << "->" << stream_number(min)
 | 
			
		||||
              << "==" << std::dec << stream_number(d2) << "..." << std::flush;
 | 
			
		||||
    assert(d1 == difference_type(max) - difference_type(min));
 | 
			
		||||
    assert(d2 == difference_type(min) - difference_type(max));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This test morsel gets executed for numbers whose difference may exceed the
 | 
			
		||||
// capacity of intmax_t.
 | 
			
		||||
template <class Number>
 | 
			
		||||
void signed_test(out_of_range_tag, Number* = 0)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
 | 
			
		||||
    typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
 | 
			
		||||
    const Number max = complement_traits<Number>::max;
 | 
			
		||||
    const Number min = complement_traits<Number>::min;
 | 
			
		||||
 | 
			
		||||
    difference_type min_distance = complement_traits<difference_type>::min;
 | 
			
		||||
    difference_type max_distance = complement_traits<difference_type>::max;
 | 
			
		||||
 | 
			
		||||
    const Number n1 = Number(min + max_distance);
 | 
			
		||||
    const Number n2 = Number(max + min_distance);
 | 
			
		||||
    difference_type d1 = boost::detail::numeric_distance(min, n1);
 | 
			
		||||
    difference_type d2 = boost::detail::numeric_distance(max, n2);
 | 
			
		||||
 | 
			
		||||
    std::cout << stream_number(min) << "->" << stream_number(n1) << "==";
 | 
			
		||||
    std::cout << std::dec << stream_number(d1) << "; ";
 | 
			
		||||
    std::cout << std::hex << stream_number(max) << "->" << stream_number(n2)
 | 
			
		||||
              << "==" << std::dec << stream_number(d2) << "..." << std::flush;
 | 
			
		||||
    assert(d1 == max_distance);
 | 
			
		||||
    assert(d2 == min_distance);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Number>
 | 
			
		||||
void test_aux(signed_tag, Number* = 0)
 | 
			
		||||
{
 | 
			
		||||
    typedef typename boost::detail::numeric_traits<Number>::difference_type difference_type;
 | 
			
		||||
    BOOST_STATIC_ASSERT(boost::detail::is_signed<Number>::value);
 | 
			
		||||
    BOOST_STATIC_ASSERT(
 | 
			
		||||
        (sizeof(Number) < sizeof(boost::intmax_t))
 | 
			
		||||
        | (boost::is_same<difference_type, Number>::value));
 | 
			
		||||
 | 
			
		||||
    // Force casting to Number here to work around the fact that it's an enum on MSVC
 | 
			
		||||
    BOOST_STATIC_ASSERT(Number(complement_traits<Number>::max) > Number(0));
 | 
			
		||||
    BOOST_STATIC_ASSERT(Number(complement_traits<Number>::min) < Number(0));
 | 
			
		||||
    
 | 
			
		||||
    const Number max = complement_traits<Number>::max;
 | 
			
		||||
    const Number min = complement_traits<Number>::min;
 | 
			
		||||
    
 | 
			
		||||
    std::cout << std::hex << "min = " << stream_number(min) << ", max = "
 | 
			
		||||
              << stream_number(max) << "..." << std::flush;
 | 
			
		||||
    std::cout << "difference_type = " << typeid(difference_type).name() << "..."
 | 
			
		||||
              << std::flush;
 | 
			
		||||
 | 
			
		||||
    typedef typename boost::detail::if_true<
 | 
			
		||||
                          (sizeof(Number) < sizeof(boost::intmax_t))>
 | 
			
		||||
                        ::template then<
 | 
			
		||||
                          in_range_tag,
 | 
			
		||||
                          out_of_range_tag
 | 
			
		||||
                        >::type
 | 
			
		||||
        range_tag;
 | 
			
		||||
    signed_test<Number>(range_tag());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Test for all numbers. The extra default Number parameter works around an MSVC
 | 
			
		||||
// bug.
 | 
			
		||||
template <class Number>
 | 
			
		||||
void test(Number* = 0)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "testing " << typeid(Number).name() << ":\n"
 | 
			
		||||
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
 | 
			
		||||
              << "is_signed: " << (std::numeric_limits<Number>::is_signed ? "true\n" : "false\n")
 | 
			
		||||
              << "is_bounded: " << (std::numeric_limits<Number>::is_bounded ? "true\n" : "false\n")
 | 
			
		||||
              << "digits: " << std::numeric_limits<Number>::digits << "\n"
 | 
			
		||||
#endif
 | 
			
		||||
              << "..." << std::flush;
 | 
			
		||||
 | 
			
		||||
    // factoring out difference_type for the assert below confused Borland :(
 | 
			
		||||
    typedef boost::detail::is_signed<
 | 
			
		||||
#ifndef BOOST_MSVC
 | 
			
		||||
        typename
 | 
			
		||||
#endif
 | 
			
		||||
        boost::detail::numeric_traits<Number>::difference_type
 | 
			
		||||
        > is_signed;
 | 
			
		||||
    BOOST_STATIC_ASSERT(is_signed::value);
 | 
			
		||||
 | 
			
		||||
    typedef typename boost::detail::if_true<
 | 
			
		||||
        boost::detail::is_signed<Number>::value
 | 
			
		||||
        >::template then<signed_tag, unsigned_tag>::type signedness;
 | 
			
		||||
    
 | 
			
		||||
    test_aux<Number>(signedness());
 | 
			
		||||
    std::cout << "passed" << std::endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    test<char>();
 | 
			
		||||
    test<unsigned char>();
 | 
			
		||||
    test<signed char>();
 | 
			
		||||
    test<wchar_t>();
 | 
			
		||||
    test<short>();
 | 
			
		||||
    test<unsigned short>();
 | 
			
		||||
    test<int>();
 | 
			
		||||
    test<unsigned int>();
 | 
			
		||||
    test<long>();
 | 
			
		||||
    test<unsigned long>();
 | 
			
		||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
 | 
			
		||||
    test<long long>();
 | 
			
		||||
    test<unsigned long long>();
 | 
			
		||||
#elif defined(BOOST_MSVC)
 | 
			
		||||
    // The problem of not having compile-time static class constants other than
 | 
			
		||||
    // enums prevents this from working, since values get truncated.
 | 
			
		||||
    // test<boost::uintmax_t>();
 | 
			
		||||
    // test<boost::intmax_t>();
 | 
			
		||||
#endif
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1563
									
								
								operators.htm
									
									
									
									
									
								
							
							
						
						
									
										1563
									
								
								operators.htm
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -8,18 +8,26 @@
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  20 May 01 Output progress messages.  Added tests for new operator
 | 
			
		||||
//            templates.  Updated random number generator.  Changed tests to
 | 
			
		||||
//            use Boost Test Tools library.  (Daryle Walker)
 | 
			
		||||
//  04 Jun 00 Added regression test for a bug I found (David Abrahams)
 | 
			
		||||
//  17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy)
 | 
			
		||||
//  ?? ??? 00 Major update to randomly test all one- and two- argument forms by
 | 
			
		||||
//            wrapping integral types and comparing the results of operations to
 | 
			
		||||
//            the results for the raw types (David Abrahams)
 | 
			
		||||
//            wrapping integral types and comparing the results of operations
 | 
			
		||||
//            to the results for the raw types (David Abrahams)
 | 
			
		||||
//  12 Dec 99 Minor update, output confirmation message.
 | 
			
		||||
//  15 Nov 99 Initial version
 | 
			
		||||
 | 
			
		||||
#include <boost/operators.hpp>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <boost/min_rand.hpp>
 | 
			
		||||
#define BOOST_INCLUDE_MAIN
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>                      // for BOOST_MSVC
 | 
			
		||||
#include <boost/cstdlib.hpp>                     // for boost::exit_success
 | 
			
		||||
#include <boost/operators.hpp>                   // for the tested items
 | 
			
		||||
#include <boost/random/linear_congruential.hpp>  // for boost::minstd_rand
 | 
			
		||||
#include <boost/test/test_tools.hpp>             // for main
 | 
			
		||||
 | 
			
		||||
#include <iostream>  // for std::cout (std::endl indirectly)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace
 | 
			
		||||
@@ -28,14 +36,18 @@ namespace
 | 
			
		||||
    int true_value(int x) { return x; }
 | 
			
		||||
    long true_value(long x) { return x; }
 | 
			
		||||
    signed char true_value(signed char x) { return x; }
 | 
			
		||||
    short true_value(short x) { return x; }
 | 
			
		||||
    unsigned int true_value(unsigned int x) { return x; }
 | 
			
		||||
    unsigned long true_value(unsigned long x) { return x; }
 | 
			
		||||
    unsigned char true_value(unsigned char x) { return x; }
 | 
			
		||||
    unsigned short true_value(unsigned short x) { return x; }
 | 
			
		||||
 | 
			
		||||
    // The use of operators<> here tended to obscure interactions with certain
 | 
			
		||||
    // compiler bugs
 | 
			
		||||
    // The use of operators<> here tended to obscure
 | 
			
		||||
    // interactions with certain compiler bugs
 | 
			
		||||
    template <class T>
 | 
			
		||||
    class Wrapped1 : boost::operators<Wrapped1<T> >
 | 
			
		||||
    class Wrapped1
 | 
			
		||||
        : boost::operators<Wrapped1<T> >
 | 
			
		||||
        , boost::shiftable<Wrapped1<T> >
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        explicit Wrapped1( T v = T() ) : _value(v) {}
 | 
			
		||||
@@ -60,6 +72,10 @@ namespace
 | 
			
		||||
          { _value &= x._value; return *this; }
 | 
			
		||||
        Wrapped1& operator^=(const Wrapped1& x)
 | 
			
		||||
          { _value ^= x._value; return *this; }
 | 
			
		||||
        Wrapped1& operator<<=(const Wrapped1& x)
 | 
			
		||||
          { _value <<= x._value; return *this; }
 | 
			
		||||
        Wrapped1& operator>>=(const Wrapped1& x)
 | 
			
		||||
          { _value >>= x._value; return *this; }
 | 
			
		||||
        Wrapped1& operator++()               { ++_value; return *this; }
 | 
			
		||||
        Wrapped1& operator--()               { --_value; return *this; }
 | 
			
		||||
        
 | 
			
		||||
@@ -70,9 +86,11 @@ namespace
 | 
			
		||||
    T true_value(Wrapped1<T> x) { return x.value(); }    
 | 
			
		||||
 | 
			
		||||
    template <class T, class U>
 | 
			
		||||
    class Wrapped2 :
 | 
			
		||||
        boost::operators<Wrapped2<T, U> >,
 | 
			
		||||
        boost::operators2<Wrapped2<T, U>, U>
 | 
			
		||||
    class Wrapped2
 | 
			
		||||
        : boost::operators<Wrapped2<T, U> >
 | 
			
		||||
        , boost::operators2<Wrapped2<T, U>, U>
 | 
			
		||||
        , boost::shiftable1<Wrapped2<T, U>
 | 
			
		||||
        , boost::shiftable2<Wrapped2<T, U>, U > >
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        explicit Wrapped2( T v = T() ) : _value(v) {}
 | 
			
		||||
@@ -97,6 +115,10 @@ namespace
 | 
			
		||||
          { _value &= x._value; return *this; }
 | 
			
		||||
        Wrapped2& operator^=(const Wrapped2& x)
 | 
			
		||||
          { _value ^= x._value; return *this; }
 | 
			
		||||
        Wrapped2& operator<<=(const Wrapped2& x)
 | 
			
		||||
          { _value <<= x._value; return *this; }
 | 
			
		||||
        Wrapped2& operator>>=(const Wrapped2& x)
 | 
			
		||||
          { _value >>= x._value; return *this; }
 | 
			
		||||
        Wrapped2& operator++()                { ++_value; return *this; }
 | 
			
		||||
        Wrapped2& operator--()                { --_value; return *this; }
 | 
			
		||||
         
 | 
			
		||||
@@ -111,6 +133,8 @@ namespace
 | 
			
		||||
        Wrapped2& operator|=(U u) { _value |= u; return *this; }
 | 
			
		||||
        Wrapped2& operator&=(U u) { _value &= u; return *this; }
 | 
			
		||||
        Wrapped2& operator^=(U u) { _value ^= u; return *this; }
 | 
			
		||||
        Wrapped2& operator<<=(U u) { _value <<= u; return *this; }
 | 
			
		||||
        Wrapped2& operator>>=(U u) { _value >>= u; return *this; }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        T _value;
 | 
			
		||||
@@ -118,203 +142,268 @@ namespace
 | 
			
		||||
    template <class T, class U>
 | 
			
		||||
    T true_value(Wrapped2<T,U> x) { return x.value(); }
 | 
			
		||||
    
 | 
			
		||||
    template <class T>
 | 
			
		||||
    class Wrapped3
 | 
			
		||||
        : boost::equivalent<Wrapped3<T> >
 | 
			
		||||
        , boost::partially_ordered<Wrapped3<T> >
 | 
			
		||||
        , boost::equality_comparable<Wrapped3<T> >
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        explicit Wrapped3( T v = T() ) : _value(v) {}
 | 
			
		||||
        T value() const { return _value; }
 | 
			
		||||
 | 
			
		||||
        bool operator<(const Wrapped3& x) const { return _value < x._value; }
 | 
			
		||||
        
 | 
			
		||||
    private:
 | 
			
		||||
        T _value;
 | 
			
		||||
    };
 | 
			
		||||
    template <class T>
 | 
			
		||||
    T true_value(Wrapped3<T> x) { return x.value(); }    
 | 
			
		||||
 | 
			
		||||
    template <class T, class U>
 | 
			
		||||
    class Wrapped4
 | 
			
		||||
        : boost::equality_comparable1<Wrapped4<T, U>
 | 
			
		||||
        , boost::equivalent1<Wrapped4<T, U>
 | 
			
		||||
        , boost::partially_ordered1<Wrapped4<T, U> > > >
 | 
			
		||||
        , boost::partially_ordered2<Wrapped4<T, U>, U
 | 
			
		||||
        , boost::equivalent2<Wrapped4<T, U>, U
 | 
			
		||||
        , boost::equality_comparable2<Wrapped4<T, U>, U> > >
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        explicit Wrapped4( T v = T() ) : _value(v) {}
 | 
			
		||||
        T value() const { return _value; }
 | 
			
		||||
 | 
			
		||||
        bool operator<(const Wrapped4& x) const { return _value < x._value; }
 | 
			
		||||
         
 | 
			
		||||
        bool operator<(U u) const { return _value < u; }
 | 
			
		||||
        bool operator>(U u) const { return _value > u; }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
        T _value;
 | 
			
		||||
    };
 | 
			
		||||
    template <class T, class U>
 | 
			
		||||
    T true_value(Wrapped4<T,U> x) { return x.value(); }
 | 
			
		||||
    
 | 
			
		||||
    //  MyInt uses only the single template-argument form of all_operators<>
 | 
			
		||||
    typedef Wrapped1<int> MyInt;
 | 
			
		||||
 | 
			
		||||
    typedef Wrapped2<long, long> MyLong;
 | 
			
		||||
 | 
			
		||||
    typedef Wrapped3<signed char> MyChar;
 | 
			
		||||
 | 
			
		||||
    typedef Wrapped4<short, short> MyShort;
 | 
			
		||||
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        assert(true_value(y1) == true_value(y2));
 | 
			
		||||
        assert(true_value(x1) == true_value(x2));
 | 
			
		||||
        BOOST_TEST( true_value(y1) == true_value(y2) );
 | 
			
		||||
        BOOST_TEST( true_value(x1) == true_value(x2) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        assert((x1 < y1) == (x2 < y2));
 | 
			
		||||
        assert((x1 <= y1) == (x2 <= y2));
 | 
			
		||||
        assert((x1 >= y1) == (x2 >= y2));
 | 
			
		||||
        assert((x1 > y1) == (x2 > y2));
 | 
			
		||||
        BOOST_TEST( (x1 < y1) == (x2 < y2) );
 | 
			
		||||
        BOOST_TEST( (x1 <= y1) == (x2 <= y2) );
 | 
			
		||||
        BOOST_TEST( (x1 >= y1) == (x2 >= y2) );
 | 
			
		||||
        BOOST_TEST( (x1 > y1) == (x2 > y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check(x1, y1, x2, y2);
 | 
			
		||||
        test_less_than_comparable_aux(x1, y1, x2, y2);
 | 
			
		||||
        test_less_than_comparable_aux(y1, x1, y2, x2);
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        test_less_than_comparable_aux( x1, y1, x2, y2 );
 | 
			
		||||
        test_less_than_comparable_aux( y1, x1, y2, x2 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        assert((x1 == y1) == (x2 == y2));
 | 
			
		||||
        assert((x1 != y1) == (x2 != y2));
 | 
			
		||||
        BOOST_TEST( (x1 == y1) == (x2 == y2) );
 | 
			
		||||
        BOOST_TEST( (x1 != y1) == (x2 != y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check(x1, y1, x2, y2);
 | 
			
		||||
        test_equality_comparable_aux(x1, y1, x2, y2);
 | 
			
		||||
        test_equality_comparable_aux(y1, x1, y2, x2);
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        test_equality_comparable_aux( x1, y1, x2, y2 );
 | 
			
		||||
        test_equality_comparable_aux( y1, x1, y2, x2 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        assert((x1 * y1).value() == (x2 * y2));
 | 
			
		||||
        BOOST_TEST( (x1 * y1).value() == (x2 * y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check(x1, y1, x2, y2);
 | 
			
		||||
        test_multipliable_aux(x1, y1, x2, y2);
 | 
			
		||||
        test_multipliable_aux(y1, x1, y2, x2);
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        test_multipliable_aux( x1, y1, x2, y2 );
 | 
			
		||||
        test_multipliable_aux( y1, x1, y2, x2 );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        assert((x1 + y1).value() == (x2 + y2));
 | 
			
		||||
        BOOST_TEST( (x1 + y1).value() == (x2 + y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check(x1, y1, x2, y2);
 | 
			
		||||
        test_addable_aux(x1, y1, x2, y2);
 | 
			
		||||
        test_addable_aux(y1, x1, y2, x2);
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        test_addable_aux( x1, y1, x2, y2 );
 | 
			
		||||
        test_addable_aux( y1, x1, y2, x2 );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check(x1, y1, x2, y2);
 | 
			
		||||
        assert((x1 - y1).value() == x2 - y2);
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        BOOST_TEST( (x1 - y1).value() == (x2 - y2) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check(x1, y1, x2, y2);
 | 
			
		||||
        if (y2 != 0)
 | 
			
		||||
            assert((x1 / y1).value() == x2 / y2);
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        if ( y2 != 0 )
 | 
			
		||||
            BOOST_TEST( (x1 / y1).value() == (x2 / y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check(x1, y1, x2, y2);
 | 
			
		||||
        if (y2 != 0)
 | 
			
		||||
            assert((x1 / y1).value() == x2 / y2);
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        if ( y2 != 0 )
 | 
			
		||||
            BOOST_TEST( (x1 % y1).value() == (x2 % y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        assert((x1 ^ y1).value() == (x2 ^ y2));
 | 
			
		||||
        BOOST_TEST( (x1 ^ y1).value() == (x2 ^ y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check(x1, y1, x2, y2);
 | 
			
		||||
        test_xorable_aux(x1, y1, x2, y2);
 | 
			
		||||
        test_xorable_aux(y1, x1, y2, x2);
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        test_xorable_aux( x1, y1, x2, y2 );
 | 
			
		||||
        test_xorable_aux( y1, x1, y2, x2 );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        assert((x1 & y1).value() == (x2 & y2));
 | 
			
		||||
        BOOST_TEST( (x1 & y1).value() == (x2 & y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check(x1, y1, x2, y2);
 | 
			
		||||
        test_andable_aux(x1, y1, x2, y2);
 | 
			
		||||
        test_andable_aux(y1, x1, y2, x2);
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        test_andable_aux( x1, y1, x2, y2 );
 | 
			
		||||
        test_andable_aux( y1, x1, y2, x2 );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        assert((x1 | y1).value() == (x2 | y2));
 | 
			
		||||
        BOOST_TEST( (x1 | y1).value() == (x2 | y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check(x1, y1, x2, y2);
 | 
			
		||||
        test_orable_aux(x1, y1, x2, y2);
 | 
			
		||||
        test_orable_aux(y1, x1, y2, x2);
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        test_orable_aux( x1, y1, x2, y2 );
 | 
			
		||||
        test_orable_aux( y1, x1, y2, x2 );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        BOOST_TEST( (x1 << y1).value() == (x2 << y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        BOOST_TEST( (x1 >> y1).value() == (x2 >> y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class X2>
 | 
			
		||||
    void test_incrementable(X1 x1, X2 x2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check(x1, x1, x2, x2);
 | 
			
		||||
        assert(x1++.value() == x2++);
 | 
			
		||||
        assert(x1.value() == x2);
 | 
			
		||||
        sanity_check( x1, x1, x2, x2 );
 | 
			
		||||
        BOOST_TEST( (x1++).value() == x2++ );
 | 
			
		||||
        BOOST_TEST( x1.value() == x2 );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class X2>
 | 
			
		||||
    void test_decrementable(X1 x1, X2 x2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check(x1, x1, x2, x2);
 | 
			
		||||
        assert(x1--.value() == x2--);
 | 
			
		||||
        assert(x1.value() == x2);
 | 
			
		||||
        sanity_check( x1, x1, x2, x2 );
 | 
			
		||||
        BOOST_TEST( (x1--).value() == x2-- );
 | 
			
		||||
        BOOST_TEST( x1.value() == x2 );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        test_less_than_comparable(x1, y1, x2, y2);
 | 
			
		||||
        test_equality_comparable(x1, y1, x2, y2);
 | 
			
		||||
        test_multipliable(x1, y1, x2, y2);
 | 
			
		||||
        test_addable(x1, y1, x2, y2);
 | 
			
		||||
        test_subtractable(x1, y1, x2, y2);
 | 
			
		||||
        test_dividable(x1, y1, x2, y2);
 | 
			
		||||
        test_modable(x1, y1, x2, y2);
 | 
			
		||||
        test_xorable(x1, y1, x2, y2);
 | 
			
		||||
        test_andable(x1, y1, x2, y2);
 | 
			
		||||
        test_orable(x1, y1, x2, y2);
 | 
			
		||||
        test_incrementable(x1, x2);
 | 
			
		||||
        test_decrementable(x1, x2);
 | 
			
		||||
        test_less_than_comparable( x1, y1, x2, y2 );
 | 
			
		||||
        test_equality_comparable( x1, y1, x2, y2 );
 | 
			
		||||
        test_multipliable( x1, y1, x2, y2 );
 | 
			
		||||
        test_addable( x1, y1, x2, y2 );
 | 
			
		||||
        test_subtractable( x1, y1, x2, y2 );
 | 
			
		||||
        test_dividable( x1, y1, x2, y2 );
 | 
			
		||||
        test_modable( x1, y1, x2, y2 );
 | 
			
		||||
        test_xorable( x1, y1, x2, y2 );
 | 
			
		||||
        test_andable( x1, y1, x2, y2 );
 | 
			
		||||
        test_orable( x1, y1, x2, y2 );
 | 
			
		||||
        test_left_shiftable( x1, y1, x2, y2 );
 | 
			
		||||
        test_right_shiftable( x1, y1, x2, y2 );
 | 
			
		||||
        test_incrementable( x1, x2 );
 | 
			
		||||
        test_decrementable( x1, x2 );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class Big, class Small>
 | 
			
		||||
    struct tester
 | 
			
		||||
    {
 | 
			
		||||
        void operator()(boost::min_rand& randomizer) const
 | 
			
		||||
        void operator()(boost::minstd_rand& randomizer) const
 | 
			
		||||
        {
 | 
			
		||||
            Big b1 = Big(randomizer());
 | 
			
		||||
            Big b2 = Big(randomizer());
 | 
			
		||||
            Small s = Small(randomizer());
 | 
			
		||||
            Big    b1 = Big( randomizer() );
 | 
			
		||||
            Big    b2 = Big( randomizer() );
 | 
			
		||||
            Small  s = Small( randomizer() );
 | 
			
		||||
            
 | 
			
		||||
            test_all(Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2);
 | 
			
		||||
            test_all(Wrapped2<Big, Small>(b1), s, b1, s);
 | 
			
		||||
            test_all( Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2 );
 | 
			
		||||
            test_all( Wrapped2<Big, Small>(b1), s, b1, s );
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // added as a regression test. We had a bug which this uncovered.
 | 
			
		||||
    struct Point
 | 
			
		||||
        : boost::addable<Point,
 | 
			
		||||
        boost::subtractable<Point> >
 | 
			
		||||
        : boost::addable<Point
 | 
			
		||||
        , boost::subtractable<Point> >
 | 
			
		||||
    {
 | 
			
		||||
        Point( int h, int v ) : h(h), v(v) {}
 | 
			
		||||
        Point() :h(0), v(0) {}
 | 
			
		||||
        const Point& operator+=( const Point& rhs ) { h += rhs.h; v += rhs.v; return *this; }
 | 
			
		||||
        const Point& operator-=( const Point& rhs ) { h -= rhs.h; v -= rhs.v; return *this; }
 | 
			
		||||
        const Point& operator+=( const Point& rhs )
 | 
			
		||||
            { h += rhs.h; v += rhs.v; return *this; }
 | 
			
		||||
        const Point& operator-=( const Point& rhs )
 | 
			
		||||
            { h -= rhs.h; v -= rhs.v; return *this; }
 | 
			
		||||
 | 
			
		||||
        int h;
 | 
			
		||||
        int v;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
} // unnamed namespace
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -340,20 +429,25 @@ template Wrapped2<unsigned long, unsigned char>;
 | 
			
		||||
template Wrapped2<unsigned long, unsigned long>;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef NDEBUG
 | 
			
		||||
#error This program is pointless when NDEBUG disables assert()!
 | 
			
		||||
#endif
 | 
			
		||||
#define PRIVATE_EXPR_TEST(e, t)  BOOST_TEST( ((e), (t)) )
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
test_main( int , char * [] )
 | 
			
		||||
{
 | 
			
		||||
    using std::cout;
 | 
			
		||||
    using std::endl;
 | 
			
		||||
 | 
			
		||||
    // Regression test.
 | 
			
		||||
    Point x;
 | 
			
		||||
    x = x + Point(3, 4);
 | 
			
		||||
    x = x - Point(3, 4);
 | 
			
		||||
    
 | 
			
		||||
    cout << "Created point, and operated on it." << endl;
 | 
			
		||||
    
 | 
			
		||||
    for (int n = 0; n < 10000; ++n)
 | 
			
		||||
    {
 | 
			
		||||
        boost::min_rand r;
 | 
			
		||||
        boost::minstd_rand r;
 | 
			
		||||
        tester<long, int>()(r);
 | 
			
		||||
        tester<long, signed char>()(r);
 | 
			
		||||
        tester<long, long>()(r);
 | 
			
		||||
@@ -367,115 +461,197 @@ int main()
 | 
			
		||||
        tester<unsigned int, unsigned char>()(r);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    cout << "Did random tester loop." << endl;
 | 
			
		||||
 | 
			
		||||
    MyInt i1(1);
 | 
			
		||||
    MyInt i2(2);
 | 
			
		||||
    MyInt i;
 | 
			
		||||
 | 
			
		||||
    assert( i1.value() == 1 );
 | 
			
		||||
    assert( i2.value() == 2 );
 | 
			
		||||
    assert( i.value() == 0 );
 | 
			
		||||
    BOOST_TEST( i1.value() == 1 );
 | 
			
		||||
    BOOST_TEST( i2.value() == 2 );
 | 
			
		||||
    BOOST_TEST( i.value() == 0 );
 | 
			
		||||
 | 
			
		||||
    i = i2;
 | 
			
		||||
    assert( i.value() == 2 );
 | 
			
		||||
    assert( i2 == i );
 | 
			
		||||
    assert( i1 != i2 );
 | 
			
		||||
    assert( i1 <  i2 );
 | 
			
		||||
    assert( i1 <= i2 );
 | 
			
		||||
    assert( i <= i2 );
 | 
			
		||||
    assert( i2 >  i1 );
 | 
			
		||||
    assert( i2 >= i1 );
 | 
			
		||||
    assert( i2 >= i );
 | 
			
		||||
    cout << "Created MyInt objects.\n";
 | 
			
		||||
 | 
			
		||||
    i = i1 + i2; assert( i.value() == 3 );
 | 
			
		||||
    i = i + i2; assert( i.value() == 5 );
 | 
			
		||||
    i = i - i1; assert( i.value() == 4 );
 | 
			
		||||
    i = i * i2; assert( i.value() == 8 );
 | 
			
		||||
    i = i / i2; assert( i.value() == 4 );
 | 
			
		||||
    i = i % (i - i1); assert( i.value() == 1 );
 | 
			
		||||
    i = i2 + i2; assert( i.value() == 4 );
 | 
			
		||||
    i = i1 | i2 | i; assert( i.value() == 7 );
 | 
			
		||||
    i = i & i2; assert( i.value() == 2 );
 | 
			
		||||
    i = i + i1; assert( i.value() == 3 );
 | 
			
		||||
    i = i ^ i1; assert( i.value() == 2 );
 | 
			
		||||
    i = (i+i1)*(i2|i1); assert( i.value() == 9 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) );
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( i2 == i );
 | 
			
		||||
    BOOST_TEST( i1 != i2 );
 | 
			
		||||
    BOOST_TEST( i1 <  i2 );
 | 
			
		||||
    BOOST_TEST( i1 <= i2 );
 | 
			
		||||
    BOOST_TEST( i <= i2 );
 | 
			
		||||
    BOOST_TEST( i2 >  i1 );
 | 
			
		||||
    BOOST_TEST( i2 >= i1 );
 | 
			
		||||
    BOOST_TEST( i2 >= i );
 | 
			
		||||
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) );
 | 
			
		||||
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) );
 | 
			
		||||
    
 | 
			
		||||
    cout << "Performed tests on MyInt objects.\n";
 | 
			
		||||
 | 
			
		||||
    MyLong j1(1);
 | 
			
		||||
    MyLong j2(2);
 | 
			
		||||
    MyLong j;
 | 
			
		||||
 | 
			
		||||
    assert( j1.value() == 1 );
 | 
			
		||||
    assert( j2.value() == 2 );
 | 
			
		||||
    assert( j.value() == 0 );
 | 
			
		||||
    BOOST_TEST( j1.value() == 1 );
 | 
			
		||||
    BOOST_TEST( j2.value() == 2 );
 | 
			
		||||
    BOOST_TEST( j.value() == 0 );
 | 
			
		||||
 | 
			
		||||
    j = j2;
 | 
			
		||||
    assert( j.value() == 2 );
 | 
			
		||||
    
 | 
			
		||||
    assert( j2 == j );
 | 
			
		||||
    assert( 2 == j );
 | 
			
		||||
    assert( j2 == 2 );    
 | 
			
		||||
    assert( j == j2 );
 | 
			
		||||
    assert( j1 != j2 );
 | 
			
		||||
    assert( j1 != 2 );
 | 
			
		||||
    assert( 1 != j2 );
 | 
			
		||||
    assert( j1 <  j2 );
 | 
			
		||||
    assert( 1 <  j2 );
 | 
			
		||||
    assert( j1 <  2 );
 | 
			
		||||
    assert( j1 <= j2 );
 | 
			
		||||
    assert( 1 <= j2 );
 | 
			
		||||
    assert( j1 <= j );
 | 
			
		||||
    assert( j <= j2 );
 | 
			
		||||
    assert( 2 <= j2 );
 | 
			
		||||
    assert( j <= 2 );
 | 
			
		||||
    assert( j2 >  j1 );
 | 
			
		||||
    assert( 2 >  j1 );
 | 
			
		||||
    assert( j2 >  1 );
 | 
			
		||||
    assert( j2 >= j1 );
 | 
			
		||||
    assert( 2 >= j1 );
 | 
			
		||||
    assert( j2 >= 1 );
 | 
			
		||||
    assert( j2 >= j );
 | 
			
		||||
    assert( 2 >= j );
 | 
			
		||||
    assert( j2 >= 2 );
 | 
			
		||||
    cout << "Created MyLong objects.\n";
 | 
			
		||||
 | 
			
		||||
    assert( (j1 + 2) == 3 );
 | 
			
		||||
    assert( (1 + j2) == 3 );
 | 
			
		||||
    j = j1 + j2; assert( j.value() == 3 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) );
 | 
			
		||||
    
 | 
			
		||||
    assert( (j + 2) == 5 );
 | 
			
		||||
    assert( (3 + j2) == 5 );
 | 
			
		||||
    j = j + j2; assert( j.value() == 5 );
 | 
			
		||||
    BOOST_TEST( j2 == j );
 | 
			
		||||
    BOOST_TEST( 2 == j );
 | 
			
		||||
    BOOST_TEST( j2 == 2 );    
 | 
			
		||||
    BOOST_TEST( j == j2 );
 | 
			
		||||
    BOOST_TEST( j1 != j2 );
 | 
			
		||||
    BOOST_TEST( j1 != 2 );
 | 
			
		||||
    BOOST_TEST( 1 != j2 );
 | 
			
		||||
    BOOST_TEST( j1 <  j2 );
 | 
			
		||||
    BOOST_TEST( 1 <  j2 );
 | 
			
		||||
    BOOST_TEST( j1 <  2 );
 | 
			
		||||
    BOOST_TEST( j1 <= j2 );
 | 
			
		||||
    BOOST_TEST( 1 <= j2 );
 | 
			
		||||
    BOOST_TEST( j1 <= j );
 | 
			
		||||
    BOOST_TEST( j <= j2 );
 | 
			
		||||
    BOOST_TEST( 2 <= j2 );
 | 
			
		||||
    BOOST_TEST( j <= 2 );
 | 
			
		||||
    BOOST_TEST( j2 >  j1 );
 | 
			
		||||
    BOOST_TEST( 2 >  j1 );
 | 
			
		||||
    BOOST_TEST( j2 >  1 );
 | 
			
		||||
    BOOST_TEST( j2 >= j1 );
 | 
			
		||||
    BOOST_TEST( 2 >= j1 );
 | 
			
		||||
    BOOST_TEST( j2 >= 1 );
 | 
			
		||||
    BOOST_TEST( j2 >= j );
 | 
			
		||||
    BOOST_TEST( 2 >= j );
 | 
			
		||||
    BOOST_TEST( j2 >= 2 );
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( (j1 + 2) == 3 );
 | 
			
		||||
    BOOST_TEST( (1 + j2) == 3 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) );
 | 
			
		||||
    
 | 
			
		||||
    assert( (j - 1) == 4 );
 | 
			
		||||
    j = j - j1; assert( j.value() == 4 );
 | 
			
		||||
    BOOST_TEST( (j + 2) == 5 );
 | 
			
		||||
    BOOST_TEST( (3 + j2) == 5 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) );
 | 
			
		||||
    
 | 
			
		||||
    assert( (j * 2) == 8 );
 | 
			
		||||
    assert( (4 * j2) == 8 );
 | 
			
		||||
    j = j * j2; assert( j.value() == 8 );
 | 
			
		||||
    BOOST_TEST( (j - 1) == 4 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) );
 | 
			
		||||
    
 | 
			
		||||
    assert( (j / 2) == 4 );
 | 
			
		||||
    j = j / j2; assert( j.value() == 4 );
 | 
			
		||||
    BOOST_TEST( (j * 2) == 8 );
 | 
			
		||||
    BOOST_TEST( (4 * j2) == 8 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) );
 | 
			
		||||
    
 | 
			
		||||
    assert( (j % 3) == 1 );
 | 
			
		||||
    j = j % (j - j1); assert( j.value() == 1 );
 | 
			
		||||
    BOOST_TEST( (j / 2) == 4 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) );
 | 
			
		||||
    
 | 
			
		||||
    j = j2 + j2; assert( j.value() == 4 );
 | 
			
		||||
    BOOST_TEST( (j % 3) == 1 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) );
 | 
			
		||||
    
 | 
			
		||||
    assert( (1 | j2 | j) == 7 );
 | 
			
		||||
    assert( (j1 | 2 | j) == 7 );
 | 
			
		||||
    assert( (j1 | j2 | 4) == 7 );
 | 
			
		||||
    j = j1 | j2 | j; assert( j.value() == 7 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) );
 | 
			
		||||
    
 | 
			
		||||
    assert( (7 & j2) == 2 );
 | 
			
		||||
    assert( (j & 2) == 2 );
 | 
			
		||||
    j = j & j2; assert( j.value() == 2 );
 | 
			
		||||
    BOOST_TEST( (1 | j2 | j) == 7 );
 | 
			
		||||
    BOOST_TEST( (j1 | 2 | j) == 7 );
 | 
			
		||||
    BOOST_TEST( (j1 | j2 | 4) == 7 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) );
 | 
			
		||||
    
 | 
			
		||||
    j = j | j1; assert( j.value() == 3 );
 | 
			
		||||
    BOOST_TEST( (7 & j2) == 2 );
 | 
			
		||||
    BOOST_TEST( (j & 2) == 2 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) );
 | 
			
		||||
    
 | 
			
		||||
    assert( (3 ^ j1) == 2 );
 | 
			
		||||
    assert( (j ^ 1) == 2 );
 | 
			
		||||
    j = j ^ j1; assert( j.value() == 2 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) );
 | 
			
		||||
    
 | 
			
		||||
    j = (j+j1)*(j2|j1); assert( j.value() == 9 );
 | 
			
		||||
    BOOST_TEST( (3 ^ j1) == 2 );
 | 
			
		||||
    BOOST_TEST( (j ^ 1) == 2 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) );
 | 
			
		||||
    
 | 
			
		||||
    std::cout << "0 errors detected\n";
 | 
			
		||||
    return 0;
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) );
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( (j1 << 2) == 4 );
 | 
			
		||||
    BOOST_TEST( (j2 << 1) == 4 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) );
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( (j >> 2) == 1 );
 | 
			
		||||
    BOOST_TEST( (j2 >> 1) == 1 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) );
 | 
			
		||||
    
 | 
			
		||||
    cout << "Performed tests on MyLong objects.\n";
 | 
			
		||||
 | 
			
		||||
    MyChar k1(1);
 | 
			
		||||
    MyChar k2(2);
 | 
			
		||||
    MyChar k;
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( k1.value() == 1 );
 | 
			
		||||
    BOOST_TEST( k2.value() == 2 );
 | 
			
		||||
    BOOST_TEST( k.value() == 0 );
 | 
			
		||||
 | 
			
		||||
    cout << "Created MyChar objects.\n";
 | 
			
		||||
 | 
			
		||||
    PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) );
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( k2 == k );
 | 
			
		||||
    BOOST_TEST( k1 != k2 );
 | 
			
		||||
    BOOST_TEST( k1 <  k2 );
 | 
			
		||||
    BOOST_TEST( k1 <= k2 );
 | 
			
		||||
    BOOST_TEST( k <= k2 );
 | 
			
		||||
    BOOST_TEST( k2 >  k1 );
 | 
			
		||||
    BOOST_TEST( k2 >= k1 );
 | 
			
		||||
    BOOST_TEST( k2 >= k );
 | 
			
		||||
    
 | 
			
		||||
    cout << "Performed tests on MyChar objects.\n";
 | 
			
		||||
 | 
			
		||||
    MyShort l1(1);
 | 
			
		||||
    MyShort l2(2);
 | 
			
		||||
    MyShort l;
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( l1.value() == 1 );
 | 
			
		||||
    BOOST_TEST( l2.value() == 2 );
 | 
			
		||||
    BOOST_TEST( l.value() == 0 );
 | 
			
		||||
 | 
			
		||||
    cout << "Created MyShort objects.\n";
 | 
			
		||||
 | 
			
		||||
    PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( l2 == l );
 | 
			
		||||
    BOOST_TEST( 2 == l );
 | 
			
		||||
    BOOST_TEST( l2 == 2 );    
 | 
			
		||||
    BOOST_TEST( l == l2 );
 | 
			
		||||
    BOOST_TEST( l1 != l2 );
 | 
			
		||||
    BOOST_TEST( l1 != 2 );
 | 
			
		||||
    BOOST_TEST( 1 != l2 );
 | 
			
		||||
    BOOST_TEST( l1 <  l2 );
 | 
			
		||||
    BOOST_TEST( 1 <  l2 );
 | 
			
		||||
    BOOST_TEST( l1 <  2 );
 | 
			
		||||
    BOOST_TEST( l1 <= l2 );
 | 
			
		||||
    BOOST_TEST( 1 <= l2 );
 | 
			
		||||
    BOOST_TEST( l1 <= l );
 | 
			
		||||
    BOOST_TEST( l <= l2 );
 | 
			
		||||
    BOOST_TEST( 2 <= l2 );
 | 
			
		||||
    BOOST_TEST( l <= 2 );
 | 
			
		||||
    BOOST_TEST( l2 >  l1 );
 | 
			
		||||
    BOOST_TEST( 2 >  l1 );
 | 
			
		||||
    BOOST_TEST( l2 >  1 );
 | 
			
		||||
    BOOST_TEST( l2 >= l1 );
 | 
			
		||||
    BOOST_TEST( 2 >= l1 );
 | 
			
		||||
    BOOST_TEST( l2 >= 1 );
 | 
			
		||||
    BOOST_TEST( l2 >= l );
 | 
			
		||||
    BOOST_TEST( 2 >= l );
 | 
			
		||||
    BOOST_TEST( l2 >= 2 );
 | 
			
		||||
    
 | 
			
		||||
    cout << "Performed tests on MyShort objects.\n";
 | 
			
		||||
    
 | 
			
		||||
    return boost::exit_success;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										391
									
								
								projection_iterator.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										391
									
								
								projection_iterator.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,391 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
<title>Projection Iterator Adaptor Documentation</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
 | 
			
		||||
align="center" width="277" height="86">
 | 
			
		||||
 | 
			
		||||
<h1>Projection Iterator Adaptor</h1>
 | 
			
		||||
 | 
			
		||||
Defined in header
 | 
			
		||||
<a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
The projection iterator adaptor is similar to the <a
 | 
			
		||||
href="./transform_iterator.htm">transform iterator adaptor</a> in that
 | 
			
		||||
its <tt>operator*()</tt> applies some function to the result of
 | 
			
		||||
dereferencing the base iterator and then returns the result. The
 | 
			
		||||
difference is that the function must return a reference to some
 | 
			
		||||
existing object (for example, a data member within the
 | 
			
		||||
<tt>value_type</tt> of the base iterator). The following
 | 
			
		||||
<b>pseudo-code</b> gives the basic idea. The data member <tt>p</tt> is
 | 
			
		||||
the function object.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
  reference projection_iterator::operator*() const {
 | 
			
		||||
    return this->p(*this->base_iterator);
 | 
			
		||||
  }
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<h2>Synopsis</h2>
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
namespace boost {
 | 
			
		||||
  template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator>
 | 
			
		||||
  struct projection_iterator_generator;
 | 
			
		||||
  
 | 
			
		||||
  template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, 
 | 
			
		||||
            class BaseIterator, class ConstBaseIterator>
 | 
			
		||||
  struct projection_iterator_pair_generator;
 | 
			
		||||
 | 
			
		||||
  template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator>
 | 
			
		||||
  typename projection_iterator_generator<AdaptableUnaryFunction, BaseIterator>::type
 | 
			
		||||
  make_projection_iterator(BaseIterator base,
 | 
			
		||||
			   const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
 | 
			
		||||
 | 
			
		||||
  template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class ConstBaseIterator>
 | 
			
		||||
  typename projection_iterator_generator<AdaptableUnaryFunction, ConstBaseIterator>::type
 | 
			
		||||
  make_const_projection_iterator(ConstBaseIterator base,
 | 
			
		||||
                                 const AdaptableUnaryFunction& p = AdaptableUnaryFunction())  
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
<h2><a name="projection_iterator_generator">The Projection Iterator Type
 | 
			
		||||
Generator</a></h2>
 | 
			
		||||
 | 
			
		||||
The class <tt>projection_iterator_generator</tt> is a helper class
 | 
			
		||||
whose purpose is to construct an projection iterator type.  The main
 | 
			
		||||
template parameter for this class is the <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a>
 | 
			
		||||
function object type and the <tt>BaseIterator</tt> type that is being
 | 
			
		||||
wrapped.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator>
 | 
			
		||||
class projection_iterator_generator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  typedef <tt><a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> type; // the resulting projection iterator type 
 | 
			
		||||
};
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<h3>Example</h3>
 | 
			
		||||
 | 
			
		||||
In the following example we have a list of personnel records. Each
 | 
			
		||||
record has an employee's name and ID number. We want to be able to
 | 
			
		||||
traverse through the list accessing either the name or the ID numbers
 | 
			
		||||
of the employees using the projection iterator so we create the
 | 
			
		||||
function object classes <tt>select_name</tt> and
 | 
			
		||||
<tt>select_ID</tt>. We then use the
 | 
			
		||||
<tt>projection_iterator_generator</tt> class to create a projection
 | 
			
		||||
iterator and use it to print out the names of the employees.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
struct personnel_record {
 | 
			
		||||
  personnel_record(std::string n, int id) : m_name(n), m_ID(id) { }
 | 
			
		||||
  std::string m_name;
 | 
			
		||||
  int m_ID;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct select_name {
 | 
			
		||||
  typedef personnel_record argument_type;
 | 
			
		||||
  typedef std::string result_type;
 | 
			
		||||
  const std::string& operator()(const personnel_record& r) const {
 | 
			
		||||
    return r.m_name;
 | 
			
		||||
  }
 | 
			
		||||
  std::string& operator()(personnel_record& r) const {
 | 
			
		||||
    return r.m_name;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct select_ID {
 | 
			
		||||
  typedef personnel_record argument_type;
 | 
			
		||||
  typedef int result_type;
 | 
			
		||||
  const int& operator()(const personnel_record& r) const {
 | 
			
		||||
    return r.m_ID;
 | 
			
		||||
  }
 | 
			
		||||
  int& operator()(personnel_record& r) const {
 | 
			
		||||
    return r.m_ID;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  std::list<personnel_record> personnel_list;
 | 
			
		||||
 | 
			
		||||
  personnel_list.push_back(personnel_record("Barney", 13423));
 | 
			
		||||
  personnel_list.push_back(personnel_record("Fred", 12343));
 | 
			
		||||
  personnel_list.push_back(personnel_record("Wilma", 62454));
 | 
			
		||||
  personnel_list.push_back(personnel_record("Betty", 20490));
 | 
			
		||||
 | 
			
		||||
  // Example of using projection_iterator_generator
 | 
			
		||||
  // to print out the names in the personnel list.
 | 
			
		||||
 | 
			
		||||
  boost::projection_iterator_generator<select_name,
 | 
			
		||||
    std::list<personnel_record>::iterator>::type
 | 
			
		||||
    personnel_first(personnel_list.begin()),
 | 
			
		||||
    personnel_last(personnel_list.end());
 | 
			
		||||
 | 
			
		||||
  std::copy(personnel_first, personnel_last,
 | 
			
		||||
            std::ostream_iterator<std::string>(std::cout, "\n"));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // to be continued...
 | 
			
		||||
</pre>
 | 
			
		||||
The output for this part is:
 | 
			
		||||
<pre>
 | 
			
		||||
Barney
 | 
			
		||||
Fred
 | 
			
		||||
Wilma
 | 
			
		||||
Betty
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<h3>Template Parameters</h3>
 | 
			
		||||
 | 
			
		||||
<Table border>
 | 
			
		||||
<TR>
 | 
			
		||||
<TH>Parameter</TH><TH>Description</TH>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a></TD>
 | 
			
		||||
<TD>The type of the function object. The <tt>argument_type</tt> of the
 | 
			
		||||
function must match the value type of the base iterator. The function
 | 
			
		||||
should return a reference to the function's <tt>result_type</tt>.
 | 
			
		||||
The <tt>result_type</tt> will be the resulting iterator's <tt>value_type</tt>.
 | 
			
		||||
</TD>
 | 
			
		||||
</TD>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><tt>BaseIterator</tt></TD>
 | 
			
		||||
<TD>The iterator type being wrapped.</TD>
 | 
			
		||||
</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
</Table>
 | 
			
		||||
 | 
			
		||||
<h3>Model of</h3>
 | 
			
		||||
 | 
			
		||||
If the base iterator is a model of <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
 | 
			
		||||
Access Iterator</a> then so is the resulting projection iterator.  If
 | 
			
		||||
the base iterator supports less functionality than this the resulting
 | 
			
		||||
projection iterator will also support less functionality.
 | 
			
		||||
 | 
			
		||||
<h3>Members</h3>
 | 
			
		||||
 | 
			
		||||
The projection iterator type implements the member functions and
 | 
			
		||||
operators required of the <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
 | 
			
		||||
Access Iterator</a> concept.
 | 
			
		||||
In addition it has the following constructor:
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
projection_iterator_generator::type(const BaseIterator& it,
 | 
			
		||||
                                    const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>
 | 
			
		||||
 | 
			
		||||
<h2><a name="projection_iterator_pair_generator">The Projection Iterator Pair
 | 
			
		||||
Generator</a></h2>
 | 
			
		||||
 | 
			
		||||
Sometimes a mutable/const pair of iterator types is needed, such as
 | 
			
		||||
when implementing a container type. The
 | 
			
		||||
<tt>projection_iterator_pair_generator</tt> class makes it more
 | 
			
		||||
convenient to create this pair of iterator types.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator, class ConstBaseIterator>
 | 
			
		||||
class projection_iterator_pair_generator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  typedef <tt><a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> iterator;       // the mutable projection iterator type 
 | 
			
		||||
  typedef <tt><a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> const_iterator; // the immutable projection iterator type 
 | 
			
		||||
};
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<h3>Example</h3>
 | 
			
		||||
 | 
			
		||||
In this part of the example we use the
 | 
			
		||||
<tt>projection_iterator_pair_generator</tt> to create a mutable/const
 | 
			
		||||
pair of projection iterators that access the ID numbers of the
 | 
			
		||||
personnel. We use the mutable iterator to re-index the ID numbers from
 | 
			
		||||
zero. We then use the constant iterator to print the ID numbers out.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
  // continuing from the last example...
 | 
			
		||||
 | 
			
		||||
  typedef boost::projection_iterator_pair_generator<select_ID,
 | 
			
		||||
    std::list<personnel_record>::iterator,
 | 
			
		||||
    std::list<personnel_record>::const_iterator> PairGen;
 | 
			
		||||
 | 
			
		||||
  PairGen::iterator ID_first(personnel_list.begin()),
 | 
			
		||||
    ID_last(personnel_list.end());
 | 
			
		||||
 | 
			
		||||
  int new_id = 0;
 | 
			
		||||
  while (ID_first != ID_last) {
 | 
			
		||||
    *ID_first = new_id++;
 | 
			
		||||
    ++ID_first;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  PairGen::const_iterator const_ID_first(personnel_list.begin()),
 | 
			
		||||
    const_ID_last(personnel_list.end());
 | 
			
		||||
 | 
			
		||||
  std::copy(const_ID_first, const_ID_last,
 | 
			
		||||
            std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  // to be continued...
 | 
			
		||||
</pre>
 | 
			
		||||
The output is:
 | 
			
		||||
<pre>
 | 
			
		||||
0 1 2 3 
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<h3>Template Parameters</h3>
 | 
			
		||||
 | 
			
		||||
<Table border>
 | 
			
		||||
<TR>
 | 
			
		||||
<TH>Parameter</TH><TH>Description</TH>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a></TD>
 | 
			
		||||
<TD>The type of the function object. The <tt>argument_type</tt> of the
 | 
			
		||||
function must match the value type of the base iterator. The function
 | 
			
		||||
should return a true reference to the function's <tt>result_type</tt>.
 | 
			
		||||
The <tt>result_type</tt> will be the resulting iterator's <tt>value_type</tt>.
 | 
			
		||||
</TD>
 | 
			
		||||
</TD>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><tt>BaseIterator</tt></TD>
 | 
			
		||||
<TD>The mutable iterator type being wrapped.</TD>
 | 
			
		||||
</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><tt>ConstBaseIterator</tt></TD>
 | 
			
		||||
<TD>The constant iterator type being wrapped.</TD>
 | 
			
		||||
</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
</Table>
 | 
			
		||||
 | 
			
		||||
<h3>Model of</h3>
 | 
			
		||||
 | 
			
		||||
If the base iterator types model the <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
 | 
			
		||||
Access Iterator</a> then so do the resulting projection iterator
 | 
			
		||||
types.  If the base iterators support less functionality the
 | 
			
		||||
resulting projection iterator types will also support less
 | 
			
		||||
functionality.  The resulting <tt>iterator</tt> type is mutable, and
 | 
			
		||||
the resulting <tt>const_iterator</tt> type is constant.
 | 
			
		||||
 | 
			
		||||
<h3>Members</h3>
 | 
			
		||||
 | 
			
		||||
The resulting <tt>iterator</tt> and <tt>const_iterator</tt> types
 | 
			
		||||
implements the member functions and operators required of the <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
 | 
			
		||||
Access Iterator</a> concept.  In addition they support the following
 | 
			
		||||
constructors:
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
projection_iterator_pair_generator::iterator(const BaseIterator& it,
 | 
			
		||||
                                             const AdaptableUnaryFunction& p = AdaptableUnaryFunction())</pre>
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
projection_iterator_pair_generator::const_iterator(const BaseIterator& it,
 | 
			
		||||
                                                   const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>
 | 
			
		||||
 | 
			
		||||
<h2><a name="make_projection_iterator">The Projection Iterator Object Generators</a></h2>
 | 
			
		||||
 | 
			
		||||
The <tt>make_projection_iterator()</tt> and
 | 
			
		||||
<tt>make_const_projection_iterator()</tt> functions provide a more
 | 
			
		||||
convenient way to create projection iterator objects. The functions
 | 
			
		||||
save the user the trouble of explicitly writing out the iterator
 | 
			
		||||
types.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator>
 | 
			
		||||
typename projection_iterator_generator<AdaptableUnaryFunction, BaseIterator>::type
 | 
			
		||||
make_projection_iterator(BaseIterator base,
 | 
			
		||||
			 const AdaptableUnaryFunction& p = AdaptableUnaryFunction())  
 | 
			
		||||
 | 
			
		||||
template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class ConstBaseIterator>
 | 
			
		||||
typename projection_iterator_generator<AdaptableUnaryFunction, ConstBaseIterator>::type
 | 
			
		||||
make_const_projection_iterator(ConstBaseIterator base,
 | 
			
		||||
			       const AdaptableUnaryFunction& p = AdaptableUnaryFunction())  
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Example</h3>
 | 
			
		||||
 | 
			
		||||
In this part of the example, we again print out the names of the
 | 
			
		||||
personnel, but this time we use the
 | 
			
		||||
<tt>make_const_projection_iterator()</tt> function to save some typing.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
  // continuing from the last example...
 | 
			
		||||
 | 
			
		||||
  std::copy
 | 
			
		||||
    (boost::make_const_projection_iterator<select_name>(personnel_list.begin()),
 | 
			
		||||
     boost::make_const_projection_iterator<select_name>(personnel_list.end()),
 | 
			
		||||
     std::ostream_iterator<std::string>(std::cout, "\n"));
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
The output is:
 | 
			
		||||
<pre>
 | 
			
		||||
Barney
 | 
			
		||||
Fred
 | 
			
		||||
Wilma
 | 
			
		||||
Betty
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->17 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14763" --></p>
 | 
			
		||||
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
<!--  LocalWords:  html charset alt gif hpp BaseIterator const namespace struct
 | 
			
		||||
 -->
 | 
			
		||||
<!--  LocalWords:  ConstPointer ConstReference typename iostream int abcdefg
 | 
			
		||||
 -->
 | 
			
		||||
<!--  LocalWords:  sizeof  PairGen pre Siek htm AdaptableUnaryFunction
 | 
			
		||||
 -->
 | 
			
		||||
<!--  LocalWords:  ConstBaseIterator
 | 
			
		||||
 -->
 | 
			
		||||
							
								
								
									
										96
									
								
								projection_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								projection_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
struct personnel_record {
 | 
			
		||||
  personnel_record(std::string n, int id) : m_name(n), m_ID(id) { }
 | 
			
		||||
  std::string m_name;
 | 
			
		||||
  int m_ID;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct select_name {
 | 
			
		||||
  typedef personnel_record argument_type;
 | 
			
		||||
  typedef std::string result_type;
 | 
			
		||||
  const std::string& operator()(const personnel_record& r) const {
 | 
			
		||||
    return r.m_name;
 | 
			
		||||
  }
 | 
			
		||||
  std::string& operator()(personnel_record& r) const {
 | 
			
		||||
    return r.m_name;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct select_ID {
 | 
			
		||||
  typedef personnel_record argument_type;
 | 
			
		||||
  typedef int result_type;
 | 
			
		||||
  const int& operator()(const personnel_record& r) const {
 | 
			
		||||
    return r.m_ID;
 | 
			
		||||
  }
 | 
			
		||||
  int& operator()(personnel_record& r) const {
 | 
			
		||||
    return r.m_ID;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  std::list<personnel_record> personnel_list;
 | 
			
		||||
 | 
			
		||||
  personnel_list.push_back(personnel_record("Barney", 13423));
 | 
			
		||||
  personnel_list.push_back(personnel_record("Fred", 12343));
 | 
			
		||||
  personnel_list.push_back(personnel_record("Wilma", 62454));
 | 
			
		||||
  personnel_list.push_back(personnel_record("Betty", 20490));
 | 
			
		||||
 | 
			
		||||
  // Example of using projection_iterator_generator
 | 
			
		||||
  // to print out the names in the personnel list.
 | 
			
		||||
 | 
			
		||||
  boost::projection_iterator_generator<select_name,
 | 
			
		||||
    std::list<personnel_record>::iterator>::type
 | 
			
		||||
    personnel_first(personnel_list.begin()),
 | 
			
		||||
    personnel_last(personnel_list.end());
 | 
			
		||||
 | 
			
		||||
  std::copy(personnel_first, personnel_last,
 | 
			
		||||
            std::ostream_iterator<std::string>(std::cout, "\n"));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  // Example of using projection_iterator_pair_generator
 | 
			
		||||
  // to assign new ID numbers to the personnel.
 | 
			
		||||
  
 | 
			
		||||
  typedef boost::projection_iterator_pair_generator<select_ID,
 | 
			
		||||
    std::list<personnel_record>::iterator,
 | 
			
		||||
    std::list<personnel_record>::const_iterator> PairGen;
 | 
			
		||||
 | 
			
		||||
  PairGen::iterator ID_first(personnel_list.begin()),
 | 
			
		||||
    ID_last(personnel_list.end());
 | 
			
		||||
 | 
			
		||||
  int new_id = 0;
 | 
			
		||||
  while (ID_first != ID_last) {
 | 
			
		||||
    *ID_first = new_id++;
 | 
			
		||||
    ++ID_first;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  PairGen::const_iterator const_ID_first(personnel_list.begin()),
 | 
			
		||||
    const_ID_last(personnel_list.end());
 | 
			
		||||
 | 
			
		||||
  std::copy(const_ID_first, const_ID_last,
 | 
			
		||||
            std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  // Example of using make_const_projection_iterator()
 | 
			
		||||
  // to print out the names in the personnel list again.
 | 
			
		||||
  
 | 
			
		||||
  std::copy
 | 
			
		||||
    (boost::make_const_projection_iterator<select_name>(personnel_list.begin()),
 | 
			
		||||
     boost::make_const_projection_iterator<select_name>(personnel_list.end()),
 | 
			
		||||
     std::ostream_iterator<std::string>(std::cout, "\n"));
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										331
									
								
								reverse_iterator.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								reverse_iterator.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,331 @@
 | 
			
		||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
 | 
			
		||||
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
    <meta name="generator" content="HTML Tidy, see www.w3.org">
 | 
			
		||||
    <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
 | 
			
		||||
    <meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
    <meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
 | 
			
		||||
    <title>Reverse Iterator Adaptor Documentation</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
    <img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
 | 
			
		||||
    "center" width="277" height="86"> 
 | 
			
		||||
 | 
			
		||||
    <h1>Reverse Iterator Adaptor</h1>
 | 
			
		||||
    Defined in header <a href=
 | 
			
		||||
    "../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a> 
 | 
			
		||||
 | 
			
		||||
    <p>The reverse iterator adaptor flips the direction of a base iterator's
 | 
			
		||||
    motion. Invoking <tt>operator++()</tt> moves the base iterator backward and
 | 
			
		||||
    invoking <tt>operator--()</tt> moves the base iterator forward. The Boost
 | 
			
		||||
    reverse iterator adaptor is better to use than the
 | 
			
		||||
    <tt>std::reverse_iterator</tt> class in situations where pairs of
 | 
			
		||||
    mutable/constant iterators are needed (e.g., in containers) because
 | 
			
		||||
    comparisons and conversions between the mutable and const versions are
 | 
			
		||||
    implemented correctly.
 | 
			
		||||
 | 
			
		||||
    <h2>Synopsis</h2>
 | 
			
		||||
<pre>
 | 
			
		||||
namespace boost {
 | 
			
		||||
  template <class <a href=
 | 
			
		||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>,
 | 
			
		||||
            class Value, class Reference, class Pointer, class Category, class Distance>
 | 
			
		||||
  struct reverse_iterator_generator;
 | 
			
		||||
  
 | 
			
		||||
  template <class <a href=
 | 
			
		||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>>
 | 
			
		||||
  typename reverse_iterator_generator<BidirectionalIterator>::type
 | 
			
		||||
  make_reverse_iterator(BidirectionalIterator base)  
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <h2><a name="reverse_iterator_generator">The Reverse Iterator Type
 | 
			
		||||
    Generator</a></h2>
 | 
			
		||||
    The <tt>reverse_iterator_generator</tt> template is a <a href=
 | 
			
		||||
    "../../more/generic_programming.html#type_generator">generator</a> of
 | 
			
		||||
    reverse iterator types. The main template parameter for this class is the
 | 
			
		||||
    base <tt>BidirectionalIterator</tt> type that is being adapted. In most
 | 
			
		||||
    cases the associated types of the base iterator can be deduced using
 | 
			
		||||
    <tt>std::iterator_traits</tt>, but in some situations the user may want to
 | 
			
		||||
    override these types, so there are also template parameters for the base
 | 
			
		||||
    iterator's associated types. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
template <class <a href=
 | 
			
		||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a>,
 | 
			
		||||
          class Value, class Reference, class Pointer, class Category, class Distance>
 | 
			
		||||
class reverse_iterator_generator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  typedef <tt><a href=
 | 
			
		||||
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> type; // the resulting reverse iterator type 
 | 
			
		||||
};
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <h3>Example</h3>
 | 
			
		||||
    In this example we sort a sequence of letters and then output the sequence
 | 
			
		||||
    in descending order using reverse iterators. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  char letters[] = "hello world!";
 | 
			
		||||
  const int N = sizeof(letters)/sizeof(char) - 1;
 | 
			
		||||
  std::cout << "original sequence of letters:\t"
 | 
			
		||||
      << letters << std::endl;
 | 
			
		||||
 | 
			
		||||
  std::sort(letters, letters + N);
 | 
			
		||||
 | 
			
		||||
  // Use reverse_iterator_generator to print a sequence
 | 
			
		||||
  // of letters in reverse order.
 | 
			
		||||
  
 | 
			
		||||
  boost::reverse_iterator_generator<char*>::type
 | 
			
		||||
    reverse_letters_first(letters + N),
 | 
			
		||||
    reverse_letters_last(letters);
 | 
			
		||||
 | 
			
		||||
  std::cout << "letters in descending order:\t";
 | 
			
		||||
  std::copy(reverse_letters_first, reverse_letters_last,
 | 
			
		||||
      std::ostream_iterator<char>(std::cout));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // to be continued...
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
    The output is: 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
original sequence of letters: hello world!
 | 
			
		||||
letters in descending order:  wroolllhed! 
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <h3>Template Parameters</h3>
 | 
			
		||||
 | 
			
		||||
    <table border>
 | 
			
		||||
      <tr>
 | 
			
		||||
        <th>Parameter
 | 
			
		||||
 | 
			
		||||
        <th>Description
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt><a href=
 | 
			
		||||
        "http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a></tt>
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        <td>The iterator type being wrapped.
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Value</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The value-type of the base iterator and the resulting reverse
 | 
			
		||||
        iterator.<br>
 | 
			
		||||
         <b>Default:</b><tt>std::iterator_traits<BidirectionalIterator>::value_type</tt>
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Reference</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>reference</tt> type of the resulting iterator, and in
 | 
			
		||||
        particular, the result type of <tt>operator*()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&</tt> is
 | 
			
		||||
        used. Otherwise
 | 
			
		||||
        <tt>std::iterator_traits<BidirectionalIterator>::reference</tt>
 | 
			
		||||
        is used.
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Pointer</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>pointer</tt> type of the resulting iterator, and in
 | 
			
		||||
        particular, the result type of <tt>operator->()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
 | 
			
		||||
        otherwise
 | 
			
		||||
        <tt>std::iterator_traits<BidirectionalIterator>::pointer</tt>.
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Category</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
 | 
			
		||||
         <b>Default:</b>
 | 
			
		||||
        <tt>std::iterator_traits<BidirectionalIterator>::iterator_category</tt>
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Distance</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>difference_type</tt> for the resulting iterator.<br>
 | 
			
		||||
         <b>Default:</b>
 | 
			
		||||
        <tt>std::iterator_traits<BidirectionalIterator&gt::difference_type</tt>
 | 
			
		||||
        
 | 
			
		||||
    </table>
 | 
			
		||||
 | 
			
		||||
    <h3>Concept Model</h3>
 | 
			
		||||
    The indirect iterator will model whichever <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/Iterators.html">standard iterator concept
 | 
			
		||||
    category</a> is modeled by the base iterator. Thus, if the base iterator is
 | 
			
		||||
    a model of <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
 | 
			
		||||
    Iterator</a> then so is the resulting indirect iterator. If the base
 | 
			
		||||
    iterator models a more restrictive concept, the resulting indirect iterator
 | 
			
		||||
    will model the same concept. The base iterator must be at least a <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional
 | 
			
		||||
    Iterator</a> 
 | 
			
		||||
 | 
			
		||||
    <h3>Members</h3>
 | 
			
		||||
    The reverse iterator type implements the member functions and operators
 | 
			
		||||
    required of the <a href=
 | 
			
		||||
    "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
 | 
			
		||||
    Iterator</a> concept. In addition it has the following constructor: 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
reverse_iterator_generator::type(const BidirectionalIterator& it)
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <br>
 | 
			
		||||
     <br>
 | 
			
		||||
     
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <p>
 | 
			
		||||
 | 
			
		||||
    <h2><a name="make_reverse_iterator">The Reverse Iterator Object
 | 
			
		||||
    Generator</a></h2>
 | 
			
		||||
    The <tt>make_reverse_iterator()</tt> function provides a more convenient
 | 
			
		||||
    way to create reverse iterator objects. The function saves the user the
 | 
			
		||||
    trouble of explicitly writing out the iterator types. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
template <class BidirectionalIterator>
 | 
			
		||||
typename reverse_iterator_generator<BidirectionalIterator>::type
 | 
			
		||||
make_reverse_iterator(BidirectionalIterator base);
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
 | 
			
		||||
    <h3>Example</h3>
 | 
			
		||||
    In this part of the example we use <tt>make_reverse_iterator()</tt> to
 | 
			
		||||
    print the sequence of letters in reverse-reverse order, which is the
 | 
			
		||||
    original order. 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
  // continuing from the previous example...
 | 
			
		||||
 | 
			
		||||
  std::cout << "letters in ascending order:\t";
 | 
			
		||||
  std::copy(boost::make_reverse_iterator(reverse_letters_last),
 | 
			
		||||
      boost::make_reverse_iterator(reverse_letters_first),
 | 
			
		||||
      std::ostream_iterator<char>(std::cout));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
    The output is: 
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
letters in ascending order:  !dehllloorw
 | 
			
		||||
</pre>
 | 
			
		||||
    </blockquote>
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <h2><a name="interactions">Constant/Mutable Iterator Interactions</a></h2>
 | 
			
		||||
 | 
			
		||||
    <p>One failing of the standard <tt><a
 | 
			
		||||
    href="http://www.sgi.com/tech/stl/ReverseIterator.html">reverse_iterator</a></tt>
 | 
			
		||||
    adaptor is that it doesn't properly support interactions between adapted
 | 
			
		||||
    <tt>const</tt> and non-<tt>const</tt> iterators. For example:
 | 
			
		||||
<blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
template <class T> void convert(T x) {}
 | 
			
		||||
 | 
			
		||||
// Test interactions of a matched pair of random access iterators
 | 
			
		||||
template <class Iterator, class ConstIterator>
 | 
			
		||||
void test_interactions(Iterator i, ConstIterator ci)
 | 
			
		||||
{
 | 
			
		||||
  bool eq = i == ci;               // comparisons
 | 
			
		||||
  bool ne = i != ci;            
 | 
			
		||||
  bool lt = i < ci;
 | 
			
		||||
  bool le = i <= ci;
 | 
			
		||||
  bool gt = i > ci;
 | 
			
		||||
  bool ge = i >= ci;
 | 
			
		||||
  std::size_t distance = i - ci;   // difference
 | 
			
		||||
  ci = i;                          // assignment
 | 
			
		||||
  ConstIterator ci2(i);            // construction
 | 
			
		||||
  convert<ConstIterator>(i);       // implicit conversion
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void f()
 | 
			
		||||
{
 | 
			
		||||
  typedef std::vector<int> vec;
 | 
			
		||||
  vec v;
 | 
			
		||||
  const vec& cv;
 | 
			
		||||
 | 
			
		||||
  test_interactions(v.begin(), cv.begin());   // <font color="#007F00">OK</font>
 | 
			
		||||
  test_interactions(v.rbegin(), cv.rbegin()); // <font color="#FF0000">ERRORS ON EVERY TEST!!</font>
 | 
			
		||||
</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
Reverse iterators created with <tt>boost::reverse_iterator_generator</tt> don't have this problem, though:
 | 
			
		||||
<blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
  typedef boost::reverse_iterator_generator<vec::iterator>::type ri;
 | 
			
		||||
  typedef boost::reverse_iterator_generator<vec::const_iterator>::type cri;
 | 
			
		||||
  test_interactions(ri(v.begin()), cri(cv.begin()));   // <font color="#007F00">OK!!</font>
 | 
			
		||||
</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
Or, more simply,
 | 
			
		||||
<blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
  test_interactions(
 | 
			
		||||
    boost::make_reverse_iterator(v.begin()), 
 | 
			
		||||
    boost::make_reverse_iterator(cv.begin()));   // <font color="#007F00">OK!!</font>
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
 | 
			
		||||
<p>If you are wondering why there is no
 | 
			
		||||
<tt>reverse_iterator_pair_generator</tt> in the manner of <tt><a
 | 
			
		||||
href="projection_iterator.htm#projection_iterator_pair_generator">projection_iterator_pair_generator</a></tt>,
 | 
			
		||||
the answer is simple: we tried it, but found that in practice it took
 | 
			
		||||
<i>more</i> typing to use <tt>reverse_iterator_pair_generator</tt> than to
 | 
			
		||||
simply use <tt>reverse_iterator_generator</tt> twice!<br><br>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    <p>Revised 
 | 
			
		||||
    <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->17 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14763" -->
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <p>© Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell
 | 
			
		||||
    and distribute this document is granted provided this copyright notice
 | 
			
		||||
    appears in all copies. This document is provided "as is" without express or
 | 
			
		||||
    implied warranty, and with no claim as to its suitability for any purpose. 
 | 
			
		||||
    <!--  LocalWords:  html charset alt gif hpp BidirectionalIterator const namespace struct
 | 
			
		||||
         -->
 | 
			
		||||
     
 | 
			
		||||
    <!--  LocalWords:  ConstPointer ConstReference typename iostream int abcdefg
 | 
			
		||||
         -->
 | 
			
		||||
     <!--  LocalWords:  sizeof  PairGen pre Siek wroolllhed dehllloorw
 | 
			
		||||
         -->
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										42
									
								
								reverse_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								reverse_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  char letters[] = "hello world!";
 | 
			
		||||
  const int N = sizeof(letters)/sizeof(char) - 1;
 | 
			
		||||
  std::cout << "original sequence of letters:\t"
 | 
			
		||||
	    << letters << std::endl;
 | 
			
		||||
 | 
			
		||||
  std::sort(letters, letters + N);
 | 
			
		||||
 | 
			
		||||
  // Use reverse_iterator_generator to print a sequence
 | 
			
		||||
  // of letters in reverse order.
 | 
			
		||||
  
 | 
			
		||||
  boost::reverse_iterator_generator<char*>::type
 | 
			
		||||
    reverse_letters_first(letters + N),
 | 
			
		||||
    reverse_letters_last(letters);
 | 
			
		||||
 | 
			
		||||
  std::cout << "letters in descending order:\t";
 | 
			
		||||
  std::copy(reverse_letters_first, reverse_letters_last,
 | 
			
		||||
	    std::ostream_iterator<char>(std::cout));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Use make_reverse_iterator() to print the sequence
 | 
			
		||||
  // of letters in reverse-reverse order.
 | 
			
		||||
 | 
			
		||||
  std::cout << "letters in ascending order:\t";
 | 
			
		||||
  std::copy(boost::make_reverse_iterator(reverse_letters_last),
 | 
			
		||||
	    boost::make_reverse_iterator(reverse_letters_first),
 | 
			
		||||
	    std::ostream_iterator<char>(std::cout));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										8
									
								
								tie.html
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								tie.html
									
									
									
									
									
								
							@@ -23,7 +23,9 @@
 | 
			
		||||
<TT>tie</TT>
 | 
			
		||||
</H1>
 | 
			
		||||
 | 
			
		||||
<P>
 | 
			
		||||
<h3>
 | 
			
		||||
[tie has been deprecated.  Its functionality is supplied by the Boost
 | 
			
		||||
Tuples Library.]</h3>
 | 
			
		||||
<PRE>
 | 
			
		||||
template <class A, class B>
 | 
			
		||||
tied<A,B> tie(A& a, B& b);
 | 
			
		||||
@@ -64,7 +66,7 @@ pair of iterators is assigned to the iterator variables <TT>i</TT> and
 | 
			
		||||
 | 
			
		||||
<P>
 | 
			
		||||
Here is another example that uses <TT>tie()</TT> for handling operations with <a
 | 
			
		||||
href="http://www.sgi.com/Technology/STL/set.html"><TT>std::set</TT></a>.
 | 
			
		||||
href="http://www.sgi.com/tech/stl/set.html"><TT>std::set</TT></a>.
 | 
			
		||||
 | 
			
		||||
<P>
 | 
			
		||||
<PRE>
 | 
			
		||||
@@ -124,7 +126,7 @@ The output is:
 | 
			
		||||
<TABLE>
 | 
			
		||||
<TR valign=top>
 | 
			
		||||
<TD nowrap>Copyright © 2000</TD><TD>
 | 
			
		||||
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>,
 | 
			
		||||
<a HREF="../../people/jeremy_siek.htm">Jeremy Siek</a>,
 | 
			
		||||
Univ.of Notre Dame (<A
 | 
			
		||||
HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)<br>
 | 
			
		||||
<A HREF=http://www.lsc.nd.edu/~llee1>Lie-Quan Lee</A>, Univ.of Notre Dame (<A HREF="mailto:llee1@lsc.nd.edu">llee1@lsc.nd.edu</A>)<br>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										223
									
								
								transform_iterator.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								transform_iterator.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,223 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
 | 
			
		||||
<meta name="ProgId" content="FrontPage.Editor.Document">
 | 
			
		||||
<title>Transform Iterator Adaptor Documentation</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
 | 
			
		||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
 | 
			
		||||
align="center" width="277" height="86">
 | 
			
		||||
 | 
			
		||||
<h1>Transform Iterator Adaptor</h1>
 | 
			
		||||
 | 
			
		||||
Defined in header
 | 
			
		||||
<a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
The transform iterator adaptor augments an iterator by applying some
 | 
			
		||||
function object to the result of dereferencing the iterator. Another
 | 
			
		||||
words, the <tt>operator*</tt> of the transform iterator first
 | 
			
		||||
dereferences the base iterator, passes the result of this to the
 | 
			
		||||
function object, and then returns the result. The following
 | 
			
		||||
<b>pseudo-code</b> shows the basic idea:
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
  value_type transform_iterator::operator*() const {
 | 
			
		||||
    return this->f(*this->base_iterator);
 | 
			
		||||
  }
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
All of the other operators of the transform iterator behave in the
 | 
			
		||||
same fashion as those of the base iterator.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h2>Synopsis</h2>
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
namespace boost {
 | 
			
		||||
  template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator>
 | 
			
		||||
  class transform_iterator_generator;
 | 
			
		||||
 | 
			
		||||
  template <class <a href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>, class BaseIterator>
 | 
			
		||||
  typename transform_iterator_generator<AdaptableUnaryFunction,Iterator>::type
 | 
			
		||||
  make_transform_iterator(BaseIterator base, const AdaptableUnaryFunction& f = AdaptableUnaryFunction());
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
<h2><a name="transform_iterator_generator">The Transform Iterator Type
 | 
			
		||||
Generator</a></h2>
 | 
			
		||||
 | 
			
		||||
The class <tt>transform_iterator_generator</tt> is a helper class whose
 | 
			
		||||
purpose is to construct a transform iterator type.  The template
 | 
			
		||||
parameters for this class are the <tt>AdaptableUnaryFunction</tt> function object
 | 
			
		||||
type and the <tt>BaseIterator</tt> type that is being wrapped.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
template <class AdaptableUnaryFunction, class Iterator>
 | 
			
		||||
class transform_iterator_generator
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    typedef <a href="./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...> type;
 | 
			
		||||
};
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<h3>Example</h3>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
The following is an example of how to use the
 | 
			
		||||
<tt>transform_iterator_generator</tt> class to iterate through a range
 | 
			
		||||
of numbers, multiplying each of them by 2 when they are dereferenced.
 | 
			
		||||
The <tt>boost::binder1st</tt> class is used instead of the standard
 | 
			
		||||
one because tranform iterator requires the function object to be
 | 
			
		||||
Default Constructible.
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
<PRE>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
// definition of class boost::binder1st and function boost::bind1st() ...
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
 | 
			
		||||
 | 
			
		||||
  typedef boost::binder1st< std::multiplies<int> > Function;
 | 
			
		||||
  typedef boost::transform_iterator_generator<Function, int*>::type doubling_iterator;
 | 
			
		||||
 | 
			
		||||
  doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)),
 | 
			
		||||
    i_end(x + sizeof(x)/sizeof(int), boost::bind1st(std::multiplies<int>(), 2));
 | 
			
		||||
 | 
			
		||||
  std::cout << "multiplying the array by 2:" << std::endl;
 | 
			
		||||
  while (i != i_end)
 | 
			
		||||
    std::cout << *i++ << " ";
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // to be continued...
 | 
			
		||||
</PRE>
 | 
			
		||||
The output from this part is:
 | 
			
		||||
<pre>
 | 
			
		||||
2 4 6 8 10 12 14 16
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<h3>Template Parameters</h3>
 | 
			
		||||
 | 
			
		||||
<Table border>
 | 
			
		||||
<TR>
 | 
			
		||||
<TH>Parameter</TH><TH>Description</TH>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html"><tt>AdaptableUnaryFunction</tt></a></TD>
 | 
			
		||||
<TD>The function object that transforms each element in the iterator
 | 
			
		||||
range.  The <tt>argument_type</tt> of the function object must match
 | 
			
		||||
the value type of the base iterator.  The <tt>result_type</tt> of the
 | 
			
		||||
function object will be the resulting iterator's
 | 
			
		||||
<tt>value_type</tt>. If you want the resulting iterator to behave as
 | 
			
		||||
an iterator, the result of the function should be solely a function of
 | 
			
		||||
its argument. Also, the function object must be <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/DefaultConstructible.html"> Default
 | 
			
		||||
Constructible</a> (which many of the standard function objects are not).</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD><tt>BaseIterator</tt></TD>
 | 
			
		||||
<TD>The iterator type being wrapped. This type must at least be a model
 | 
			
		||||
 of the <a href="http://www.sgi.com/tech/stl/InputIterator">InputIterator</a> concept.</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
</Table>
 | 
			
		||||
 | 
			
		||||
<h3>Model of</h3>
 | 
			
		||||
 | 
			
		||||
The transform iterator adaptor (the type
 | 
			
		||||
<tt>transform_iterator_generator<...>::type</tt>) is a model of <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a><a href="#1">[1]</a>.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Members</h3>
 | 
			
		||||
 | 
			
		||||
The transform iterator type implements the member functions and
 | 
			
		||||
operators required of the <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterator</a>
 | 
			
		||||
concept, except that the <tt>reference</tt> type is the same as the <tt>value_type</tt>
 | 
			
		||||
so <tt>operator*()</tt> returns by-value. In addition it has the following constructor:
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
transform_iterator_generator::type(const BaseIterator& it,
 | 
			
		||||
                                   const AdaptableUnaryFunction& f = AdaptableUnaryFunction())
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h2><a name="make_transform_iterator">The Transform Iterator Object Generator</a></h2>
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
template <class AdaptableUnaryFunction, class BaseIterator>
 | 
			
		||||
typename transform_iterator_generator<AdaptableUnaryFunction,BaseIterator>::type
 | 
			
		||||
make_transform_iterator(BaseIterator base,
 | 
			
		||||
                        const AdaptableUnaryFunction& f = AdaptableUnaryFunction());
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
This function provides a convenient way to create transform iterators.
 | 
			
		||||
 | 
			
		||||
<h3>Example</h3>
 | 
			
		||||
 | 
			
		||||
Continuing from the previous example, we use the <tt>make_transform_iterator()</tt>
 | 
			
		||||
function to add four to each element of the array.
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
  std::cout << "adding 4 to each element in the array:" << std::endl;
 | 
			
		||||
 | 
			
		||||
  std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)),
 | 
			
		||||
	    boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
 | 
			
		||||
	    std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
</pre>
 | 
			
		||||
The output from this part is:
 | 
			
		||||
<pre>
 | 
			
		||||
5 6 7 8 9 10 11 12
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<h3>Notes</h3>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<a name="1">[1]</a> If the base iterator is a model of <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterator</a>
 | 
			
		||||
then the transform iterator will also suppport most of the
 | 
			
		||||
functionality required by the Random Access Iterator concept. However, a
 | 
			
		||||
transform iterator can never completely satisfy the requirements for
 | 
			
		||||
<a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterator</a>
 | 
			
		||||
(or of any concepts that refine Forward Iterator, which includes
 | 
			
		||||
Random Access Iterator and Bidirectional Iterator) since the <tt>operator*</tt> of the transform
 | 
			
		||||
iterator always returns by-value.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->17 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14763" --></p>
 | 
			
		||||
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
without express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										76
									
								
								transform_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								transform_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
 | 
			
		||||
// What a bummer. We can't use std::binder1st with transform iterator
 | 
			
		||||
// because it does not have a default constructor. Here's a version
 | 
			
		||||
// that does.
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
  template <class Operation> 
 | 
			
		||||
  class binder1st
 | 
			
		||||
    : public std::unary_function<typename Operation::second_argument_type,
 | 
			
		||||
			         typename Operation::result_type> {
 | 
			
		||||
  protected:
 | 
			
		||||
    Operation op;
 | 
			
		||||
    typename Operation::first_argument_type value;
 | 
			
		||||
  public:
 | 
			
		||||
    binder1st() { } // this had to be added!
 | 
			
		||||
    binder1st(const Operation& x,
 | 
			
		||||
	      const typename Operation::first_argument_type& y)
 | 
			
		||||
	: op(x), value(y) {}
 | 
			
		||||
    typename Operation::result_type
 | 
			
		||||
    operator()(const typename Operation::second_argument_type& x) const {
 | 
			
		||||
      return op(value, x); 
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template <class Operation, class T>
 | 
			
		||||
  inline binder1st<Operation> bind1st(const Operation& op, const T& x) {
 | 
			
		||||
    typedef typename Operation::first_argument_type arg1_type;
 | 
			
		||||
    return binder1st<Operation>(op, arg1_type(x));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  // This is a simple example of using the transform_iterators class to
 | 
			
		||||
  // generate iterators that multiply the value returned by dereferencing
 | 
			
		||||
  // the iterator. In this case we are multiplying by 2.
 | 
			
		||||
  // Would be cooler to use lambda library in this example.
 | 
			
		||||
 | 
			
		||||
  int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
 | 
			
		||||
  const int N = sizeof(x)/sizeof(int);
 | 
			
		||||
 | 
			
		||||
  typedef boost::binder1st< std::multiplies<int> > Function;
 | 
			
		||||
  typedef boost::transform_iterator_generator<Function, int*>::type doubling_iterator;
 | 
			
		||||
 | 
			
		||||
  doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)),
 | 
			
		||||
    i_end(x + N, boost::bind1st(std::multiplies<int>(), 2));
 | 
			
		||||
 | 
			
		||||
  std::cout << "multiplying the array by 2:" << std::endl;
 | 
			
		||||
  while (i != i_end)
 | 
			
		||||
    std::cout << *i++ << " ";
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  std::cout << "adding 4 to each element in the array:" << std::endl;
 | 
			
		||||
 | 
			
		||||
  std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)),
 | 
			
		||||
	    boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
 | 
			
		||||
	    std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										620
									
								
								type_traits.htm
									
									
									
									
									
								
							
							
						
						
									
										620
									
								
								type_traits.htm
									
									
									
									
									
								
							@@ -1,620 +0,0 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type"
 | 
			
		||||
content="text/html; charset=iso-8859-1">
 | 
			
		||||
<meta name="Template"
 | 
			
		||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
 | 
			
		||||
<title>Type Traits</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" link="#0000FF" vlink="#800080">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../c++boost.gif" width="276" height="86">Header
 | 
			
		||||
<<a href="../../boost/detail/type_traits.hpp">boost/type_traits.hpp</a>></h1>
 | 
			
		||||
 | 
			
		||||
<p>The contents of <boost/type_traits.hpp> are declared in
 | 
			
		||||
namespace boost.</p>
 | 
			
		||||
 | 
			
		||||
<p>The file <<a href="../../boost/detail/type_traits.hpp">boost/type_traits.hpp</a>>
 | 
			
		||||
contains various template classes that describe the fundamental
 | 
			
		||||
properties of a type; each class represents a single type
 | 
			
		||||
property or a single type transformation. This documentation is
 | 
			
		||||
divided up into the following sections:</p>
 | 
			
		||||
 | 
			
		||||
<pre><a href="#fop">Fundamental type operations</a>
 | 
			
		||||
<a href="#fp">Fundamental type properties</a>
 | 
			
		||||
   <a href="#misc">Miscellaneous</a>
 | 
			
		||||
<code>   </code><a href="#cv">cv-Qualifiers</a>
 | 
			
		||||
<code>   </code><a href="#ft">Fundamental Types</a>
 | 
			
		||||
<code>   </code><a href="#ct">Compound Types</a>
 | 
			
		||||
<code>   </code><a href="#ot">Object/Scalar Types</a>
 | 
			
		||||
<a href="#cs">Compiler Support Information</a>
 | 
			
		||||
<a href="#ec">Example Code</a></pre>
 | 
			
		||||
 | 
			
		||||
<h2><a name="fop"></a>Fundamental type operations</h2>
 | 
			
		||||
 | 
			
		||||
<p>Usage: "class_name<T>::type" performs
 | 
			
		||||
indicated transformation on type T.</p>
 | 
			
		||||
 | 
			
		||||
<table border="1" cellpadding="7" cellspacing="1" width="100%">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><p align="center">Expression.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="45%"><p align="center">Description.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">Compiler.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>remove_volatile<T>::type</code></td>
 | 
			
		||||
        <td valign="top" width="45%">Creates a type the same as T
 | 
			
		||||
        but with any top level volatile qualifier removed. For
 | 
			
		||||
        example "volatile int" would become "int".</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">P</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>remove_const<T>::type</code></td>
 | 
			
		||||
        <td valign="top" width="45%">Creates a type the same as T
 | 
			
		||||
        but with any top level const qualifier removed. For
 | 
			
		||||
        example "const int" would become "int".</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">P</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>remove_cv<T>::type</code></td>
 | 
			
		||||
        <td valign="top" width="45%">Creates a type the same as T
 | 
			
		||||
        but with any top level cv-qualifiers removed. For example
 | 
			
		||||
        "const int" would become "int", and
 | 
			
		||||
        "volatile double" would become "double".</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">P</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>remove_reference<T>::type</code></td>
 | 
			
		||||
        <td valign="top" width="45%">If T is a reference type
 | 
			
		||||
        then removes the reference, otherwise leaves T unchanged.
 | 
			
		||||
        For example "int&" becomes "int"
 | 
			
		||||
        but "int*" remains unchanged.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">P</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>add_reference<T>::type</code></td>
 | 
			
		||||
        <td valign="top" width="45%">If T is a reference type
 | 
			
		||||
        then leaves T unchanged, otherwise converts T to a
 | 
			
		||||
        reference type. For example "int&" remains
 | 
			
		||||
        unchanged, but "double" becomes "double&".</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">P</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>remove_bounds<T>::type</code></td>
 | 
			
		||||
        <td valign="top" width="45%">If T is an array type then
 | 
			
		||||
        removes the top level array qualifier from T, otherwise
 | 
			
		||||
        leaves T unchanged. For example "int[2][3]"
 | 
			
		||||
        becomes "int[3]".</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">P</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<h2><a name="fp"></a>Fundamental type properties</h2>
 | 
			
		||||
 | 
			
		||||
<p>Usage: "class_name<T>::value" is true if
 | 
			
		||||
indicated property is true, false otherwise. (Note that class_name<T>::value
 | 
			
		||||
is always defined as a compile time constant).</p>
 | 
			
		||||
 | 
			
		||||
<h3><a name="misc"></a>Miscellaneous</h3>
 | 
			
		||||
 | 
			
		||||
<table border="1" cellspacing="1" width="100%">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td width="37%"><p align="center">Expression</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td width="36%"><p align="center">Description</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td width="27%"><p align="center">Compiler</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td width="37%"><div align="center"><center><pre><code>is_same<T,U>::value</code></pre>
 | 
			
		||||
        </center></div></td>
 | 
			
		||||
        <td width="36%"><p align="center">True if T and U are the
 | 
			
		||||
        same type.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td width="27%">  </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td width="37%"><div align="center"><center><pre>is_convertible<T,U>::value</pre>
 | 
			
		||||
        </center></div></td>
 | 
			
		||||
        <td width="36%"><p align="center">True if type T is
 | 
			
		||||
        convertible to type U.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td width="27%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td width="37%"><div align="center"><center><pre>alignment_of<T>::value</pre>
 | 
			
		||||
        </center></div></td>
 | 
			
		||||
        <td width="36%"><p align="center">An integral value
 | 
			
		||||
        representing the minimum alignment requirements of type T
 | 
			
		||||
        (strictly speaking defines a multiple of the type's
 | 
			
		||||
        alignment requirement; for all compilers tested so far
 | 
			
		||||
        however it does return the actual alignment).</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td width="27%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<h3><a name="cv"></a>cv-Qualifiers</h3>
 | 
			
		||||
 | 
			
		||||
<p>The following classes determine what cv-qualifiers are present
 | 
			
		||||
on a type (see 3.93).</p>
 | 
			
		||||
 | 
			
		||||
<table border="1" cellpadding="7" cellspacing="1" width="100%">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="37%"><p align="center">Expression.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="37%"><p align="center">Description.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="27%"><p align="center">Compiler.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="37%"><code>is_const<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="37%">True if type T is top-level
 | 
			
		||||
        const qualified.</td>
 | 
			
		||||
        <td valign="top" width="27%">  </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="37%"><code>is_volatile<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="37%">True if type T is top-level
 | 
			
		||||
        volatile qualified.</td>
 | 
			
		||||
        <td valign="top" width="27%">  </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<h3><a name="ft"></a>Fundamental Types</h3>
 | 
			
		||||
 | 
			
		||||
<p>The following will only ever be true for cv-unqualified types;
 | 
			
		||||
these are closely based on the section 3.9 of the C++ Standard.</p>
 | 
			
		||||
 | 
			
		||||
<table border="1" cellpadding="7" cellspacing="1" width="100%">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><p align="center">Expression.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="45%"><p align="center">Description.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">Compiler.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_void<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True only if T is void.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_standard_unsigned_integral<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True only if T is one of the
 | 
			
		||||
        standard unsigned integral types (3.9.1 p3) - unsigned
 | 
			
		||||
        char, unsigned short, unsigned int, and unsigned long.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_standard_signed_integral<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True only if T is one of the
 | 
			
		||||
        standard signed integral types (3.9.1 p2) - signed char,
 | 
			
		||||
        short, int, and long.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_standard_integral<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is a standard
 | 
			
		||||
        integral type(3.9.1 p7) - T is either char, wchar_t, bool
 | 
			
		||||
        or either is_standard_signed_integral<T>::value or
 | 
			
		||||
        is_standard_integral<T>::value is true.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_standard_float<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is one of the
 | 
			
		||||
        standard floating point types(3.9.1 p8) - float, double
 | 
			
		||||
        or long double.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_standard_arithmetic<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is a standard
 | 
			
		||||
        arithmetic type(3.9.1 p8) - implies is_standard_integral
 | 
			
		||||
        or is_standard_float is true.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_standard_fundamental<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is a standard
 | 
			
		||||
        arithmetic type or if T is void.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_extension_unsigned_integral<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True for compiler specific
 | 
			
		||||
        unsigned integral types.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_extension_signed_integral<T>>:value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True for compiler specific
 | 
			
		||||
        signed integral types.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_extension_integral<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if either is_extension_unsigned_integral<T>::value
 | 
			
		||||
        or is_extension_signed_integral<T>::value is true.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_extension_float<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True for compiler specific
 | 
			
		||||
        floating point types.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_extension_arithmetic<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if either is_extension_integral<T>::value
 | 
			
		||||
        or is_extension_float<T>::value are true.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code> is_extension_fundamental<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if either is_extension_arithmetic<T>::value
 | 
			
		||||
        or is_void<T>::value are true.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code> is_unsigned_integral<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if either is_standard_unsigned_integral<T>::value
 | 
			
		||||
        or is_extention_unsigned_integral<T>::value are
 | 
			
		||||
        true.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_signed_integral<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if either is_standard_signed_integral<T>::value
 | 
			
		||||
        or is_extention_signed_integral<T>>::value are
 | 
			
		||||
        true.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_integral<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if either is_standard_integral<T>::value
 | 
			
		||||
        or is_extention_integral<T>::value are true.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_float<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if either is_standard_float<T>::value
 | 
			
		||||
        or is_extention_float<T>::value are true.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_arithmetic<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if either is_integral<T>::value
 | 
			
		||||
        or is_float<T>::value are true.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_fundamental<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if either is_arithmetic<T>::value
 | 
			
		||||
        or is_void<T>::value are true.</td>
 | 
			
		||||
        <td valign="top" width="33%"> </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<h3><a name="ct"></a>Compound Types</h3>
 | 
			
		||||
 | 
			
		||||
<p>The following will only ever be true for cv-unqualified types,
 | 
			
		||||
as defined by the Standard. </p>
 | 
			
		||||
 | 
			
		||||
<table border="1" cellpadding="7" cellspacing="1" width="100%">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><p align="center">Expression</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="45%"><p align="center">Description</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">Compiler</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_array<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is an array type.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">P</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_pointer<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is a regular
 | 
			
		||||
        pointer type - including function pointers - but
 | 
			
		||||
        excluding pointers to member functions (3.9.2 p1 and 8.3.1).</td>
 | 
			
		||||
        <td valign="top" width="33%">  </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_member_pointer<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is a pointer to a
 | 
			
		||||
        non-static class member (3.9.2 p1 and 8.3.1).</td>
 | 
			
		||||
        <td valign="top" width="33%">  </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_reference<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is a reference
 | 
			
		||||
        type (3.9.2 p1 and 8.3.2).</td>
 | 
			
		||||
        <td valign="top" width="33%">  </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_class<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is a class or
 | 
			
		||||
        struct type.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">PD</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_union<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is a union type.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">C</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_enum<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is an enumerator
 | 
			
		||||
        type.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">C</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_compound<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is any of the
 | 
			
		||||
        above compound types.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">PD</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<h3><a name="ot"></a>Object/Scalar Types</h3>
 | 
			
		||||
 | 
			
		||||
<p>The following ignore any top level cv-qualifiers: if <code>class_name<T>::value</code>
 | 
			
		||||
is true then <code>class_name<cv-qualified-T>::value</code>
 | 
			
		||||
will also be true.</p>
 | 
			
		||||
 | 
			
		||||
<table border="1" cellpadding="7" cellspacing="1" width="100%">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><p align="center">Expression</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="45%"><p align="center">Description</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">Compiler</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_object<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is not a reference
 | 
			
		||||
        type, or a (possibly cv-qualified) void type.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">P</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_standard_scalar<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is a standard
 | 
			
		||||
        arithmetic type, an enumerated type, a pointer or a
 | 
			
		||||
        member pointer.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">PD</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_extension_scalar<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is an extentions
 | 
			
		||||
        arithmetic type, an enumerated type, a pointer or a
 | 
			
		||||
        member pointer.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">PD</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_scalar<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is an arithmetic
 | 
			
		||||
        type, an enumerated type, a pointer or a member pointer.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">PD</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_POD<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is a "Plain
 | 
			
		||||
        Old Data" type (see 3.9 p2&p3). Note that
 | 
			
		||||
        although this requires compiler support to be correct in
 | 
			
		||||
        all cases, if T is a scalar or an array of scalars then
 | 
			
		||||
        we can correctly define T as a POD.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">PC</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>is_empty<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T is an empty struct
 | 
			
		||||
        or class. If the compiler implements the "zero sized
 | 
			
		||||
        empty base classes" optimisation, then is_empty will
 | 
			
		||||
        correctly guess whether T is empty. Relies upon is_class
 | 
			
		||||
        to determine whether T is a class type. Screens out enum
 | 
			
		||||
        types by using is_convertible<T,int>, this means
 | 
			
		||||
        that empty classes that overload operator int(), will not
 | 
			
		||||
        be classified as empty.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">PCD</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>has_trivial_constructor<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T has a trivial
 | 
			
		||||
        default constructor - that is T() is equivalent to memset.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">PC</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>has_trivial_copy<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T has a trivial copy
 | 
			
		||||
        constructor - that is T(const T&) is equivalent to
 | 
			
		||||
        memcpy.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">PC</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>has_trivial_assign<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T has a trivial
 | 
			
		||||
        assignment operator - that is if T::operator=(const T&)
 | 
			
		||||
        is equivalent to memcpy.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">PC</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="45%"><code>has_trivial_destructor<T>::value</code></td>
 | 
			
		||||
        <td valign="top" width="45%">True if T has a trivial
 | 
			
		||||
        destructor - that is if T::~T() has no effect.</td>
 | 
			
		||||
        <td valign="top" width="33%"><p align="center">PC</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<h2><a name="cs"></a>Compiler Support Information</h2>
 | 
			
		||||
 | 
			
		||||
<p>The legends used in the tables above have the following
 | 
			
		||||
meanings:</p>
 | 
			
		||||
 | 
			
		||||
<table border="0" cellpadding="7" cellspacing="0" width="480">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="50%"><p align="center">P</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="90%">Denotes that the class
 | 
			
		||||
        requires support for partial specialisation of class
 | 
			
		||||
        templates to work correctly.</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="50%"><p align="center">C</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="90%">Denotes that direct compiler
 | 
			
		||||
        support for that traits class is required.</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="50%"><p align="center">D</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="90%">Denotes that the traits
 | 
			
		||||
        class is dependent upon a class that requires direct
 | 
			
		||||
        compiler support.</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<p>For those classes that are marked with a D or C, if compiler
 | 
			
		||||
support is not provided, this type trait may return "false"
 | 
			
		||||
when the correct value is actually "true". The single
 | 
			
		||||
exception to this rule is "is_class", which attempts to
 | 
			
		||||
guess whether or not T is really a class, and may return "true"
 | 
			
		||||
when the correct value is actually "false". This can
 | 
			
		||||
happen if: T is a union, T is an enum, or T is a compiler-supplied
 | 
			
		||||
scalar type that is not specialised for in these type traits.</p>
 | 
			
		||||
 | 
			
		||||
<p><i>If there is no compiler support</i>, to ensure that these
 | 
			
		||||
traits <i>always</i> return the correct values, specialise 'is_enum'
 | 
			
		||||
for each user-defined enumeration type, 'is_union' for each user-defined
 | 
			
		||||
union type, 'is_empty' for each user-defined empty composite type,
 | 
			
		||||
and 'is_POD' for each user-defined POD type. The 'has_*' traits
 | 
			
		||||
should also be specialized if the user-defined type has those
 | 
			
		||||
traits and is <i>not</i> a POD.</p>
 | 
			
		||||
 | 
			
		||||
<p>The following rules are automatically enforced:</p>
 | 
			
		||||
 | 
			
		||||
<p>is_enum implies is_POD</p>
 | 
			
		||||
 | 
			
		||||
<p>is_POD implies has_*</p>
 | 
			
		||||
 | 
			
		||||
<p>This means, for example, if you have an empty POD-struct, just
 | 
			
		||||
specialize is_empty and is_POD, which will cause all the has_* to
 | 
			
		||||
also return true.</p>
 | 
			
		||||
 | 
			
		||||
<h2><a name="ec"></a>Example code</h2>
 | 
			
		||||
 | 
			
		||||
<p>Type-traits comes with two sample programs: <a
 | 
			
		||||
href="type_traits_test.cpp">type_traits_test.cpp</a> tests the
 | 
			
		||||
type traits classes - mostly this is a test of your compiler's
 | 
			
		||||
support for the concepts used in the type traits implementation,
 | 
			
		||||
while <a href="algo_opt_examples.cpp">algo_opt_examples.cpp</a>
 | 
			
		||||
uses the type traits classes to "optimise" some
 | 
			
		||||
familiar standard library algorithms.</p>
 | 
			
		||||
 | 
			
		||||
<p>There are four algorithm examples in algo_opt_examples.cpp:</p>
 | 
			
		||||
 | 
			
		||||
<table border="0" cellpadding="7" cellspacing="0" width="638">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="50%"><pre>opt::copy</pre>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="50%">If the copy operation can be
 | 
			
		||||
        performed using memcpy then does so, otherwise uses a
 | 
			
		||||
        regular element by element copy (<i>c.f.</i> std::copy).</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="50%"><pre>opt::fill</pre>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="50%">If the fill operation can be
 | 
			
		||||
        performed by memset, then does so, otherwise uses a
 | 
			
		||||
        regular element by element assign. Also uses call_traits
 | 
			
		||||
        to optimise how the parameters can be passed (<i>c.f.</i>
 | 
			
		||||
        std::fill).</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="50%"><pre>opt::destroy_array</pre>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="50%">If the type in the array has
 | 
			
		||||
        a trivial destructor then does nothing, otherwise calls
 | 
			
		||||
        destructors for all elements in the array - this
 | 
			
		||||
        algorithm is the reverse of std::uninitialized_copy / std::uninitialized_fill.</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="50%"><pre>opt::iter_swap</pre>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="50%">Determines whether the
 | 
			
		||||
        iterator is a proxy-iterator: if it is then does a "slow
 | 
			
		||||
        and safe" swap, otherwise calls std::swap on the
 | 
			
		||||
        assumption that std::swap may be specialised for the
 | 
			
		||||
        iterated type.</td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
<p>Revised 01 September 2000</p>
 | 
			
		||||
 | 
			
		||||
<p><EFBFBD> Copyright boost.org 2000. Permission to copy, use, modify,
 | 
			
		||||
sell and distribute this document is granted provided this
 | 
			
		||||
copyright notice appears in all copies. This document is provided
 | 
			
		||||
"as is" without express or implied warranty, and with
 | 
			
		||||
no claim as to its suitability for any purpose.</p>
 | 
			
		||||
 | 
			
		||||
<p>Based on contributions by Steve Cleary, Beman Dawes, Howard
 | 
			
		||||
Hinnant and John Maddock.</p>
 | 
			
		||||
 | 
			
		||||
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
 | 
			
		||||
Maddock</a>, the latest version of this file can be found at <a
 | 
			
		||||
href="http://www.boost.org/">www.boost.org</a>, and the boost
 | 
			
		||||
discussion list at <a href="http://www.egroups.com/list/boost">www.egroups.com/list/boost</a>.</p>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
@@ -1,644 +0,0 @@
 | 
			
		||||
//  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
 | 
			
		||||
//  Permission to copy, use, modify, sell and
 | 
			
		||||
//  distribute this software is granted provided this copyright notice appears
 | 
			
		||||
//  in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
//  warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
// standalone test program for <boost/type_traits.hpp>
 | 
			
		||||
 | 
			
		||||
/* Release notes:
 | 
			
		||||
   31st July 2000:
 | 
			
		||||
      Added extra tests for is_empty, is_convertible, alignment_of.
 | 
			
		||||
   23rd July 2000:
 | 
			
		||||
      Removed all call_traits tests to call_traits_test.cpp
 | 
			
		||||
      Removed all compressed_pair tests to compressed_pair_tests.cpp
 | 
			
		||||
      Improved tests macros
 | 
			
		||||
      Tidied up specialistions of type_types classes for test cases.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <typeinfo>
 | 
			
		||||
 | 
			
		||||
#include <boost/type_traits.hpp>
 | 
			
		||||
#include <boost/utility.hpp>
 | 
			
		||||
#include "type_traits_test.hpp"
 | 
			
		||||
 | 
			
		||||
using namespace boost;
 | 
			
		||||
 | 
			
		||||
// Since there is no compiler support, we should specialize:
 | 
			
		||||
//  is_enum for all enumerations (is_enum implies is_POD)
 | 
			
		||||
//  is_union for all unions
 | 
			
		||||
//  is_empty for all empty composites
 | 
			
		||||
//  is_POD for all PODs (except enums) (is_POD implies has_*)
 | 
			
		||||
//  has_* for any UDT that has that trait and is not POD
 | 
			
		||||
 | 
			
		||||
enum enum_UDT{ one, two, three };
 | 
			
		||||
struct UDT
 | 
			
		||||
{
 | 
			
		||||
   UDT();
 | 
			
		||||
   ~UDT();
 | 
			
		||||
   UDT(const UDT&);
 | 
			
		||||
   UDT& operator=(const UDT&);
 | 
			
		||||
   int i;
 | 
			
		||||
 | 
			
		||||
   void f1();
 | 
			
		||||
   int f2();
 | 
			
		||||
   int f3(int);
 | 
			
		||||
   int f4(int, float);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct POD_UDT { int x; };
 | 
			
		||||
struct empty_UDT{ ~empty_UDT(){}; };
 | 
			
		||||
struct empty_POD_UDT{};
 | 
			
		||||
union union_UDT
 | 
			
		||||
{
 | 
			
		||||
  int x;
 | 
			
		||||
  double y;
 | 
			
		||||
  ~union_UDT();
 | 
			
		||||
};
 | 
			
		||||
union POD_union_UDT
 | 
			
		||||
{
 | 
			
		||||
  int x;
 | 
			
		||||
  double y;
 | 
			
		||||
};
 | 
			
		||||
union empty_union_UDT
 | 
			
		||||
{
 | 
			
		||||
  ~empty_union_UDT();
 | 
			
		||||
};
 | 
			
		||||
union empty_POD_union_UDT{};
 | 
			
		||||
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
 | 
			
		||||
namespace boost {
 | 
			
		||||
template <> struct is_enum<enum_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct is_POD<POD_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
// this type is not POD, so we have to specialize the has_* individually
 | 
			
		||||
template <> struct has_trivial_constructor<empty_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct has_trivial_copy<empty_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct has_trivial_assign<empty_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct is_POD<empty_POD_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct is_union<union_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct is_union<POD_union_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct is_POD<POD_union_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct is_union<empty_union_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
// this type is not POD, so we have to specialize the has_* individually
 | 
			
		||||
template <> struct has_trivial_constructor<empty_union_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct has_trivial_copy<empty_union_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct has_trivial_assign<empty_union_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct is_union<empty_POD_union_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct is_POD<empty_POD_union_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
namespace boost {
 | 
			
		||||
template <> struct is_enum<enum_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct is_POD<POD_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
// this type is not POD, so we have to specialize the has_* individually
 | 
			
		||||
template <> struct has_trivial_constructor<empty_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct has_trivial_copy<empty_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct has_trivial_assign<empty_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct is_POD<empty_POD_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct is_union<union_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct is_union<POD_union_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct is_POD<POD_union_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct is_union<empty_union_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
// this type is not POD, so we have to specialize the has_* individually
 | 
			
		||||
template <> struct has_trivial_constructor<empty_union_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct has_trivial_copy<empty_union_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct has_trivial_assign<empty_union_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct is_union<empty_POD_union_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct is_POD<empty_POD_union_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
class Base { };
 | 
			
		||||
 | 
			
		||||
class Deriverd : public Base { };
 | 
			
		||||
 | 
			
		||||
class NonDerived { };
 | 
			
		||||
 | 
			
		||||
enum enum1
 | 
			
		||||
{
 | 
			
		||||
   one_,two_
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum enum2
 | 
			
		||||
{
 | 
			
		||||
   three_,four_
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct VB
 | 
			
		||||
{
 | 
			
		||||
   virtual ~VB(){};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct VD : VB
 | 
			
		||||
{
 | 
			
		||||
   ~VD(){};
 | 
			
		||||
};
 | 
			
		||||
//
 | 
			
		||||
// struct non_pointer:
 | 
			
		||||
// used to verify that is_pointer does not return
 | 
			
		||||
// true for class types that implement operator void*()
 | 
			
		||||
//
 | 
			
		||||
struct non_pointer
 | 
			
		||||
{
 | 
			
		||||
   operator void*(){return this;}
 | 
			
		||||
};
 | 
			
		||||
//
 | 
			
		||||
// struct non_empty:
 | 
			
		||||
// used to verify that is_empty does not emit
 | 
			
		||||
// spurious warnings or errors.
 | 
			
		||||
//
 | 
			
		||||
struct non_empty : boost::noncopyable
 | 
			
		||||
{
 | 
			
		||||
   int i;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Steve: All comments that I (Steve Cleary) have added below are prefixed with
 | 
			
		||||
//  "Steve:"  The failures that BCB4 has on the tests are due to Borland's
 | 
			
		||||
//  not considering cv-qual's as a part of the type -- they are considered
 | 
			
		||||
//  compiler hints only.  These failures should be fixed before long.
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
   std::cout << "Checking type operations..." << std::endl << std::endl;
 | 
			
		||||
 | 
			
		||||
   // cv-qualifiers applied to reference types should have no effect
 | 
			
		||||
   // declare these here for later use with is_reference and remove_reference:
 | 
			
		||||
   typedef int& r_type;
 | 
			
		||||
   typedef const r_type cr_type;
 | 
			
		||||
 | 
			
		||||
   type_test(int, remove_reference<int>::type)
 | 
			
		||||
   type_test(const int, remove_reference<const int>::type)
 | 
			
		||||
   type_test(int, remove_reference<int&>::type)
 | 
			
		||||
   type_test(const int, remove_reference<const int&>::type)
 | 
			
		||||
   type_test(volatile int, remove_reference<volatile int&>::type)
 | 
			
		||||
   type_test(int, remove_reference<cr_type>::type)
 | 
			
		||||
 | 
			
		||||
   type_test(int, remove_const<const int>::type)
 | 
			
		||||
   // Steve: fails on BCB4
 | 
			
		||||
   type_test(volatile int, remove_const<volatile int>::type)
 | 
			
		||||
   // Steve: fails on BCB4
 | 
			
		||||
   type_test(volatile int, remove_const<const volatile int>::type)
 | 
			
		||||
   type_test(int, remove_const<int>::type)
 | 
			
		||||
   type_test(int*, remove_const<int* const>::type)
 | 
			
		||||
   type_test(int, remove_volatile<volatile int>::type)
 | 
			
		||||
   // Steve: fails on BCB4
 | 
			
		||||
   type_test(const int, remove_volatile<const int>::type)
 | 
			
		||||
   // Steve: fails on BCB4
 | 
			
		||||
   type_test(const int, remove_volatile<const volatile int>::type)
 | 
			
		||||
   type_test(int, remove_volatile<int>::type)
 | 
			
		||||
   type_test(int*, remove_volatile<int* volatile>::type)
 | 
			
		||||
   type_test(int, remove_cv<volatile int>::type)
 | 
			
		||||
   type_test(int, remove_cv<const int>::type)
 | 
			
		||||
   type_test(int, remove_cv<const volatile int>::type)
 | 
			
		||||
   type_test(int, remove_cv<int>::type)
 | 
			
		||||
   type_test(int*, remove_cv<int* volatile>::type)
 | 
			
		||||
   type_test(int*, remove_cv<int* const>::type)
 | 
			
		||||
   type_test(int*, remove_cv<int* const volatile>::type)
 | 
			
		||||
   type_test(const int *, remove_cv<const int * const>::type)
 | 
			
		||||
   type_test(int, remove_bounds<int>::type)
 | 
			
		||||
   type_test(int*, remove_bounds<int*>::type)
 | 
			
		||||
   type_test(int, remove_bounds<int[3]>::type)
 | 
			
		||||
   type_test(int[3], remove_bounds<int[2][3]>::type)
 | 
			
		||||
 | 
			
		||||
   std::cout << std::endl << "Checking type properties..." << std::endl << std::endl;
 | 
			
		||||
 | 
			
		||||
   value_test(true, (is_same<int, int>::value))
 | 
			
		||||
   value_test(false, (is_same<int, const int>::value))
 | 
			
		||||
   value_test(false, (is_same<int, int&>::value))
 | 
			
		||||
   value_test(false, (is_same<int*, const int*>::value))
 | 
			
		||||
   value_test(false, (is_same<int*, int*const>::value))
 | 
			
		||||
   value_test(false, (is_same<int, int[2]>::value))
 | 
			
		||||
   value_test(false, (is_same<int*, int[2]>::value))
 | 
			
		||||
   value_test(false, (is_same<int[4], int[2]>::value))
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_const<int>::value)
 | 
			
		||||
   value_test(true, is_const<const int>::value)
 | 
			
		||||
   value_test(false, is_const<volatile int>::value)
 | 
			
		||||
   value_test(true, is_const<const volatile int>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_volatile<int>::value)
 | 
			
		||||
   value_test(false, is_volatile<const int>::value)
 | 
			
		||||
   value_test(true, is_volatile<volatile int>::value)
 | 
			
		||||
   value_test(true, is_volatile<const volatile int>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(true, is_void<void>::value)
 | 
			
		||||
   // Steve: fails on BCB4
 | 
			
		||||
   // JM: but looks as though it should according to [3.9.3p1]?
 | 
			
		||||
   //value_test(false, is_void<const void>::value)
 | 
			
		||||
   value_test(false, is_void<int>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<UDT>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<void>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<bool>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<char>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<signed char>::value)
 | 
			
		||||
   value_test(true, is_standard_unsigned_integral<unsigned char>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<wchar_t>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<short>::value)
 | 
			
		||||
   value_test(true, is_standard_unsigned_integral<unsigned short>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<int>::value)
 | 
			
		||||
   value_test(true, is_standard_unsigned_integral<unsigned int>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<long>::value)
 | 
			
		||||
   value_test(true, is_standard_unsigned_integral<unsigned long>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<float>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<double>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<long double>::value)
 | 
			
		||||
   #ifdef ULLONG_MAX
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<long long>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<unsigned long long>::value)
 | 
			
		||||
   #endif
 | 
			
		||||
   #if defined(__BORLANDC__) || defined(_MSC_VER)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<__int64>::value)
 | 
			
		||||
   value_test(false, is_standard_unsigned_integral<unsigned __int64>::value)
 | 
			
		||||
   #endif
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_standard_signed_integral<UDT>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<void>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<bool>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<char>::value)
 | 
			
		||||
   value_test(true, is_standard_signed_integral<signed char>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<unsigned char>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<wchar_t>::value)
 | 
			
		||||
   value_test(true, is_standard_signed_integral<short>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<unsigned short>::value)
 | 
			
		||||
   value_test(true, is_standard_signed_integral<int>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<unsigned int>::value)
 | 
			
		||||
   value_test(true, is_standard_signed_integral<long>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<unsigned long>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<float>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<double>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<long double>::value)
 | 
			
		||||
   #ifdef ULLONG_MAX
 | 
			
		||||
   value_test(false, is_standard_signed_integral<long long>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<unsigned long long>::value)
 | 
			
		||||
   #endif
 | 
			
		||||
   #if defined(__BORLANDC__) || defined(_MSC_VER)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<__int64>::value)
 | 
			
		||||
   value_test(false, is_standard_signed_integral<unsigned __int64>::value)
 | 
			
		||||
   #endif
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_standard_arithmetic<UDT>::value)
 | 
			
		||||
   value_test(false, is_standard_arithmetic<void>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<bool>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<char>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<signed char>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<unsigned char>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<wchar_t>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<short>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<unsigned short>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<int>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<unsigned int>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<long>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<unsigned long>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<float>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<double>::value)
 | 
			
		||||
   value_test(true, is_standard_arithmetic<long double>::value)
 | 
			
		||||
   #ifdef ULLONG_MAX
 | 
			
		||||
   value_test(false, is_standard_arithmetic<long long>::value)
 | 
			
		||||
   value_test(false, is_standard_arithmetic<unsigned long long>::value)
 | 
			
		||||
   #endif
 | 
			
		||||
   #if defined(__BORLANDC__) || defined(_MSC_VER)
 | 
			
		||||
   value_test(false, is_standard_arithmetic<__int64>::value)
 | 
			
		||||
   value_test(false, is_standard_arithmetic<unsigned __int64>::value)
 | 
			
		||||
   #endif
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_standard_fundamental<UDT>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<void>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<bool>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<char>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<signed char>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<unsigned char>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<wchar_t>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<short>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<unsigned short>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<int>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<unsigned int>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<long>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<unsigned long>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<float>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<double>::value)
 | 
			
		||||
   value_test(true, is_standard_fundamental<long double>::value)
 | 
			
		||||
   #ifdef ULLONG_MAX
 | 
			
		||||
   value_test(false, is_standard_fundamental<long long>::value)
 | 
			
		||||
   value_test(false, is_standard_fundamental<unsigned long long>::value)
 | 
			
		||||
   #endif
 | 
			
		||||
   #if defined(__BORLANDC__) || defined(_MSC_VER)
 | 
			
		||||
   value_test(false, is_standard_fundamental<__int64>::value)
 | 
			
		||||
   value_test(false, is_standard_fundamental<unsigned __int64>::value)
 | 
			
		||||
   #endif
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_arithmetic<UDT>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<char>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<signed char>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<unsigned char>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<wchar_t>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<short>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<unsigned short>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<int>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<unsigned int>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<long>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<unsigned long>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<float>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<double>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<long double>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<bool>::value)
 | 
			
		||||
   #ifdef ULLONG_MAX
 | 
			
		||||
   value_test(true, is_arithmetic<long long>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<unsigned long long>::value)
 | 
			
		||||
   #endif
 | 
			
		||||
   #if defined(__BORLANDC__) || defined(_MSC_VER)
 | 
			
		||||
   value_test(true, is_arithmetic<__int64>::value)
 | 
			
		||||
   value_test(true, is_arithmetic<unsigned __int64>::value)
 | 
			
		||||
   #endif
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_array<int>::value)
 | 
			
		||||
   value_test(false, is_array<int*>::value)
 | 
			
		||||
   value_test(false, is_array<const int*>::value)
 | 
			
		||||
   value_test(false, is_array<const volatile int*>::value)
 | 
			
		||||
   value_test(true, is_array<int[2]>::value)
 | 
			
		||||
   value_test(true, is_array<const int[2]>::value)
 | 
			
		||||
   value_test(true, is_array<const volatile int[2]>::value)
 | 
			
		||||
   value_test(true, is_array<int[2][3]>::value)
 | 
			
		||||
   value_test(true, is_array<UDT[2]>::value)
 | 
			
		||||
   value_test(false, is_array<int(&)[2]>::value)
 | 
			
		||||
 | 
			
		||||
   typedef void(*f1)();
 | 
			
		||||
   typedef int(*f2)(int);
 | 
			
		||||
   typedef int(*f3)(int, bool);
 | 
			
		||||
   typedef void (UDT::*mf1)();
 | 
			
		||||
   typedef int (UDT::*mf2)();
 | 
			
		||||
   typedef int (UDT::*mf3)(int);
 | 
			
		||||
   typedef int (UDT::*mf4)(int, float);
 | 
			
		||||
   
 | 
			
		||||
   value_test(false, is_const<f1>::value)
 | 
			
		||||
   value_test(false, is_reference<f1>::value)
 | 
			
		||||
   value_test(false, is_array<f1>::value)
 | 
			
		||||
   value_test(false, is_pointer<int>::value)
 | 
			
		||||
   value_test(false, is_pointer<int&>::value)
 | 
			
		||||
   value_test(true, is_pointer<int*>::value)
 | 
			
		||||
   value_test(true, is_pointer<const int*>::value)
 | 
			
		||||
   value_test(true, is_pointer<volatile int*>::value)
 | 
			
		||||
   value_test(true, is_pointer<non_pointer*>::value)
 | 
			
		||||
   // Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1
 | 
			
		||||
   value_test(false, is_pointer<int*const>::value)
 | 
			
		||||
   // Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1
 | 
			
		||||
   value_test(false, is_pointer<int*volatile>::value)
 | 
			
		||||
   // Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1
 | 
			
		||||
   value_test(false, is_pointer<int*const volatile>::value)
 | 
			
		||||
   // JM 02 Oct 2000:
 | 
			
		||||
   value_test(false, is_pointer<non_pointer>::value)
 | 
			
		||||
   value_test(false, is_pointer<int*&>::value)
 | 
			
		||||
   value_test(false, is_pointer<int(&)[2]>::value)
 | 
			
		||||
   value_test(false, is_pointer<int[2]>::value)
 | 
			
		||||
   value_test(false, is_pointer<char[sizeof(void*)]>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(true, is_pointer<f1>::value)
 | 
			
		||||
   value_test(true, is_pointer<f2>::value)
 | 
			
		||||
   value_test(true, is_pointer<f3>::value)
 | 
			
		||||
   // Steve: was 'true', should be 'false', via 3.9.2p3
 | 
			
		||||
   value_test(false, is_pointer<mf1>::value)
 | 
			
		||||
   // Steve: was 'true', should be 'false', via 3.9.2p3
 | 
			
		||||
   value_test(false, is_pointer<mf2>::value)
 | 
			
		||||
   // Steve: was 'true', should be 'false', via 3.9.2p3
 | 
			
		||||
   value_test(false, is_pointer<mf3>::value)
 | 
			
		||||
   // Steve: was 'true', should be 'false', via 3.9.2p3
 | 
			
		||||
   value_test(false, is_pointer<mf4>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_reference<bool>::value)
 | 
			
		||||
   value_test(true, is_reference<int&>::value)
 | 
			
		||||
   value_test(true, is_reference<const int&>::value)
 | 
			
		||||
   value_test(true, is_reference<volatile int &>::value)
 | 
			
		||||
   value_test(true, is_reference<r_type>::value)
 | 
			
		||||
   value_test(true, is_reference<cr_type>::value)
 | 
			
		||||
   value_test(true, is_reference<const UDT&>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_class<int>::value)
 | 
			
		||||
   value_test(false, is_class<const int>::value)
 | 
			
		||||
   value_test(false, is_class<volatile int>::value)
 | 
			
		||||
   value_test(false, is_class<int*>::value)
 | 
			
		||||
   value_test(false, is_class<int* const>::value)
 | 
			
		||||
   value_test(false, is_class<int[2]>::value)
 | 
			
		||||
   value_test(false, is_class<int&>::value)
 | 
			
		||||
   value_test(false, is_class<mf4>::value)
 | 
			
		||||
   value_test(false, is_class<f1>::value)
 | 
			
		||||
   value_test(false, is_class<enum_UDT>::value)
 | 
			
		||||
   value_test(true, is_class<UDT>::value)
 | 
			
		||||
   value_test(true, is_class<UDT const>::value)
 | 
			
		||||
   value_test(true, is_class<UDT volatile>::value)
 | 
			
		||||
   value_test(true, is_class<empty_UDT>::value)
 | 
			
		||||
   value_test(true, is_class<std::iostream>::value)
 | 
			
		||||
   value_test(false, is_class<UDT*>::value)
 | 
			
		||||
   value_test(false, is_class<UDT[2]>::value)
 | 
			
		||||
   value_test(false, is_class<UDT&>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(true, is_object<int>::value)
 | 
			
		||||
   value_test(true, is_object<UDT>::value)
 | 
			
		||||
   value_test(false, is_object<int&>::value)
 | 
			
		||||
   value_test(false, is_object<void>::value)
 | 
			
		||||
   value_test(true, is_standard_scalar<int>::value)
 | 
			
		||||
   value_test(true, is_extension_scalar<void*>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_enum<int>::value)
 | 
			
		||||
   value_test(true, is_enum<enum_UDT>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_member_pointer<f1>::value)
 | 
			
		||||
   value_test(false, is_member_pointer<f2>::value)
 | 
			
		||||
   value_test(false, is_member_pointer<f3>::value)
 | 
			
		||||
   value_test(true, is_member_pointer<mf1>::value)
 | 
			
		||||
   value_test(true, is_member_pointer<mf2>::value)
 | 
			
		||||
   value_test(true, is_member_pointer<mf3>::value)
 | 
			
		||||
   value_test(true, is_member_pointer<mf4>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(false, is_empty<int>::value)
 | 
			
		||||
   value_test(false, is_empty<int*>::value)
 | 
			
		||||
   value_test(false, is_empty<int&>::value)
 | 
			
		||||
#if defined(__MWERKS__) || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
 | 
			
		||||
   // apparent compiler bug causes this to fail to compile:
 | 
			
		||||
   value_fail(false, is_empty<int[2]>::value)
 | 
			
		||||
#else
 | 
			
		||||
   value_test(false, is_empty<int[2]>::value)
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
 | 
			
		||||
   value_fail(false, is_empty<f1>::value)
 | 
			
		||||
#else
 | 
			
		||||
   value_test(false, is_empty<f1>::value)
 | 
			
		||||
#endif
 | 
			
		||||
   value_test(false, is_empty<mf1>::value)
 | 
			
		||||
   value_test(false, is_empty<UDT>::value)
 | 
			
		||||
   value_test(true, is_empty<empty_UDT>::value)
 | 
			
		||||
   value_test(true, is_empty<empty_POD_UDT>::value)
 | 
			
		||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
 | 
			
		||||
   value_fail(true, is_empty<empty_union_UDT>::value)
 | 
			
		||||
#else
 | 
			
		||||
   value_test(true, is_empty<empty_union_UDT>::value)
 | 
			
		||||
#endif
 | 
			
		||||
   value_test(false, is_empty<enum_UDT>::value)
 | 
			
		||||
   value_test(true, is_empty<boost::noncopyable>::value)
 | 
			
		||||
   value_test(false, is_empty<non_empty>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(true, has_trivial_constructor<int>::value)
 | 
			
		||||
   value_test(true, has_trivial_constructor<int*>::value)
 | 
			
		||||
   value_test(true, has_trivial_constructor<int*const>::value)
 | 
			
		||||
   value_test(true, has_trivial_constructor<const int>::value)
 | 
			
		||||
   value_test(true, has_trivial_constructor<volatile int>::value)
 | 
			
		||||
   value_test(true, has_trivial_constructor<int[2]>::value)
 | 
			
		||||
   value_test(true, has_trivial_constructor<int[3][2]>::value)
 | 
			
		||||
   value_test(true, has_trivial_constructor<int[2][4][5][6][3]>::value)
 | 
			
		||||
   value_test(true, has_trivial_constructor<f1>::value)
 | 
			
		||||
   value_test(true, has_trivial_constructor<mf2>::value)
 | 
			
		||||
   value_test(false, has_trivial_constructor<UDT>::value)
 | 
			
		||||
   value_test(true, has_trivial_constructor<empty_UDT>::value)
 | 
			
		||||
   value_test(true, has_trivial_constructor<enum_UDT>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(true, has_trivial_copy<int>::value)
 | 
			
		||||
   value_test(true, has_trivial_copy<int*>::value)
 | 
			
		||||
   value_test(true, has_trivial_copy<int*const>::value)
 | 
			
		||||
   value_test(true, has_trivial_copy<const int>::value)
 | 
			
		||||
   // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10
 | 
			
		||||
   value_test(true, has_trivial_copy<volatile int>::value)
 | 
			
		||||
   value_test(true, has_trivial_copy<int[2]>::value)
 | 
			
		||||
   value_test(true, has_trivial_copy<int[3][2]>::value)
 | 
			
		||||
   value_test(true, has_trivial_copy<int[2][4][5][6][3]>::value)
 | 
			
		||||
   value_test(true, has_trivial_copy<f1>::value)
 | 
			
		||||
   value_test(true, has_trivial_copy<mf2>::value)
 | 
			
		||||
   value_test(false, has_trivial_copy<UDT>::value)
 | 
			
		||||
   value_test(true, has_trivial_copy<empty_UDT>::value)
 | 
			
		||||
   value_test(true, has_trivial_copy<enum_UDT>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(true, has_trivial_assign<int>::value)
 | 
			
		||||
   value_test(true, has_trivial_assign<int*>::value)
 | 
			
		||||
   value_test(true, has_trivial_assign<int*const>::value)
 | 
			
		||||
   value_test(true, has_trivial_assign<const int>::value)
 | 
			
		||||
   // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10
 | 
			
		||||
   value_test(true, has_trivial_assign<volatile int>::value)
 | 
			
		||||
   value_test(true, has_trivial_assign<int[2]>::value)
 | 
			
		||||
   value_test(true, has_trivial_assign<int[3][2]>::value)
 | 
			
		||||
   value_test(true, has_trivial_assign<int[2][4][5][6][3]>::value)
 | 
			
		||||
   value_test(true, has_trivial_assign<f1>::value)
 | 
			
		||||
   value_test(true, has_trivial_assign<mf2>::value)
 | 
			
		||||
   value_test(false, has_trivial_assign<UDT>::value)
 | 
			
		||||
   value_test(true, has_trivial_assign<empty_UDT>::value)
 | 
			
		||||
   value_test(true, has_trivial_assign<enum_UDT>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(true, has_trivial_destructor<int>::value)
 | 
			
		||||
   value_test(true, has_trivial_destructor<int*>::value)
 | 
			
		||||
   value_test(true, has_trivial_destructor<int*const>::value)
 | 
			
		||||
   value_test(true, has_trivial_destructor<const int>::value)
 | 
			
		||||
   value_test(true, has_trivial_destructor<volatile int>::value)
 | 
			
		||||
   value_test(true, has_trivial_destructor<int[2]>::value)
 | 
			
		||||
   value_test(true, has_trivial_destructor<int[3][2]>::value)
 | 
			
		||||
   value_test(true, has_trivial_destructor<int[2][4][5][6][3]>::value)
 | 
			
		||||
   value_test(true, has_trivial_destructor<f1>::value)
 | 
			
		||||
   value_test(true, has_trivial_destructor<mf2>::value)
 | 
			
		||||
   value_test(false, has_trivial_destructor<UDT>::value)
 | 
			
		||||
   value_test(false, has_trivial_destructor<empty_UDT>::value)
 | 
			
		||||
   value_test(true, has_trivial_destructor<enum_UDT>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(true, is_POD<int>::value)
 | 
			
		||||
   value_test(true, is_POD<int*>::value)
 | 
			
		||||
   // Steve: was 'true', should be 'false', via 3.9p10
 | 
			
		||||
   value_test(false, is_POD<int&>::value)
 | 
			
		||||
   value_test(true, is_POD<int*const>::value)
 | 
			
		||||
   value_test(true, is_POD<const int>::value)
 | 
			
		||||
   // Steve: was 'false', should be 'true', via 3.9p10
 | 
			
		||||
   value_test(true, is_POD<volatile int>::value)
 | 
			
		||||
   // Steve: was 'true', should be 'false', via 3.9p10
 | 
			
		||||
   value_test(false, is_POD<const int&>::value)
 | 
			
		||||
   value_test(true, is_POD<int[2]>::value)
 | 
			
		||||
   value_test(true, is_POD<int[3][2]>::value)
 | 
			
		||||
   value_test(true, is_POD<int[2][4][5][6][3]>::value)
 | 
			
		||||
   value_test(true, is_POD<f1>::value)
 | 
			
		||||
   value_test(true, is_POD<mf2>::value)
 | 
			
		||||
   value_test(false, is_POD<UDT>::value)
 | 
			
		||||
   value_test(false, is_POD<empty_UDT>::value)
 | 
			
		||||
   value_test(true, is_POD<enum_UDT>::value)
 | 
			
		||||
 | 
			
		||||
   value_test(true, (boost::is_convertible<Deriverd,Base>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<Deriverd,Deriverd>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<Base,Base>::value));
 | 
			
		||||
   value_test(false, (boost::is_convertible<Base,Deriverd>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<Deriverd,Deriverd>::value));
 | 
			
		||||
   value_test(false, (boost::is_convertible<NonDerived,Base>::value));
 | 
			
		||||
   value_test(false, (boost::is_convertible<boost::noncopyable, int>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<float,int>::value));
 | 
			
		||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
 | 
			
		||||
   value_test(false, (boost::is_convertible<float,void>::value));
 | 
			
		||||
   value_test(false, (boost::is_convertible<void,float>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<void,void>::value));
 | 
			
		||||
#endif
 | 
			
		||||
   value_test(true, (boost::is_convertible<enum1, int>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<Deriverd*, Base*>::value));
 | 
			
		||||
   value_test(false, (boost::is_convertible<Base*, Deriverd*>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<Deriverd&, Base&>::value));
 | 
			
		||||
   value_test(false, (boost::is_convertible<Base&, Deriverd&>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<const Deriverd*, const Base*>::value));
 | 
			
		||||
   value_test(false, (boost::is_convertible<const Base*, const Deriverd*>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<const Deriverd&, const Base&>::value));
 | 
			
		||||
   value_test(false, (boost::is_convertible<const Base&, const Deriverd&>::value));
 | 
			
		||||
 | 
			
		||||
   value_test(false, (boost::is_convertible<const int *, int*>::value));
 | 
			
		||||
   value_test(false, (boost::is_convertible<const int&, int&>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<int*, int[2]>::value));
 | 
			
		||||
   value_test(false, (boost::is_convertible<const int*, int[3]>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<const int&, int>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<int(&)[4], const int*>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<int(&)(int), int(*)(int)>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<int *, const int*>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<int&, const int&>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<int[2], int*>::value));
 | 
			
		||||
   value_test(true, (boost::is_convertible<int[2], const int*>::value));
 | 
			
		||||
   value_test(false, (boost::is_convertible<const int[2], int*>::value));
 | 
			
		||||
 | 
			
		||||
   align_test(int);
 | 
			
		||||
   align_test(char);
 | 
			
		||||
   align_test(double);
 | 
			
		||||
   align_test(int[4]);
 | 
			
		||||
   align_test(int(*)(int));
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
   align_test(char&);
 | 
			
		||||
   align_test(char (&)(int));
 | 
			
		||||
   align_test(char(&)[4]);
 | 
			
		||||
#endif
 | 
			
		||||
   align_test(int*);
 | 
			
		||||
   //align_test(const int);
 | 
			
		||||
   align_test(VB);
 | 
			
		||||
   align_test(VD);
 | 
			
		||||
 | 
			
		||||
   std::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit";
 | 
			
		||||
   std::cin.get();
 | 
			
		||||
   return failures;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,112 +0,0 @@
 | 
			
		||||
 // boost::compressed_pair test program   
 | 
			
		||||
    
 | 
			
		||||
 //  (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and   
 | 
			
		||||
 //  distribute this software is granted provided this copyright notice appears   
 | 
			
		||||
 //  in all copies. This software is provided "as is" without express or implied   
 | 
			
		||||
 //  warranty, and with no claim as to its suitability for any purpose.   
 | 
			
		||||
 | 
			
		||||
// common test code for type_traits_test.cpp/call_traits_test.cpp/compressed_pair_test.cpp
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_TYPE_TRAITS_TEST_HPP
 | 
			
		||||
#define BOOST_TYPE_TRAITS_TEST_HPP
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// this one is here just to suppress warnings:
 | 
			
		||||
//
 | 
			
		||||
template <class T>
 | 
			
		||||
bool do_compare(T i, T j)
 | 
			
		||||
{
 | 
			
		||||
   return i == j;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// this one is to verify that a constant is indeed a
 | 
			
		||||
// constant-integral-expression:
 | 
			
		||||
//
 | 
			
		||||
template <int>
 | 
			
		||||
struct ct_checker
 | 
			
		||||
{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2(X,Y)
 | 
			
		||||
#define BOOST_DO_JOIN2(X, Y) X##Y
 | 
			
		||||
#define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y )
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
#define value_test(v, x) ++test_count;\
 | 
			
		||||
                        {typedef ct_checker<(x)> this_is_a_compile_time_check_;}\
 | 
			
		||||
                         if(!do_compare((int)v,(int)x)){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;}
 | 
			
		||||
#else
 | 
			
		||||
#define value_test(v, x) ++test_count;\
 | 
			
		||||
                         typedef ct_checker<(x)> BOOST_JOIN(this_is_a_compile_time_check_, __LINE__);\
 | 
			
		||||
                         if(!do_compare((int)v,(int)x)){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;}
 | 
			
		||||
#endif
 | 
			
		||||
#define value_fail(v, x) ++test_count; ++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
#define type_test(v, x)  ++test_count;\
 | 
			
		||||
                           if(do_compare(boost::is_same<v, x>::value, false)){\
 | 
			
		||||
                           ++failures; \
 | 
			
		||||
                           std::cout << "checking type of " << #x << "...failed" << std::endl; \
 | 
			
		||||
                           std::cout << "   expected type was " << #v << std::endl; \
 | 
			
		||||
                           std::cout << "   " << typeid(boost::is_same<v, x>).name() << "::value is false" << std::endl; }
 | 
			
		||||
#else
 | 
			
		||||
#define type_test(v, x)  ++test_count;\
 | 
			
		||||
                         if(typeid(v) != typeid(x)){\
 | 
			
		||||
                           ++failures; \
 | 
			
		||||
                           std::cout << "checking type of " << #x << "...failed" << std::endl; \
 | 
			
		||||
                           std::cout << "   expected type was " << #v << std::endl; \
 | 
			
		||||
                           std::cout << "   " << "typeid(" #v ") != typeid(" #x ")" << std::endl; }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
struct test_align
 | 
			
		||||
{
 | 
			
		||||
   struct padded
 | 
			
		||||
   {
 | 
			
		||||
      char c;
 | 
			
		||||
      T t;
 | 
			
		||||
   };
 | 
			
		||||
   static void do_it()
 | 
			
		||||
   {
 | 
			
		||||
      padded p;
 | 
			
		||||
      unsigned a = reinterpret_cast<char*>(&(p.t)) - reinterpret_cast<char*>(&p);
 | 
			
		||||
      value_test(a, boost::alignment_of<T>::value);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
template <class T>
 | 
			
		||||
struct test_align<T&>
 | 
			
		||||
{
 | 
			
		||||
   static void do_it()
 | 
			
		||||
   {
 | 
			
		||||
      //
 | 
			
		||||
      // we can't do the usual test because we can't take the address
 | 
			
		||||
      // of a reference, so check that the result is the same as for a
 | 
			
		||||
      // pointer type instead:
 | 
			
		||||
      value_test(boost::alignment_of<T*>::value, boost::alignment_of<T&>::value);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define align_test(T) test_align<T>::do_it()
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// define tests here
 | 
			
		||||
unsigned failures = 0;
 | 
			
		||||
unsigned test_count = 0;
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// turn off some warnings:
 | 
			
		||||
#ifdef __BORLANDC__
 | 
			
		||||
#pragma option -w-8004
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_MSVC
 | 
			
		||||
#pragma warning (disable: 4018)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_TYPE_TRAITS_TEST_HPP
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										46
									
								
								utility.htm
									
									
									
									
									
								
							
							
						
						
									
										46
									
								
								utility.htm
									
									
									
									
									
								
							@@ -16,10 +16,50 @@
 | 
			
		||||
<h2>Contents</h2>
 | 
			
		||||
 | 
			
		||||
<ul>
 | 
			
		||||
  <li>Function templates <a href="#checked_delete">checked_delete() and
 | 
			
		||||
    checked_array_delete()</a></li>
 | 
			
		||||
  <li>Function templates <a href="#functions next">next() and prior()</a></li>
 | 
			
		||||
  <li>Class <a href="#Class noncopyable">noncopyable</a></li>
 | 
			
		||||
  <li>Function template <a href="tie.html">tie()</a> and supporting class tied.</li>
 | 
			
		||||
</ul>
 | 
			
		||||
<h2> Function templates <a name="checked_delete">checked_delete</a>() and
 | 
			
		||||
checked_array_delete()</h2>
 | 
			
		||||
 | 
			
		||||
<p>Deletion of a pointer to an incomplete type is an unsafe programming practice
 | 
			
		||||
because there is no way for the compiler to verify that the destructor is indeed
 | 
			
		||||
trivial.  The checked_delete() and checked_array_delete() function
 | 
			
		||||
templates simply <b>delete</b> or <b>delete[]</b> their argument, but also
 | 
			
		||||
require that their argument be a complete type.  They issue an appropriate
 | 
			
		||||
compiler error diagnostic if that requirement is not met.  A typical
 | 
			
		||||
implementation is shown; other implementations may vary:</p>
 | 
			
		||||
 | 
			
		||||
<pre>    template< typename T >
 | 
			
		||||
    inline void checked_delete(T const volatile * x)
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_STATIC_ASSERT( sizeof(T) ); // assert type complete at point
 | 
			
		||||
                                          // of instantiation
 | 
			
		||||
        delete x;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template< typename T >
 | 
			
		||||
    inline void checked_array_delete(T const volatile * x)
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_STATIC_ASSERT( sizeof(T) ); // assert type complete at point
 | 
			
		||||
                                          // of instantiation
 | 
			
		||||
        delete [] x;
 | 
			
		||||
    }</pre>
 | 
			
		||||
 | 
			
		||||
<p>Contributed by Beman Dawes, based on a suggestion from Dave Abrahams,
 | 
			
		||||
generalizing an idea from Vladimir Prus, with comments from Rainer Deyke, John
 | 
			
		||||
Maddock, and others.</p>
 | 
			
		||||
 | 
			
		||||
<h3>Background</h3>
 | 
			
		||||
 | 
			
		||||
<p>The C++ Standard specifies that delete on a pointer to an incomplete types is
 | 
			
		||||
undefined behavior if the type has a non-trivial destructor in  [expr.delete]
 | 
			
		||||
5.3.5 paragraph.  No diagnostic is required.  Some but not all
 | 
			
		||||
compilers issue warnings if the type is incomplete at point of deletion.</p>
 | 
			
		||||
 | 
			
		||||
<h2> <a name="functions next">Function</a> templates next() and prior()</h2>
 | 
			
		||||
 | 
			
		||||
<p>Certain data types, such as the C++ Standard Library's forward and
 | 
			
		||||
@@ -81,7 +121,7 @@ CodeWarrior 5.0, and Microsoft Visual C++ 6.0 sp 3.</p>
 | 
			
		||||
  <pre>// inside one of your own headers ...
 | 
			
		||||
#include <boost/utility.hpp>
 | 
			
		||||
 | 
			
		||||
class ResourceLadenFileSystem : noncopyable {
 | 
			
		||||
class ResourceLadenFileSystem : boost::noncopyable {
 | 
			
		||||
...</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
 | 
			
		||||
@@ -91,9 +131,11 @@ emphasize that it is to be used only as a base class.  Dave Abrahams notes
 | 
			
		||||
concern about the effect on compiler optimization of adding (even trivial inline)
 | 
			
		||||
destructor declarations. He says "Probably this concern is misplaced, because
 | 
			
		||||
noncopyable will be used mostly for classes which own resources and thus have non-trivial destruction semantics."</p>
 | 
			
		||||
<h2>Function template tie()</h2>
 | 
			
		||||
<p>See <a href="tie.html">separate documentation</a>.</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised  <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan
 | 
			
		||||
-->28 September, 2000<!--webbot bot="Timestamp" endspan i-checksum="39343"
 | 
			
		||||
-->22 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13960"
 | 
			
		||||
-->
 | 
			
		||||
</p>
 | 
			
		||||
<p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user