mirror of
				https://github.com/boostorg/utility.git
				synced 2025-10-29 15:31:39 +01:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			svn-branch
			...
			svn-branch
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 8f583902a5 | 
							
								
								
									
										116
									
								
								Assignable.html
									
									
									
									
									
								
							
							
						
						
									
										116
									
								
								Assignable.html
									
									
									
									
									
								
							| @@ -1,116 +0,0 @@ | ||||
| <HTML> | ||||
| <!-- | ||||
|   -- Copyright (c) Jeremy Siek 2000 | ||||
|   -- | ||||
|   -- Permission to use, copy, modify, distribute and sell this software | ||||
|   -- and its documentation for any purpose is hereby granted without fee, | ||||
|   -- provided that the above copyright notice appears in all copies and | ||||
|   -- that both that copyright notice and this permission notice appear | ||||
|   -- in supporting documentation.  Silicon Graphics makes no | ||||
|   -- representations about the suitability of this software for any | ||||
|   -- purpose.  It is provided "as is" without express or implied warranty. | ||||
|   --> | ||||
| <Head> | ||||
| <Title>Assignable</Title> | ||||
| </HEAD> | ||||
| <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"  | ||||
|         ALINK="#ff0000">  | ||||
| <IMG SRC="../../c++boost.gif"  | ||||
|      ALT="C++ Boost" width="277" height="86">  | ||||
| <!--end header--> | ||||
| <BR Clear> | ||||
| <H1>Assignable</H1> | ||||
|  | ||||
| <h3>Description</h3> | ||||
| A type is Assignable if it is possible to assign one object of the type | ||||
| to another object of that type. | ||||
|  | ||||
|  | ||||
| <h3>Notation</h3> | ||||
| <Table> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| <tt>T</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| is type that is a model of Assignable | ||||
| </TD> | ||||
| </TR> | ||||
|  | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| <tt>t</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| is an object of type <tt>T</tt> | ||||
| </TD> | ||||
| </tr> | ||||
|  | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| <tt>u</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| is an object of type <tt>T</tt> or possibly <tt>const T</tt> | ||||
| </TD> | ||||
| </tr> | ||||
|  | ||||
| </table> | ||||
| <h3>Definitions</h3> | ||||
| <h3>Valid expressions</h3> | ||||
| <Table border> | ||||
| <TR> | ||||
| <TH> | ||||
| Name | ||||
| </TH> | ||||
| <TH> | ||||
| Expression | ||||
| </TH> | ||||
| <TH> | ||||
| Return type | ||||
| </TH> | ||||
| <TH> | ||||
| Semantics | ||||
| </TH> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Assignment | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>t = u</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>T&</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>t</tt> is equivalent to <tt>u</tt> | ||||
| </TD> | ||||
| </TR> | ||||
|  | ||||
| </table> | ||||
|  | ||||
|  | ||||
| </table> | ||||
| <h3>Models</h3> | ||||
|  | ||||
| <UL> | ||||
| <LI><tt>int</tt> | ||||
| <LI><tt>std::pair</tt> | ||||
| </UL> | ||||
|  | ||||
| <h3>See also</h3> | ||||
| <a href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">DefaultConstructible</A> | ||||
| and  | ||||
| <A href="./CopyConstructible.html">CopyConstructible</A> | ||||
|  | ||||
| <br> | ||||
| <HR> | ||||
| <TABLE> | ||||
| <TR valign=top> | ||||
| <TD nowrap>Copyright © 2000</TD><TD> | ||||
| <A HREF=http://www.lsc.nd.edu/~jsiek>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>) | ||||
| </TD></TR></TABLE> | ||||
|  | ||||
| </BODY> | ||||
| </HTML>  | ||||
| @@ -1,210 +0,0 @@ | ||||
| <HTML> | ||||
| <!-- | ||||
|   -- Copyright (c) Jeremy Siek 2000 | ||||
|   -- | ||||
|   -- Permission to use, copy, modify, distribute and sell this software | ||||
|   -- and its documentation for any purpose is hereby granted without fee, | ||||
|   -- provided that the above copyright notice appears in all copies and | ||||
|   -- that both that copyright notice and this permission notice appear | ||||
|   -- in supporting documentation.  Silicon Graphics makes no | ||||
|   -- representations about the suitability of this software for any | ||||
|   -- purpose.  It is provided "as is" without express or implied warranty. | ||||
|   --> | ||||
| <Head> | ||||
| <Title>CopyConstructible</Title> | ||||
| </HEAD> | ||||
| <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"  | ||||
|         ALINK="#ff0000">  | ||||
| <IMG SRC="../../c++boost.gif"  | ||||
|      ALT="C++ Boost" width="277" height="86">  | ||||
| <!--end header--> | ||||
| <BR Clear> | ||||
| <H1>CopyConstructible</H1> | ||||
|  | ||||
| <h3>Description</h3> | ||||
| A type is CopyConstructible if it is possible to copy objects of that | ||||
| type. | ||||
|  | ||||
| <h3>Notation</h3> | ||||
| <Table> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| <tt>T</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| is type that is a model of CopyConstructible | ||||
| </TD> | ||||
| </TR> | ||||
|  | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| <tt>t</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| is an object of type <tt>T</tt> | ||||
| </TD> | ||||
| </tr> | ||||
|  | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| <tt>u</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| is an object of type <tt>const T</tt> | ||||
| </TD> | ||||
| </tr> | ||||
|  | ||||
| </table> | ||||
| <h3>Definitions</h3> | ||||
| <h3>Valid expressions</h3> | ||||
| <Table border> | ||||
| <TR> | ||||
| <TH> | ||||
| Name | ||||
| </TH> | ||||
| <TH> | ||||
| Expression | ||||
| </TH> | ||||
| <TH> | ||||
| Return type | ||||
| </TH> | ||||
| <TH> | ||||
| Semantics | ||||
| </TH> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Copy constructor | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>T(t)</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>T</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>t</tt> is equivalent to <tt>T(t)</tt> | ||||
| </TD> | ||||
| </TR> | ||||
|  | ||||
|  | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Copy constructor | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <pre> | ||||
| T(u) | ||||
| </pre> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>T</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>u</tt> is equivalent to <tt>T(u)</tt> | ||||
| </TD> | ||||
| </TR> | ||||
|  | ||||
|  | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Destructor | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <pre> | ||||
| t.~T() | ||||
| </pre> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>T</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
|   | ||||
| </TD> | ||||
| </TR> | ||||
|  | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Address Operator | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <pre> | ||||
| &t | ||||
| </pre> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>T*</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| denotes the address of <tt>t</tt> | ||||
| </TD> | ||||
| </TR> | ||||
|  | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Address Operator | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <pre> | ||||
| &u | ||||
| </pre> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>T*</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| denotes the address of <tt>u</tt> | ||||
| </TD> | ||||
| </TR> | ||||
|  | ||||
|  | ||||
|  | ||||
| </table> | ||||
|  | ||||
|  | ||||
| </table> | ||||
| <h3>Models</h3> | ||||
|  | ||||
| <UL> | ||||
| <LI><tt>int</tt> | ||||
| <LI><tt>std::pair</tt> | ||||
| </UL> | ||||
|  | ||||
| <h3>Concept Checking Class</h3> | ||||
|  | ||||
| <pre> | ||||
|   template <class T> | ||||
|   struct CopyConstructibleConcept | ||||
|   { | ||||
|     void constraints() { | ||||
|       T a(b);            // require copy constructor | ||||
|       T* ptr = &a;       // require address of operator | ||||
|       const_constraints(a); | ||||
|       ignore_unused_variable_warning(ptr); | ||||
|     } | ||||
|     void const_constraints(const T& a) { | ||||
|       T c(a);            // require const copy constructor | ||||
|       const T* ptr = &a; // require const address of operator | ||||
|       ignore_unused_variable_warning(c); | ||||
|       ignore_unused_variable_warning(ptr); | ||||
|     } | ||||
|     T b; | ||||
|   }; | ||||
| </pre> | ||||
|  | ||||
| <h3>See also</h3> | ||||
| <A | ||||
| href="http://www.sgi.com/Technology/STL/DefaultConstructible.html">DefaultConstructible</A> | ||||
| and  | ||||
| <A href="http://www.sgi.com/Technology/STL/Assignable.html">Assignable</A> | ||||
|  | ||||
| <br> | ||||
| <HR> | ||||
| <TABLE> | ||||
| <TR valign=top> | ||||
| <TD nowrap>Copyright © 2000</TD><TD> | ||||
| <A HREF=http://www.lsc.nd.edu/~jsiek>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>) | ||||
| </TD></TR></TABLE> | ||||
|  | ||||
| </BODY> | ||||
| </HTML>  | ||||
| @@ -1,212 +0,0 @@ | ||||
| <HTML> | ||||
| <!-- | ||||
|   -- Copyright (c) Jeremy Siek 2000 | ||||
|   -- | ||||
|   -- Permission to use, copy, modify, distribute and sell this software | ||||
|   -- and its documentation for any purpose is hereby granted without fee, | ||||
|   -- provided that the above copyright notice appears in all copies and | ||||
|   -- that both that copyright notice and this permission notice appear | ||||
|   -- in supporting documentation.  Silicon Graphics makes no | ||||
|   -- representations about the suitability of this software for any | ||||
|   -- purpose.  It is provided "as is" without express or implied warranty. | ||||
|   --> | ||||
| <!-- | ||||
|   -- Copyright (c) 1996-1999 | ||||
|   -- Silicon Graphics Computer Systems, Inc. | ||||
|   -- | ||||
|   -- Permission to use, copy, modify, distribute and sell this software | ||||
|   -- and its documentation for any purpose is hereby granted without fee, | ||||
|   -- provided that the above copyright notice appears in all copies and | ||||
|   -- that both that copyright notice and this permission notice appear | ||||
|   -- in supporting documentation.  Silicon Graphics makes no | ||||
|   -- representations about the suitability of this software for any | ||||
|   -- purpose.  It is provided "as is" without express or implied warranty. | ||||
|   -- | ||||
|   -- Copyright (c) 1994 | ||||
|   -- Hewlett-Packard Company | ||||
|   -- | ||||
|   -- Permission to use, copy, modify, distribute and sell this software | ||||
|   -- and its documentation for any purpose is hereby granted without fee, | ||||
|   -- provided that the above copyright notice appears in all copies and | ||||
|   -- that both that copyright notice and this permission notice appear | ||||
|   -- in supporting documentation.  Hewlett-Packard Company makes no | ||||
|   -- representations about the suitability of this software for any | ||||
|   -- purpose.  It is provided "as is" without express or implied warranty. | ||||
|   -- | ||||
|   --> | ||||
| <Head> | ||||
| <Title>LessThanComparable</Title> | ||||
| </Head> | ||||
| <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"  | ||||
|         ALINK="#ff0000">  | ||||
| <IMG SRC="../../c++boost.gif"  | ||||
|      ALT="C++ Boost" width="277" height="86">  | ||||
| <!--end header--> | ||||
| <BR Clear> | ||||
| <H1>LessThanComparable</H1> | ||||
|  | ||||
| <h3>Description</h3> | ||||
| A type is LessThanComparable if it is ordered: it must | ||||
| be possible to compare two objects of that type using <tt>operator<</tt>, and | ||||
| <tt>operator<</tt> must be a strict weak ordering relation. | ||||
|  | ||||
|  | ||||
| <h3>Refinement of</h3> | ||||
| <h3>Associated types</h3> | ||||
| <h3>Notation</h3> | ||||
| <Table> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| <tt>X</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| A type that is a model of LessThanComparable | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| <tt>x</tt>, <tt>y</tt>, <tt>z</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Object of type <tt>X</tt> | ||||
| </TD> | ||||
| </tr> | ||||
| </table> | ||||
| <h3>Definitions</h3> | ||||
| Consider the relation <tt>!(x < y) && !(y < x)</tt>.  If this relation is | ||||
| transitive (that is, if <tt>!(x < y) && !(y < x) && !(y < z) && !(z < y)</tt> | ||||
| implies <tt>!(x < z) && !(z < x)</tt>), then it satisfies the mathematical | ||||
| definition of an equivalence relation.  In this case, <tt>operator<</tt> | ||||
| is a <i>strict weak ordering</i>. | ||||
| <P> | ||||
| If <tt>operator<</tt> is a strict weak ordering, and if each equivalence class | ||||
| has only a single element, then <tt>operator<</tt> is a <i>total ordering</i>. | ||||
| <h3>Valid expressions</h3> | ||||
| <Table border> | ||||
| <TR> | ||||
| <TH> | ||||
| Name | ||||
| </TH> | ||||
| <TH> | ||||
| Expression | ||||
| </TH> | ||||
| <TH> | ||||
| Type requirements | ||||
| </TH> | ||||
| <TH> | ||||
| Return type | ||||
| </TH> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Less | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>x < y</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
|   | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Convertible to <tt>bool</tt> | ||||
| </TD> | ||||
| </TR> | ||||
| </table> | ||||
|  | ||||
|  | ||||
|  | ||||
| <h3>Expression semantics</h3> | ||||
| <Table border> | ||||
| <TR> | ||||
| <TH> | ||||
| Name | ||||
| </TH> | ||||
| <TH> | ||||
| Expression | ||||
| </TH> | ||||
| <TH> | ||||
| Precondition | ||||
| </TH> | ||||
| <TH> | ||||
| Semantics | ||||
| </TH> | ||||
| <TH> | ||||
| Postcondition | ||||
| </TH> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Less | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>x < y</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>x</tt> and <tt>y</tt> are in the domain of <tt><</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
|   | ||||
| </TD> | ||||
| </table> | ||||
|  | ||||
|  | ||||
| <h3>Complexity guarantees</h3> | ||||
| <h3>Invariants</h3> | ||||
| <Table border> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Irreflexivity | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>x < x</tt> must be false. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Antisymmetry | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>x < y</tt> implies !(y < x) <A href="#2">[2]</A> | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Transitivity | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>x < y</tt> and <tt>y < z</tt> implies <tt>x < z</tt> <A href="#3">[3]</A> | ||||
| </TD> | ||||
| </tr> | ||||
| </table> | ||||
| <h3>Models</h3> | ||||
| <UL> | ||||
| <LI> | ||||
| int | ||||
| </UL> | ||||
| <h3>Notes</h3> | ||||
| <P><A name="1">[1]</A> | ||||
| Only <tt>operator<</tt> is fundamental; the other inequality operators | ||||
| are essentially syntactic sugar. | ||||
| <P><A name="2">[2]</A> | ||||
| Antisymmetry is a theorem, not an axiom: it follows from | ||||
| irreflexivity and transitivity. | ||||
| <P><A name="3">[3]</A> | ||||
| Because of irreflexivity and transitivity, <tt>operator<</tt> always | ||||
| satisfies the definition of a <i>partial ordering</i>.  The definition of | ||||
| a <i>strict weak ordering</i> is stricter, and the definition of a | ||||
| <i>total ordering</i> is stricter still. | ||||
| <h3>See also</h3> | ||||
| <A href="http://www.sgi.com/Technology/STL/EqualityComparable.html">EqualityComparable</A>, <A href="http://www.sgi.com/Technology/STL/StrictWeakOrdering.html">StrictWeakOrdering</A> | ||||
|  | ||||
|  | ||||
|  | ||||
| <br> | ||||
| <HR> | ||||
| <TABLE> | ||||
| <TR valign=top> | ||||
| <TD nowrap>Copyright © 2000</TD><TD> | ||||
| <A HREF=http://www.lsc.nd.edu/~jsiek>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>) | ||||
| </TD></TR></TABLE> | ||||
|  | ||||
| </BODY> | ||||
| </HTML>  | ||||
| @@ -1,92 +0,0 @@ | ||||
| <HTML> | ||||
| <!-- | ||||
|   -- Copyright (c) Jeremy Siek 2000 | ||||
|   -- | ||||
|   -- Permission to use, copy, modify, distribute and sell this software | ||||
|   -- and its documentation for any purpose is hereby granted without fee, | ||||
|   -- provided that the above copyright notice appears in all copies and | ||||
|   -- that both that copyright notice and this permission notice appear | ||||
|   -- in supporting documentation.  Silicon Graphics makes no | ||||
|   -- representations about the suitability of this software for any | ||||
|   -- purpose.  It is provided "as is" without express or implied warranty. | ||||
|   --> | ||||
| <Head> | ||||
| <Title>MultiPassInputIterator</Title> | ||||
| <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"  | ||||
| 	ALINK="#ff0000">  | ||||
| <IMG SRC="../../c++boost.gif"  | ||||
|      ALT="C++ Boost" width="277" height="86">  | ||||
|  | ||||
| <BR Clear> | ||||
|  | ||||
| <H2> | ||||
| <A NAME="concept:MultiPassInputIterator"></A> | ||||
| MultiPassInputIterator | ||||
| </H2> | ||||
|  | ||||
| This concept is a refinement of <a | ||||
| href="http://www.sgi.com/Technology/STL/InputIterator.html">InputIterator</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 | ||||
| only difference is that a <a | ||||
| href="http://www.sgi.com/Technology/STL/ForwardIterator.hmtl">ForwardIterator</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> | ||||
| in that the <TT>reference</TT> type merely has to be convertible to | ||||
| <TT>value_type</TT>. | ||||
|  | ||||
|  | ||||
| <h3>Design Notes</h3> | ||||
|  | ||||
| comments by Valentin Bonnard: | ||||
|  | ||||
| <p> I think that introducing MultiPassInputIterator isn't the right | ||||
| solution. Do you also want to define MultiPassBidirectionnalIterator | ||||
| and MultiPassRandomAccessIterator ? 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 | ||||
| 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. | ||||
|  | ||||
| <p>                 | ||||
| Other translations are:<br> | ||||
| std::ForwardIterator -> ForwardIterator & LvalueIterator<br> | ||||
| std::BidirectionnalIterator -> BidirectionnalIterator & LvalueIterator<br> | ||||
| std::RandomAccessIterator -> RandomAccessIterator & LvalueIterator<br> | ||||
|  | ||||
| <p> | ||||
| Note that in practice the only operation not allowed on my  | ||||
| ForwardIterator which is allowed on std::ForwardIterator is  | ||||
| <tt>&*it</tt>. I think that <tt>&*</tt> is rarely needed in generic code. | ||||
|  | ||||
| <p> | ||||
| reply by Jeremy Siek: | ||||
|  | ||||
| <p> | ||||
| The above analysis by Valentin is right on. Of course, there is | ||||
| the problem with backward compatibility. The current STL implementations | ||||
| are based on the old definition of ForwardIterator. The right course | ||||
| of action is to get ForwardIterator, etc. changed in the C++ standard. | ||||
| Once that is done we can drop MultiPassInputIterator. | ||||
|  | ||||
|  | ||||
| <br> | ||||
| <HR> | ||||
| <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>) | ||||
| </TD></TR></TABLE> | ||||
|  | ||||
| </BODY> | ||||
| </HTML>  | ||||
							
								
								
									
										762
									
								
								call_traits.htm
									
									
									
									
									
								
							
							
						
						
									
										762
									
								
								call_traits.htm
									
									
									
									
									
								
							| @@ -1,762 +0,0 @@ | ||||
| <html> | ||||
|  | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" | ||||
| content="text/html; charset=iso-8859-1"> | ||||
| <meta name="Template" | ||||
| content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot"> | ||||
| <meta name="GENERATOR" content="Microsoft FrontPage Express 2.0"> | ||||
| <title>Call Traits</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000" link="#0000FF" | ||||
| vlink="#800080"> | ||||
|  | ||||
| <h1><img src="../../c++boost.gif" width="276" height="86">Header | ||||
| <<a href="../../boost/detail/call_traits.hpp">boost/call_traits.hpp</a>></h1> | ||||
|  | ||||
| <p>All of the contents of <boost/call_traits.hpp> are | ||||
| defined inside namespace boost.</p> | ||||
|  | ||||
| <p>The template class call_traits<T> encapsulates the | ||||
| "best" method to pass a parameter of some type T to or | ||||
| from a function, and consists of a collection of typedefs defined | ||||
| as in the table below. The purpose of call_traits is to ensure | ||||
| that problems like "<a href="#refs">references to references</a>" | ||||
| never occur, and that parameters are passed in the most efficient | ||||
| manner possible (see <a href="#examples">examples</a>). In each | ||||
| case if your existing practice is to use the type defined on the | ||||
| left, then replace it with the call_traits defined type on the | ||||
| right. </p> | ||||
|  | ||||
| <p>Note that for compilers that do not support either partial | ||||
| specialization or member templates, no benefit will occur from | ||||
| using call_traits: the call_traits defined types will always be | ||||
| the same as the existing practice in this case. In addition if | ||||
| only member templates and not partial template specialisation is | ||||
| support by the compiler (for example Visual C++ 6) then | ||||
| call_traits can not be used with array types (although it can be | ||||
| used to solve the reference to reference problem).</p> | ||||
|  | ||||
| <table border="0" cellpadding="7" cellspacing="1" width="797"> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#008080"><p | ||||
|         align="center">Existing practice</p> | ||||
|         </td> | ||||
|         <td valign="top" width="35%" bgcolor="#008080"><p | ||||
|         align="center">call_traits equivalent</p> | ||||
|         </td> | ||||
|         <td valign="top" width="32%" bgcolor="#008080"><p | ||||
|         align="center">Description</p> | ||||
|         </td> | ||||
|         <td valign="top" width="16%" bgcolor="#008080"><p | ||||
|         align="center">Notes</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%"><p align="center">T<br> | ||||
|         (return by value)</p> | ||||
|         </td> | ||||
|         <td valign="top" width="35%"><p align="center"><code>call_traits<T>::value_type</code></p> | ||||
|         </td> | ||||
|         <td valign="top" width="32%">Defines a type that | ||||
|         represents the "value" of type T. Use this for | ||||
|         functions that return by value, or possibly for stored | ||||
|         values of type T.</td> | ||||
|         <td valign="top" width="16%"><p align="center">2</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%"><p align="center">T&<br> | ||||
|         (return value)</p> | ||||
|         </td> | ||||
|         <td valign="top" width="35%"><p align="center"><code>call_traits<T>::reference</code></p> | ||||
|         </td> | ||||
|         <td valign="top" width="32%">Defines a type that | ||||
|         represents a reference to type T. Use for functions that | ||||
|         would normally return a T&.</td> | ||||
|         <td valign="top" width="16%"><p align="center">1</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <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> | ||||
|         </td> | ||||
|         <td valign="top" width="32%">Defines a type that | ||||
|         represents a constant reference to type T. Use for | ||||
|         functions that would normally return a const T&.</td> | ||||
|         <td valign="top" width="16%"><p align="center">1</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <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> | ||||
|         </td> | ||||
|         <td valign="top" width="32%">Defines a type that | ||||
|         represents the "best" way to pass a parameter | ||||
|         of type T to a function.</td> | ||||
|         <td valign="top" width="16%"><p align="center">1,3</p> | ||||
|         </td> | ||||
|     </tr> | ||||
| </table> | ||||
|  | ||||
| <p>Notes:</p> | ||||
|  | ||||
| <ol> | ||||
|     <li>If T is already reference type, then call_traits is | ||||
|         defined such that <a href="#refs">references to | ||||
|         references</a> do not occur (requires partial | ||||
|         specialization).</li> | ||||
|     <li>If T is an array type, then call_traits defines <code>value_type</code> | ||||
|         as a "constant pointer to type" rather than an | ||||
|         "array of type" (requires partial | ||||
|         specialization). Note that if you are using value_type as | ||||
|         a stored value then this will result in storing a "constant | ||||
|         pointer to an array" rather than the array itself. | ||||
|         This may or may not be a good thing depending upon what | ||||
|         you actually need (in other words take care!).</li> | ||||
|     <li>If T is a small built in type or a pointer, then <code>param_type</code> | ||||
|         is defined as <code>T const</code>, instead of <code>T | ||||
|         const&</code>. This can improve the ability of the | ||||
|         compiler to optimize loops in the body of the function if | ||||
|         they depend upon the passed parameter, the semantics of | ||||
|         the passed parameter is otherwise unchanged (requires | ||||
|         partial specialization).</li> | ||||
| </ol> | ||||
|  | ||||
| <p> </p> | ||||
|  | ||||
| <h3>Copy constructibility</h3> | ||||
|  | ||||
| <p>The following table defines which call_traits types can always | ||||
| be copy-constructed from which other types, those entries marked | ||||
| with a '?' are true only if and only if T is copy constructible:</p> | ||||
|  | ||||
| <table border="0" cellpadding="7" cellspacing="1" width="766"> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%"> </td> | ||||
|         <td valign="top" colspan="5" width="85%" | ||||
|         bgcolor="#008080"><p align="center">To:</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#008080">From:</td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">T</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">value_type</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">reference</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">const_reference</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">param_type</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0">T</td> | ||||
|         <td valign="top" width="17%"><p align="center">?</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">?</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td> | ||||
|         <td valign="top" width="17%"><p align="center">?</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">?</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">N</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">N</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0">reference</td> | ||||
|         <td valign="top" width="17%"><p align="center">?</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">?</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td> | ||||
|         <td valign="top" width="17%"><p align="center">?</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">N</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">N</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td> | ||||
|         <td valign="top" width="17%"><p align="center">?</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">?</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">N</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">N</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|     </tr> | ||||
| </table> | ||||
|  | ||||
| <p> </p> | ||||
|  | ||||
| <p>If T is an assignable type the following assignments are | ||||
| possible:</p> | ||||
|  | ||||
| <table border="0" cellpadding="7" cellspacing="1" width="766"> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%"> </td> | ||||
|         <td valign="top" colspan="5" width="85%" | ||||
|         bgcolor="#008080"><p align="center">To:</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#008080">From:</td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">T</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">value_type</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">reference</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">const_reference</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">param_type</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0">T</td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0">reference</td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">Y</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">-</p> | ||||
|         </td> | ||||
|     </tr> | ||||
| </table> | ||||
|  | ||||
| <p> </p> | ||||
|  | ||||
| <h3><a name="examples"></a>Examples</h3> | ||||
|  | ||||
| <p>The following table shows the effect that call_traits has on | ||||
| various types, the table assumes that the compiler supports | ||||
| partial specialization: if it doesn't then all types behave in | ||||
| the same way as the entry for "myclass", and | ||||
| call_traits can not be used with reference or array types.</p> | ||||
|  | ||||
| <table border="0" cellpadding="7" cellspacing="1" width="766"> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%"> </td> | ||||
|         <td valign="top" colspan="5" width="85%" | ||||
|         bgcolor="#008080"><p align="center">Call_traits type:</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#008080"><p | ||||
|         align="center">Original type T</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">value_type</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">reference</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">const_reference</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">param_type</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">Applies to:</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">myclass</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">myclass</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">myclass&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const | ||||
|         myclass&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">myclass | ||||
|         const&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">All user | ||||
|         defined types.</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">int</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">int</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">int&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const | ||||
|         int&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">int const</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">All small | ||||
|         built-in types.</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">int*</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">int*</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">int*&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">int*const&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">int* const</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">All | ||||
|         pointer types.</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">int&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">int&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">int&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const | ||||
|         int&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">int&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">All | ||||
|         reference types.</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">const int&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const | ||||
|         int&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const | ||||
|         int&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const | ||||
|         int&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const | ||||
|         int&</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">All | ||||
|         constant-references.</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">int[3]</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const int*</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">int(&)[3]</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const int(&)[3]</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const int* | ||||
|         const</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">All array | ||||
|         types.</p> | ||||
|         </td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|         <td valign="top" width="17%" bgcolor="#C0C0C0"><p | ||||
|         align="center">const int[3]</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const int*</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const int(&)[3]</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const int(&)[3]</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">const int* | ||||
|         const</p> | ||||
|         </td> | ||||
|         <td valign="top" width="17%"><p align="center">All | ||||
|         constant-array types.</p> | ||||
|         </td> | ||||
|     </tr> | ||||
| </table> | ||||
|  | ||||
| <p> </p> | ||||
|  | ||||
| <h4>Example 1:</h4> | ||||
|  | ||||
| <p>The following class is a trivial class that stores some type T | ||||
| by value (see the <a href="call_traits_test.cpp">call_traits_test.cpp</a> | ||||
| file), the aim is to illustrate how each of the available | ||||
| call_traits typedefs may be used:</p> | ||||
|  | ||||
| <pre>template <class T> | ||||
| struct contained | ||||
| { | ||||
|    // define our typedefs first, arrays are stored by value | ||||
|    // so value_type is not the same as result_type: | ||||
|    typedef typename boost::call_traits<T>::param_type       param_type; | ||||
|    typedef typename boost::call_traits<T>::reference        reference; | ||||
|    typedef typename boost::call_traits<T>::const_reference  const_reference; | ||||
|    typedef T                                                value_type; | ||||
|    typedef typename boost::call_traits<T>::value_type       result_type; | ||||
|  | ||||
|    // stored value: | ||||
|    value_type v_; | ||||
|     | ||||
|    // constructors: | ||||
|    contained() {} | ||||
|    contained(param_type p) : v_(p){} | ||||
|    // return byval: | ||||
|    result_type value() { return v_; } | ||||
|    // return by_ref: | ||||
|    reference get() { return v_; } | ||||
|    const_reference const_get()const { return v_; } | ||||
|    // pass value: | ||||
|    void call(param_type p){} | ||||
|  | ||||
| };</pre> | ||||
|  | ||||
| <h4><a name="refs"></a>Example 2 (the reference to reference | ||||
| problem):</h4> | ||||
|  | ||||
| <p>Consider the definition of std::binder1st:</p> | ||||
|  | ||||
| <pre>template <class Operation>  | ||||
| class binder1st :  | ||||
|    public unary_function<typename Operation::second_argument_type, typename Operation::result_type>  | ||||
| {  | ||||
| protected:  | ||||
|    Operation op;  | ||||
|    typename Operation::first_argument_type value;  | ||||
| public:  | ||||
|    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 | ||||
| the functor takes its second argument as a reference, that | ||||
| implies that <code>Operation::second_argument_type</code> is a | ||||
| reference type, <code>operator()</code> will now end up taking a | ||||
| reference to a reference as an argument, and that is not | ||||
| currently legal. The solution here is to modify <code>operator()</code> | ||||
| to use call_traits:</p> | ||||
|  | ||||
| <pre>typename Operation::result_type operator()(typename call_traits<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 | ||||
| the no "reference to reference" occurs.</p> | ||||
|  | ||||
| <h4><a name="ex3"></a>Example 3 (the make_pair problem):</h4> | ||||
|  | ||||
| <p>If we pass the name of an array as one (or both) arguments to <code>std::make_pair</code>, | ||||
| then template argument deduction deduces the passed parameter as | ||||
| "const reference to array of T", this also applies to | ||||
| string literals (which are really array literals). Consequently | ||||
| instead of returning a pair of pointers, it tries to return a | ||||
| pair of arrays, and since an array type is not copy-constructible | ||||
| the code fails to compile. One solution is to explicitly cast the | ||||
| arguments to make_pair to pointers, but call_traits provides a | ||||
| better (i.e. automatic) solution (and one that works safely even | ||||
| in generic code where the cast might do the wrong thing):</p> | ||||
|  | ||||
| <pre>template <class T1, class T2> | ||||
| std::pair< | ||||
|    typename boost::call_traits<T1>::value_type,  | ||||
|    typename boost::call_traits<T2>::value_type>  | ||||
|       make_pair(const T1& t1, const T2& t2) | ||||
| { | ||||
|    return std::pair< | ||||
|       typename boost::call_traits<T1>::value_type,  | ||||
|       typename boost::call_traits<T2>::value_type>(t1, t2); | ||||
| }</pre> | ||||
|  | ||||
| <p>Here, the deduced argument types will be automatically | ||||
| degraded to pointers if the deduced types are arrays, similar | ||||
| situations occur in the standard binders and adapters: in | ||||
| principle in any function that "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> | ||||
|  | ||||
| <h4><a name="ex4"></a>Example 4 (optimising fill):</h4> | ||||
|  | ||||
| <p>The call_traits template will "optimize" the passing | ||||
| of a small built-in type as a function parameter, this mainly has | ||||
| an effect when the parameter is used within a loop body. In the | ||||
| following example (see <a href="algo_opt_examples.cpp">algo_opt_examples.cpp</a>), | ||||
| a version of std::fill is optimized in two ways: if the type | ||||
| passed is a single byte built-in type then std::memset is used to | ||||
| effect the fill, otherwise a conventional C++ implemention is | ||||
| used, but with the passed parameter "optimized" using | ||||
| call_traits:</p> | ||||
|  | ||||
| <pre>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); | ||||
|    { | ||||
|       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) | ||||
|    { | ||||
|       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); | ||||
| }</pre> | ||||
|  | ||||
| <p>Footnote: the reason that this is "optimal" for | ||||
| small built-in types is that with the value passed as "T | ||||
| const" instead of "const T&" the compiler is | ||||
| able to tell both that the value is constant and that it is free | ||||
| of aliases. With this information the compiler is able to cache | ||||
| the passed value in a register, unroll the loop, or use | ||||
| explicitly parallel instructions: if any of these are supported. | ||||
| Exactly how much mileage you will get from this depends upon your | ||||
| compiler - we could really use some accurate benchmarking | ||||
| software as part of boost for cases like this.</p> | ||||
|  | ||||
| <p>Note that the function arguments to fill are not expressed in | ||||
| terms of call_traits: doing so would prevent template argument | ||||
| deduction from functioning. Instead fill acts as a "thin | ||||
| wrapper" that is there to perform template argument | ||||
| deduction, the compiler will optimise away the call to fill all | ||||
| together, replacing it with the call to filler<>::do_fill, | ||||
| which does use call_traits.</p> | ||||
|  | ||||
| <h3>Rationale</h3> | ||||
|  | ||||
| <p>The following notes are intended to briefly describe the | ||||
| rational behind choices made in call_traits.</p> | ||||
|  | ||||
| <p>All user-defined types follow "existing practice" | ||||
| and need no comment.</p> | ||||
|  | ||||
| <p>Small built-in types (what the standard calls fundamental | ||||
| types [3.9.1]) differ from existing practice only in the <i>param_type</i> | ||||
| typedef. In this case passing "T const" is compatible | ||||
| with existing practice, but may improve performance in some cases | ||||
| (see <a href="#ex4">Example 4</a>), in any case this should never | ||||
| be any worse than existing practice.</p> | ||||
|  | ||||
| <p>Pointers follow the same rational as small built-in types.</p> | ||||
|  | ||||
| <p>For reference types the rational follows <a href="#refs">Example | ||||
| 2</a> - references to references are not allowed, so the | ||||
| call_traits members must be defined such that these problems do | ||||
| not occur. There is a proposal to modify the language such that | ||||
| "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 | ||||
| other words it's a workaround).</p> | ||||
|  | ||||
| <p>For array types, a function that takes an array as an argument | ||||
| will degrade the array type to a pointer type: this means that | ||||
| the type of the actual parameter is different from its declared | ||||
| type, something that can cause endless problems in template code | ||||
| that relies on the declared type of a parameter. For example:</p> | ||||
|  | ||||
| <pre>template <class T> | ||||
| 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> | ||||
|  | ||||
| <pre>template <class T> | ||||
| void A<T>::foo(T t) | ||||
| { | ||||
|    T dup(t); // doesn't compile for case that T is an array. | ||||
| }</pre> | ||||
|  | ||||
| <p>By using call_traits the degradation from array to pointer is | ||||
| explicit, and the type of the parameter is the same as it's | ||||
| declared type:</p> | ||||
|  | ||||
| <pre>template <class T> | ||||
| struct A | ||||
| { | ||||
|    void foo(typename call_traits<T>::value_type t); | ||||
| }; | ||||
|  | ||||
| template <class T> | ||||
| void A<T>::foo(typename call_traits<T>::value_type t) | ||||
| { | ||||
|    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 | ||||
| returned, not a copy of the whole array, and again call_traits | ||||
| makes the degradation explicit. The value_type member is useful | ||||
| whenever an array must be explicitly degraded to a pointer - <a | ||||
| href="#ex3">Example 3</a> provides the test case (Footnote: the | ||||
| array specialisation for call_traits is the least well understood | ||||
| of all the call_traits specialisations, if the given semantics | ||||
| cause specific problems for you, or don't solve a particular | ||||
| array-related problem, then I would be interested to hear about | ||||
| it. Most people though will probably never need to use this | ||||
| specialisation).</p> | ||||
|  | ||||
| <hr> | ||||
|  | ||||
| <p>Revised 01 September 2000</p> | ||||
|  | ||||
| <p><EFBFBD> Copyright boost.org 2000. Permission to copy, use, modify, | ||||
| sell and distribute this document is granted provided this | ||||
| copyright notice appears in all copies. This document is provided | ||||
| "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> | ||||
|  | ||||
| <p>.</p> | ||||
|  | ||||
| <p> </p> | ||||
|  | ||||
| <p> </p> | ||||
| </body> | ||||
| </html> | ||||
| @@ -1,375 +0,0 @@ | ||||
|  // boost::compressed_pair test program    | ||||
|      | ||||
|  //  (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and    | ||||
|  //  distribute this software is granted provided this copyright notice appears    | ||||
|  //  in all copies. This software is provided "as is" without express or implied    | ||||
|  //  warranty, and with no claim as to its suitability for any purpose.    | ||||
|  | ||||
| // standalone test program for <boost/call_traits.hpp> | ||||
| // 03 Oct 2000: | ||||
| //    Enabled extra tests for VC6. | ||||
|  | ||||
| #include <cassert> | ||||
| #include <iostream> | ||||
| #include <iomanip> | ||||
| #include <algorithm> | ||||
| #include <typeinfo> | ||||
| #include <boost/call_traits.hpp> | ||||
|  | ||||
| #include <boost/type_traits/type_traits_test.hpp> | ||||
| // | ||||
| // struct contained models a type that contains a type (for example std::pair) | ||||
| // arrays are contained by value, and have to be treated as a special case: | ||||
| // | ||||
| template <class T> | ||||
| struct contained | ||||
| { | ||||
|    // define our typedefs first, arrays are stored by value | ||||
|    // so value_type is not the same as result_type: | ||||
|    typedef typename boost::call_traits<T>::param_type       param_type; | ||||
|    typedef typename boost::call_traits<T>::reference        reference; | ||||
|    typedef typename boost::call_traits<T>::const_reference  const_reference; | ||||
|    typedef T                                                value_type; | ||||
|    typedef typename boost::call_traits<T>::value_type       result_type; | ||||
|  | ||||
|    // stored value: | ||||
|    value_type v_; | ||||
|     | ||||
|    // constructors: | ||||
|    contained() {} | ||||
|    contained(param_type p) : v_(p){} | ||||
|    // return byval: | ||||
|    result_type value()const { return v_; } | ||||
|    // return by_ref: | ||||
|    reference get() { return v_; } | ||||
|    const_reference const_get()const { return v_; } | ||||
|    // pass value: | ||||
|    void call(param_type p){} | ||||
|  | ||||
| }; | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template <class T, std::size_t N> | ||||
| struct contained<T[N]> | ||||
| { | ||||
|    typedef typename boost::call_traits<T[N]>::param_type       param_type; | ||||
|    typedef typename boost::call_traits<T[N]>::reference        reference; | ||||
|    typedef typename boost::call_traits<T[N]>::const_reference  const_reference; | ||||
|    typedef T                                                   value_type[N]; | ||||
|    typedef typename boost::call_traits<T[N]>::value_type       result_type; | ||||
|  | ||||
|    value_type v_; | ||||
|  | ||||
|    contained(param_type p) | ||||
|    { | ||||
|       std::copy(p, p+N, v_); | ||||
|    } | ||||
|    // return byval: | ||||
|    result_type value()const { return v_; } | ||||
|    // return by_ref: | ||||
|    reference get() { return v_; } | ||||
|    const_reference const_get()const { return v_; } | ||||
|    void call(param_type p){} | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| template <class T> | ||||
| contained<typename boost::call_traits<T>::value_type> wrap(const T& t) | ||||
| { | ||||
|    typedef typename boost::call_traits<T>::value_type ct; | ||||
|    return contained<ct>(t); | ||||
| } | ||||
|  | ||||
| namespace test{ | ||||
|  | ||||
| template <class T1, class T2> | ||||
| std::pair< | ||||
|    typename boost::call_traits<T1>::value_type, | ||||
|    typename boost::call_traits<T2>::value_type> | ||||
|       make_pair(const T1& t1, const T2& t2) | ||||
| { | ||||
|    return std::pair< | ||||
|       typename boost::call_traits<T1>::value_type, | ||||
|       typename boost::call_traits<T2>::value_type>(t1, t2); | ||||
| } | ||||
|  | ||||
| } // namespace test | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| // | ||||
| // struct call_traits_checker: | ||||
| // verifies behaviour of contained example: | ||||
| // | ||||
| template <class T> | ||||
| struct call_traits_checker | ||||
| { | ||||
|    typedef typename boost::call_traits<T>::param_type param_type; | ||||
|    void operator()(param_type); | ||||
| }; | ||||
|  | ||||
| template <class T> | ||||
| void call_traits_checker<T>::operator()(param_type p) | ||||
| { | ||||
|    T t(p); | ||||
|    contained<T> c(t); | ||||
|    cout << "checking contained<" << typeid(T).name() << ">..." << endl; | ||||
|    assert(t == c.value()); | ||||
|    assert(t == c.get()); | ||||
|    assert(t == c.const_get()); | ||||
|  | ||||
|    //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; | ||||
| } | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template <class T, std::size_t N> | ||||
| struct call_traits_checker<T[N]> | ||||
| { | ||||
|    typedef typename boost::call_traits<T[N]>::param_type param_type; | ||||
|    void operator()(param_type t) | ||||
|    { | ||||
|       contained<T[N]> c(t); | ||||
|       cout << "checking contained<" << typeid(T[N]).name() << ">..." << endl; | ||||
|       unsigned int i = 0; | ||||
|       for(i = 0; i < N; ++i) | ||||
|          assert(t[i] == c.value()[i]); | ||||
|       for(i = 0; i < N; ++i) | ||||
|          assert(t[i] == c.get()[i]); | ||||
|       for(i = 0; i < N; ++i) | ||||
|          assert(t[i] == c.const_get()[i]); | ||||
|  | ||||
|       cout << "typeof contained<" << typeid(T[N]).name() << ">::v_ is:         " << typeid(&contained<T[N]>::v_).name() << endl; | ||||
|       cout << "typeof contained<" << typeid(T[N]).name() << ">::value is:      " << typeid(&contained<T[N]>::value).name() << endl; | ||||
|       cout << "typeof contained<" << typeid(T[N]).name() << ">::get is:        " << typeid(&contained<T[N]>::get).name() << endl; | ||||
|       cout << "typeof contained<" << typeid(T[N]).name() << ">::const_get is:  " << typeid(&contained<T[N]>::const_get).name() << endl; | ||||
|       cout << "typeof contained<" << typeid(T[N]).name() << ">::call is:       " << typeid(&contained<T[N]>::call).name() << endl; | ||||
|       cout << endl; | ||||
|    } | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| // | ||||
| // check_wrap: | ||||
| template <class T, class U> | ||||
| void check_wrap(const contained<T>& w, const U& u) | ||||
| { | ||||
|    cout << "checking contained<" << typeid(T).name() << ">..." << endl; | ||||
|    assert(w.value() == u); | ||||
| } | ||||
|  | ||||
| // | ||||
| // check_make_pair: | ||||
| // verifies behaviour of "make_pair": | ||||
| // | ||||
| template <class T, class U, class V> | ||||
| void check_make_pair(T c, U u, V v) | ||||
| { | ||||
|    cout << "checking std::pair<" << typeid(c.first).name() << ", " << typeid(c.second).name() << ">..." << endl; | ||||
|    assert(c.first == u); | ||||
|    assert(c.second == v); | ||||
|    cout << endl; | ||||
| } | ||||
|  | ||||
|  | ||||
| struct comparible_UDT | ||||
| { | ||||
|    int i_; | ||||
|    comparible_UDT() : i_(2){} | ||||
|    bool operator == (const comparible_UDT& v){ return v.i_ == i_; } | ||||
| }; | ||||
|  | ||||
| int main(int argc, char *argv[ ]) | ||||
| { | ||||
|    call_traits_checker<comparible_UDT> c1; | ||||
|    comparible_UDT u; | ||||
|    c1(u); | ||||
|    call_traits_checker<int> c2; | ||||
|    int i = 2; | ||||
|    c2(i); | ||||
|    int* pi = &i; | ||||
| #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) | ||||
|    call_traits_checker<int*> c3; | ||||
|    c3(pi); | ||||
|    call_traits_checker<int&> c4; | ||||
|    c4(i); | ||||
|    call_traits_checker<const int&> c5; | ||||
|    c5(i); | ||||
| #if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) | ||||
|    int a[2] = {1,2}; | ||||
|    call_traits_checker<int[2]> c6; | ||||
|    c6(a); | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
|    check_wrap(wrap(2), 2); | ||||
|    const char ca[4] = "abc"; | ||||
|    // compiler can't deduce this for some reason: | ||||
|    //check_wrap(wrap(ca), ca); | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|    check_wrap(wrap(a), a); | ||||
|    check_make_pair(test::make_pair(a, a), a, a); | ||||
| #endif | ||||
|  | ||||
|    // cv-qualifiers applied to reference types should have no effect | ||||
|    // declare these here for later use with is_reference and remove_reference: | ||||
|    typedef int& r_type; | ||||
|    typedef const r_type cr_type; | ||||
|  | ||||
|    type_test(comparible_UDT, boost::call_traits<comparible_UDT>::value_type) | ||||
|    type_test(comparible_UDT&, boost::call_traits<comparible_UDT>::reference) | ||||
|    type_test(const comparible_UDT&, boost::call_traits<comparible_UDT>::const_reference) | ||||
|    type_test(const comparible_UDT&, boost::call_traits<comparible_UDT>::param_type) | ||||
|    type_test(int, boost::call_traits<int>::value_type) | ||||
|    type_test(int&, boost::call_traits<int>::reference) | ||||
|    type_test(const int&, boost::call_traits<int>::const_reference) | ||||
|    type_test(const int, boost::call_traits<int>::param_type) | ||||
|    type_test(int*, boost::call_traits<int*>::value_type) | ||||
|    type_test(int*&, boost::call_traits<int*>::reference) | ||||
|    type_test(int*const&, boost::call_traits<int*>::const_reference) | ||||
|    type_test(int*const, boost::call_traits<int*>::param_type) | ||||
| #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) | ||||
|    type_test(int&, boost::call_traits<int&>::value_type) | ||||
|    type_test(int&, boost::call_traits<int&>::reference) | ||||
|    type_test(const int&, boost::call_traits<int&>::const_reference) | ||||
|    type_test(int&, boost::call_traits<int&>::param_type) | ||||
| #if !(defined(__GNUC__) && (__GNUC__ < 3)) | ||||
|    type_test(int&, boost::call_traits<cr_type>::value_type) | ||||
|    type_test(int&, boost::call_traits<cr_type>::reference) | ||||
|    type_test(const int&, boost::call_traits<cr_type>::const_reference) | ||||
|    type_test(int&, boost::call_traits<cr_type>::param_type) | ||||
| #else | ||||
|    std::cout << "Your compiler cannot instantiate call_traits<int&const>, skipping four tests (4 errors)" << std::endl; | ||||
|    failures += 4; | ||||
|    test_count += 4; | ||||
| #endif | ||||
|    type_test(const int&, boost::call_traits<const int&>::value_type) | ||||
|    type_test(const int&, boost::call_traits<const int&>::reference) | ||||
|    type_test(const int&, boost::call_traits<const int&>::const_reference) | ||||
|    type_test(const int&, boost::call_traits<const int&>::param_type) | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|    type_test(const int*, boost::call_traits<int[3]>::value_type) | ||||
|    type_test(int(&)[3], boost::call_traits<int[3]>::reference) | ||||
|    type_test(const int(&)[3], boost::call_traits<int[3]>::const_reference) | ||||
|    type_test(const int*const, boost::call_traits<int[3]>::param_type) | ||||
|    type_test(const int*, boost::call_traits<const int[3]>::value_type) | ||||
|    type_test(const int(&)[3], boost::call_traits<const int[3]>::reference) | ||||
|    type_test(const int(&)[3], boost::call_traits<const int[3]>::const_reference) | ||||
|    type_test(const int*const, boost::call_traits<const int[3]>::param_type) | ||||
| #else | ||||
|    std::cout << "You're compiler does not support partial template instantiation, skipping 8 tests (8 errors)" << std::endl; | ||||
|    failures += 8; | ||||
|    test_count += 8; | ||||
| #endif | ||||
| #else | ||||
|    std::cout << "You're compiler does not support partial template instantiation, skipping 20 tests (20 errors)" << std::endl; | ||||
|    failures += 20; | ||||
|    test_count += 20; | ||||
| #endif | ||||
|  | ||||
|    return check_result(argc, argv); | ||||
| } | ||||
|  | ||||
| // | ||||
| // define call_traits tests to check that the assertions in the docs do actually work | ||||
| // this is an instantiate only set of tests: | ||||
| // | ||||
| template <typename T, bool isarray = false> | ||||
| struct call_traits_test | ||||
| { | ||||
|    typedef ::boost::call_traits<T> ct; | ||||
|    typedef typename ct::param_type param_type; | ||||
|    typedef typename ct::reference reference; | ||||
|    typedef typename ct::const_reference const_reference; | ||||
|    typedef typename ct::value_type value_type; | ||||
|    static void assert_construct(param_type val); | ||||
| }; | ||||
|  | ||||
| template <typename T, bool isarray> | ||||
| void call_traits_test<T, isarray>::assert_construct(typename call_traits_test<T, isarray>::param_type val) | ||||
| { | ||||
|    // | ||||
|    // this is to check that the call_traits assertions are valid: | ||||
|    T t(val); | ||||
|    value_type v(t); | ||||
|    reference r(t); | ||||
|    const_reference cr(t); | ||||
|    param_type p(t); | ||||
|    value_type v2(v); | ||||
|    value_type v3(r); | ||||
|    value_type v4(p); | ||||
|    reference r2(v); | ||||
|    reference r3(r); | ||||
|    const_reference cr2(v); | ||||
|    const_reference cr3(r); | ||||
|    const_reference cr4(cr); | ||||
|    const_reference cr5(p); | ||||
|    param_type p2(v); | ||||
|    param_type p3(r); | ||||
|    param_type p4(p); | ||||
| } | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template <typename T> | ||||
| struct call_traits_test<T, true> | ||||
| { | ||||
|    typedef ::boost::call_traits<T> ct; | ||||
|    typedef typename ct::param_type param_type; | ||||
|    typedef typename ct::reference reference; | ||||
|    typedef typename ct::const_reference const_reference; | ||||
|    typedef typename ct::value_type value_type; | ||||
|    static void assert_construct(param_type val); | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| void call_traits_test<T, true>::assert_construct(typename boost::call_traits<T>::param_type val) | ||||
| { | ||||
|    // | ||||
|    // this is to check that the call_traits assertions are valid: | ||||
|    T t; | ||||
|    value_type v(t); | ||||
|    value_type v5(val); | ||||
|    reference r = t; | ||||
|    const_reference cr = t; | ||||
|    reference r2 = r; | ||||
|    #ifndef __BORLANDC__ | ||||
|    // C++ Builder buglet: | ||||
|    const_reference cr2 = r; | ||||
|    #endif | ||||
|    param_type p(t); | ||||
|    value_type v2(v); | ||||
|    const_reference cr3 = cr; | ||||
|    value_type v3(r); | ||||
|    value_type v4(p); | ||||
|    param_type p2(v); | ||||
|    param_type p3(r); | ||||
|    param_type p4(p); | ||||
| } | ||||
| #endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| // | ||||
| // now check call_traits assertions by instantiating call_traits_test: | ||||
| template struct call_traits_test<int>; | ||||
| template struct call_traits_test<const int>; | ||||
| template struct call_traits_test<int*>; | ||||
| #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) | ||||
| template struct call_traits_test<int&>; | ||||
| template struct call_traits_test<const int&>; | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template struct call_traits_test<int[2], true>; | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #ifdef BOOST_MSVC | ||||
| unsigned int expected_failures = 10; | ||||
| #elif defined(__BORLANDC__) | ||||
| unsigned int expected_failures = 2; | ||||
| #elif defined(__GNUC__) | ||||
| unsigned int expected_failures = 4; | ||||
| #else | ||||
| unsigned int expected_failures = 0; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| @@ -1,92 +0,0 @@ | ||||
| <html> | ||||
|  | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" | ||||
| content="text/html; charset=iso-8859-1"> | ||||
| <meta name="Template" | ||||
| content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot"> | ||||
| <meta name="GENERATOR" content="Microsoft FrontPage Express 2.0"> | ||||
| <title>Header <boost/compressed_pair.hpp></title> | ||||
| </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> | ||||
|  | ||||
| <p>All of the contents of <boost/compressed_pair.hpp> are | ||||
| defined inside namespace boost.</p> | ||||
|  | ||||
| <p>The class compressed pair is very similar to std::pair, but if | ||||
| either of the template arguments are empty classes, then the | ||||
| "empty member optimisation" is applied to compress the | ||||
| size of the pair.</p> | ||||
|  | ||||
| <pre>template <class T1, class T2> | ||||
| class compressed_pair | ||||
| { | ||||
| public: | ||||
| 	typedef T1                                                 first_type; | ||||
| 	typedef T2                                                 second_type; | ||||
| 	typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
| 	typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
| 	typedef typename call_traits<first_type>::reference        first_reference; | ||||
| 	typedef typename call_traits<second_type>::reference       second_reference; | ||||
| 	typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
| 	typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
| 	         compressed_pair() : base() {} | ||||
| 	         compressed_pair(first_param_type x, second_param_type y); | ||||
| 	explicit compressed_pair(first_param_type x); | ||||
| 	explicit compressed_pair(second_param_type y); | ||||
|  | ||||
| 	first_reference       first(); | ||||
| 	first_const_reference first() const; | ||||
|  | ||||
| 	second_reference       second(); | ||||
| 	second_const_reference second() const; | ||||
|  | ||||
| 	void swap(compressed_pair& y); | ||||
| };</pre> | ||||
|  | ||||
| <p>The two members of the pair can be accessed using the member | ||||
| functions first() and second(). Note that not all member | ||||
| functions can be instantiated for all template parameter types. | ||||
| In particular compressed_pair can be instantiated for reference | ||||
| and array types, however in these cases the range of constructors | ||||
| that can be used are limited. If types T1 and T2 are the same | ||||
| type, then there is only one version of the single-argument | ||||
| constructor, and this constructor initialises both values in the | ||||
| pair to the passed value.</p> | ||||
|  | ||||
| <p>Note that compressed_pair can not be instantiated if either of | ||||
| the template arguments is an enumerator type, unless there is | ||||
| compiler support for boost::is_enum, or if boost::is_enum is | ||||
| specialised for the enumerator 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> | ||||
|  | ||||
| <hr> | ||||
|  | ||||
| <p>Revised 08 March 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> | ||||
|  | ||||
| <p> </p> | ||||
| </body> | ||||
| </html> | ||||
| @@ -1,154 +0,0 @@ | ||||
|  // boost::compressed_pair test program    | ||||
|      | ||||
|  //  (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and    | ||||
|  //  distribute this software is granted provided this copyright notice appears    | ||||
|  //  in all copies. This software is provided "as is" without express or implied    | ||||
|  //  warranty, and with no claim as to its suitability for any purpose.    | ||||
|  | ||||
| // standalone test program for <boost/compressed_pair.hpp> | ||||
| // Revised 03 Oct 2000:  | ||||
| //    Enabled tests for VC6. | ||||
|  | ||||
| #include <iostream> | ||||
| #include <typeinfo> | ||||
| #include <cassert> | ||||
|  | ||||
| #include <boost/compressed_pair.hpp> | ||||
| #include <boost/type_traits/type_traits_test.hpp> | ||||
|  | ||||
| using namespace boost; | ||||
|  | ||||
| namespace boost { | ||||
| #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | ||||
| template <> struct is_empty<empty_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct is_empty<empty_POD_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct is_POD<empty_POD_UDT> | ||||
| { static const bool value = true; }; | ||||
| #else | ||||
| template <> struct is_empty<empty_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct is_empty<empty_POD_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct is_POD<empty_POD_UDT> | ||||
| { enum{ value = true }; }; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| struct non_empty1 | ||||
| {  | ||||
|    int i; | ||||
|    non_empty1() : i(1){} | ||||
|    non_empty1(int v) : i(v){} | ||||
|    friend bool operator==(const non_empty1& a, const non_empty1& b) | ||||
|    { return a.i == b.i; } | ||||
| }; | ||||
|  | ||||
| struct non_empty2 | ||||
| {  | ||||
|    int i; | ||||
|    non_empty2() : i(3){} | ||||
|    non_empty2(int v) : i(v){} | ||||
|    friend bool operator==(const non_empty2& a, const non_empty2& b) | ||||
|    { return a.i == b.i; } | ||||
| }; | ||||
|  | ||||
| int main(int argc, char *argv[ ]) | ||||
| { | ||||
|    compressed_pair<int, double> cp1(1, 1.3); | ||||
|    assert(cp1.first() == 1); | ||||
|    assert(cp1.second() == 1.3); | ||||
|    compressed_pair<int, double> cp1b(2, 2.3); | ||||
|    assert(cp1b.first() == 2); | ||||
|    assert(cp1b.second() == 2.3); | ||||
|    swap(cp1, cp1b); | ||||
|    assert(cp1b.first() == 1); | ||||
|    assert(cp1b.second() == 1.3); | ||||
|    assert(cp1.first() == 2); | ||||
|    assert(cp1.second() == 2.3); | ||||
|    compressed_pair<non_empty1, non_empty2> cp1c(non_empty1(9)); | ||||
|    assert(cp1c.second() == non_empty2()); | ||||
|    assert(cp1c.first() == non_empty1(9)); | ||||
|    compressed_pair<non_empty1, non_empty2> cp1d(non_empty2(9)); | ||||
|    assert(cp1d.second() == non_empty2(9)); | ||||
|    assert(cp1d.first() == non_empty1()); | ||||
|  | ||||
|    compressed_pair<int, double> cp1e(cp1); | ||||
|  | ||||
|    compressed_pair<empty_UDT, int> cp2(2); | ||||
|    assert(cp2.second() == 2); | ||||
|    compressed_pair<int, empty_UDT> cp3(1); | ||||
|    assert(cp3.first() ==1); | ||||
|    compressed_pair<empty_UDT, empty_UDT> cp4; | ||||
|    compressed_pair<empty_UDT, empty_POD_UDT> cp5; | ||||
|    compressed_pair<int, empty_UDT> cp9(empty_UDT()); | ||||
|    compressed_pair<int, empty_UDT> cp10(1); | ||||
|    assert(cp10.first() == 1); | ||||
| #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) || !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) | ||||
|    int i = 0; | ||||
|    compressed_pair<int&, int&> cp6(i,i); | ||||
|    assert(cp6.first() == i); | ||||
|    assert(cp6.second() == i); | ||||
|    assert(&cp6.first() == &i); | ||||
|    assert(&cp6.second() == &i); | ||||
|    compressed_pair<int, double[2]> cp7; | ||||
|    cp7.first(); | ||||
|    double* pd = cp7.second(); | ||||
| #endif | ||||
|    soft_value_test(true, (sizeof(compressed_pair<empty_UDT, int>) < sizeof(std::pair<empty_UDT, int>))) | ||||
|    soft_value_test(true, (sizeof(compressed_pair<int, empty_UDT>) < sizeof(std::pair<int, empty_UDT>))) | ||||
|    soft_value_test(true, (sizeof(compressed_pair<empty_UDT, empty_UDT>) < sizeof(std::pair<empty_UDT, empty_UDT>))) | ||||
|    soft_value_test(true, (sizeof(compressed_pair<empty_UDT, empty_POD_UDT>) < sizeof(std::pair<empty_UDT, empty_POD_UDT>))) | ||||
|    soft_value_test(true, (sizeof(compressed_pair<empty_UDT, compressed_pair<empty_POD_UDT, int> >) < sizeof(std::pair<empty_UDT, std::pair<empty_POD_UDT, int> >))) | ||||
|  | ||||
|    return check_result(argc, argv); | ||||
| } | ||||
|  | ||||
| // | ||||
| // 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 | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| #ifndef __MWERKS__ | ||||
| // | ||||
| // 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&); | ||||
| // | ||||
| // and then arrays: | ||||
| #ifndef __BORLANDC__ | ||||
| template call_traits<int[2]>::reference compressed_pair<double, int[2]>::second(); | ||||
| #endif | ||||
| template call_traits<double>::reference compressed_pair<double, int[2]>::first(); | ||||
| #if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)) | ||||
| template compressed_pair<double, int[2]>::compressed_pair(call_traits<double>::param_type); | ||||
| #endif | ||||
| template compressed_pair<double, int[2]>::compressed_pair(); | ||||
| #endif // __MWERKS__ | ||||
| #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|  | ||||
| unsigned int expected_failures = 0; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -1,325 +0,0 @@ | ||||
| <html> | ||||
|  | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | ||||
| <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> | ||||
| <meta name="ProgId" content="FrontPage.Editor.Document"> | ||||
| <title>Counting Iterator Adaptor Documentation</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000"> | ||||
|  | ||||
| <img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" | ||||
| align="center" width="277" height="86"> | ||||
|  | ||||
| <h1>Counting Iterator Adaptor</h1> | ||||
|  | ||||
| Defined in header | ||||
| <a href="../../boost/counting_iterator.hpp">boost/counting_iterator.hpp</a> | ||||
|  | ||||
| <p> | ||||
| How would you fill up a vector with the numbers zero | ||||
| through one hundred using <a | ||||
| href="http://www.sgi.com/tech/stl/copy.html"><tt>std::copy()</tt></a>? The | ||||
| only iterator operation missing from builtin integer types is an | ||||
| <tt>operator*()</tt> that returns the current | ||||
| value of the integer.  The counting iterator adaptor adds this crucial piece of | ||||
| functionality to whatever type it wraps. One can use the | ||||
| counting iterator adaptor not only with integer types, but with any | ||||
| type that is <tt>Incrementable</tt> (see type requirements <a href="#requirements">below</a>).  The | ||||
| following <b>pseudo-code</b> shows the general idea of how the | ||||
| counting iterator is implemented. | ||||
| </p> | ||||
|  | ||||
| <pre> | ||||
|   // inside a hypothetical counting_iterator class... | ||||
|   typedef Incrementable value_type; | ||||
|   value_type counting_iterator::operator*() const { | ||||
|     return this->base; // no dereference! | ||||
|   } | ||||
| </pre> | ||||
|  | ||||
| All of the other operators of the counting iterator behave in the same | ||||
| fashion as the <tt>Incrementable</tt> base type. | ||||
|  | ||||
| <h2>Synopsis</h2> | ||||
|  | ||||
| <pre> | ||||
| namespace boost { | ||||
|   template <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 -->26 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14386" --></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 | ||||
|  --> | ||||
|  | ||||
| @@ -1,53 +0,0 @@ | ||||
| // (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and | ||||
| // distribute this software is granted provided this copyright notice appears | ||||
| // in all copies. This software is provided "as is" without express or implied | ||||
| // warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <iostream> | ||||
| #include <iterator> | ||||
| #include <vector> | ||||
| #include <boost/counting_iterator.hpp> | ||||
| #include <boost/iterator_adaptors.hpp> | ||||
|  | ||||
| int main(int, char*[]) | ||||
| { | ||||
|   // Example of using counting_iterator_generator | ||||
|   std::cout << "counting from 0 to 4:" << std::endl; | ||||
|   boost::counting_iterator_generator<int>::type first(0), last(4); | ||||
|   std::copy(first, last, std::ostream_iterator<int>(std::cout, " ")); | ||||
|   std::cout << std::endl; | ||||
|  | ||||
|   // Example of using make_counting_iterator() | ||||
|   std::cout << "counting from -5 to 4:" << std::endl; | ||||
|   std::copy(boost::make_counting_iterator(-5), | ||||
| 	    boost::make_counting_iterator(5), | ||||
| 	    std::ostream_iterator<int>(std::cout, " ")); | ||||
|   std::cout << std::endl; | ||||
|  | ||||
|   // Example of using counting iterator to create an array of pointers. | ||||
|   const int N = 7; | ||||
|   std::vector<int> numbers; | ||||
|   // Fill "numbers" array with [0,N) | ||||
|   std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N), | ||||
| 	    std::back_inserter(numbers)); | ||||
|  | ||||
|   std::vector<std::vector<int>::iterator> pointers; | ||||
|  | ||||
|   // Use counting iterator to fill in the array of pointers. | ||||
|   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; | ||||
| } | ||||
| @@ -1,263 +0,0 @@ | ||||
| // (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and | ||||
| // distribute this software is granted provided this copyright notice appears in | ||||
| // all copies. This software is provided "as is" without express or implied | ||||
| // warranty, and with no claim as to its suitability for any purpose. | ||||
| // | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
| // | ||||
| // Revision History | ||||
| // 16 Feb 2001  Added a missing const. Made the tests run (somewhat) with | ||||
| //              plain MSVC again. (David Abrahams) | ||||
| // 11 Feb 2001  #if 0'd out use of counting_iterator on non-numeric types in | ||||
| //              MSVC without STLport, so that the other tests may proceed | ||||
| //              (David Abrahams) | ||||
| // 04 Feb 2001  Added use of iterator_tests.hpp (David Abrahams) | ||||
| // 28 Jan 2001  Removed not_an_iterator detritus (David Abrahams) | ||||
| // 24 Jan 2001  Initial revision (David Abrahams) | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #ifdef BOOST_MSVC | ||||
| # pragma warning(disable:4786) // identifier truncated in debug info | ||||
| #endif | ||||
|  | ||||
| #include <boost/pending/iterator_tests.hpp> | ||||
| #include <boost/counting_iterator.hpp> | ||||
| #include <boost/detail/iterator.hpp> | ||||
| #include <iostream> | ||||
| #include <climits> | ||||
| #include <iterator> | ||||
| #include <stdlib.h> | ||||
| #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; | ||||
| } | ||||
| @@ -1,273 +0,0 @@ | ||||
| <html> | ||||
|  | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | ||||
| <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> | ||||
| <meta name="ProgId" content="FrontPage.Editor.Document"> | ||||
| <title>Filter Iterator Adaptor Documentation</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000"> | ||||
|  | ||||
| <img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" | ||||
| align="center" width="277" height="86"> | ||||
|  | ||||
| <h1>Filter Iterator Adaptor</h1> | ||||
|  | ||||
| Defined in header | ||||
| <a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a> | ||||
|  | ||||
|  | ||||
| <p> | ||||
| The filter iterator adaptor creates a view of an iterator range in | ||||
| which some elements of the range are skipped over. A <a | ||||
| href="http://www.sgi.com/tech/stl/Predicate.html">Predicate</a> | ||||
| function object controls which elements are skipped. When the | ||||
| predicate is applied to an element, if it returns <tt>true</tt> then | ||||
| the element is retained and if it returns <tt>false</tt> then the | ||||
| element is skipped over. | ||||
|  | ||||
|  | ||||
| <h2>Synopsis</h2> | ||||
|  | ||||
| <pre> | ||||
| namespace boost { | ||||
|   template <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="www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> or <a | ||||
| href="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 -->18 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14389" --></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> | ||||
| @@ -1,53 +0,0 @@ | ||||
| // Example of using the filter iterator adaptor from | ||||
| // boost/iterator_adaptors.hpp. | ||||
|  | ||||
| //  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, | ||||
| //  sell and distribute this software is granted provided this | ||||
| //  copyright notice appears in all copies. This software is provided | ||||
| //  "as is" without express or implied warranty, and with no claim as | ||||
| //  to its suitability for any purpose. | ||||
|  | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <algorithm> | ||||
| #include <functional> | ||||
| #include <iostream> | ||||
| #include <boost/iterator_adaptors.hpp> | ||||
|  | ||||
| struct is_positive_number { | ||||
|   bool operator()(int x) { return 0 < x; } | ||||
| }; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|   int numbers[] = { 0, -1, 4, -3, 5, 8, -2 }; | ||||
|   const int N = sizeof(numbers)/sizeof(int); | ||||
|  | ||||
|   // 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; | ||||
| } | ||||
| @@ -1,41 +0,0 @@ | ||||
| // (C) Copyright Jeremy Siek 2001. Permission to copy, use, modify, | ||||
| // sell and distribute this software is granted provided this | ||||
| // copyright notice appears in all copies. This software is provided | ||||
| // "as is" without express or implied warranty, and with no claim as | ||||
| // to its suitability for any purpose. | ||||
|  | ||||
| // Revision History: | ||||
|  | ||||
| // 27 Feb 2001   Jeremy Siek | ||||
| //      Initial checkin. | ||||
|  | ||||
| #include <iostream> | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| #include <boost/function_output_iterator.hpp> | ||||
|  | ||||
| struct string_appender { | ||||
|   string_appender(std::string& s) : m_str(s) { } | ||||
|   void operator()(const std::string& x) const { | ||||
|     m_str += x; | ||||
|   } | ||||
|   std::string& m_str; | ||||
| }; | ||||
|  | ||||
| int main(int, char*[]) | ||||
| { | ||||
|   std::vector<std::string> x; | ||||
|   x.push_back("hello"); | ||||
|   x.push_back(" "); | ||||
|   x.push_back("world"); | ||||
|   x.push_back("!"); | ||||
|  | ||||
|   std::string s = ""; | ||||
|   std::copy(x.begin(), x.end(),  | ||||
| 	    boost::make_function_output_iterator(string_appender(s))); | ||||
|    | ||||
|   std::cout << s << std::endl; | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
| @@ -1,169 +0,0 @@ | ||||
| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN"> | ||||
|  | ||||
| <html> | ||||
| <head> | ||||
|     <meta name="generator" content="HTML Tidy, see www.w3.org"> | ||||
|     <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | ||||
|     <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> | ||||
|     <meta name="ProgId" content="FrontPage.Editor.Document"> | ||||
|  | ||||
|     <title>Function Output Iterator Adaptor Documentation</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000"> | ||||
|          | ||||
|     <img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align= | ||||
|     "center" width="277" height="86">  | ||||
|  | ||||
|     <h1>Function Output Iterator Adaptor</h1> | ||||
|     Defined in header <a href= | ||||
|     "../../boost/function_output_iterator.hpp">boost/function_output_iterator.hpp</a>  | ||||
|  | ||||
|     <p>The function output iterator adaptor makes it easier to create | ||||
|     custom output iterators. The adaptor takes a <a | ||||
|     href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary | ||||
|     Function</a> and creates a model of <a | ||||
|     href="http://www.sgi.com/tech/stl/OutputIterator.html">Output | ||||
|     Iterator</a>. Each item assigned to the output iterator is passed | ||||
|     as an argument to the unary function.  The motivation for this | ||||
|     iterator is that creating a C++ Standard conforming output | ||||
|     iterator is non-trivial, particularly because the proper | ||||
|     implementation usually requires a proxy object. On the other hand, | ||||
|     creating a function (or function object) is much simpler. | ||||
|  | ||||
|     <h2>Synopsis</h2> | ||||
|  | ||||
|     <blockquote> | ||||
| <pre> | ||||
| namespace boost { | ||||
|   template <class UnaryFunction> | ||||
|   class function_output_iterator; | ||||
|  | ||||
|   template <class UnaryFunction> | ||||
|   function_output_iterator<UnaryFunction> | ||||
|   make_function_output_iterator(const UnaryFunction& f = UnaryFunction()) | ||||
| } | ||||
| </pre> | ||||
|     </blockquote> | ||||
|  | ||||
|     <h3>Example</h3> | ||||
|      | ||||
|     In this example we create an output iterator that appends | ||||
|     each item onto the end of a string, using the <tt>string_appender</tt> | ||||
|     function.  | ||||
|  | ||||
|     <blockquote> | ||||
| <pre> | ||||
| #include <iostream> | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| #include <boost/function_output_iterator.hpp> | ||||
|  | ||||
| struct string_appender { | ||||
|   string_appender(std::string& s) : m_str(s) { } | ||||
|   void operator()(const std::string& x) const { | ||||
|     m_str += x; | ||||
|   } | ||||
|   std::string& m_str; | ||||
| }; | ||||
|  | ||||
| int main(int, char*[]) | ||||
| { | ||||
|   std::vector<std::string> x; | ||||
|   x.push_back("hello"); | ||||
|   x.push_back(" "); | ||||
|   x.push_back("world"); | ||||
|   x.push_back("!"); | ||||
|  | ||||
|   std::string s = ""; | ||||
|   std::copy(x.begin(), x.end(),  | ||||
|             boost::make_function_output_iterator(string_appender(s))); | ||||
|    | ||||
|   std::cout << s << std::endl; | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
| </pre> | ||||
|     </blockquote> | ||||
|  | ||||
|     <hr> | ||||
|  | ||||
|     <h2><a name="function_output_iterator">The Function Output Iterator Class</a></h2> | ||||
|  | ||||
|     <blockquote> | ||||
| <pre> | ||||
| template <class UnaryFunction> | ||||
| class function_output_iterator; | ||||
| </pre> | ||||
|     </blockquote> | ||||
|  | ||||
|     The <tt>function_output_iterator</tt> class creates an <a | ||||
|     href="http://www.sgi.com/tech/stl/OutputIterator.html">Output | ||||
|     Iterator</a> out of a | ||||
|     <a href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary | ||||
|     Function</a>. Each item assigned to the output iterator is passed | ||||
|     as an argument to the unary function. | ||||
|  | ||||
|     <h3>Template Parameters</h3> | ||||
|  | ||||
|     <table border> | ||||
|       <tr> | ||||
|         <th>Parameter | ||||
|  | ||||
|         <th>Description | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>UnaryFunction</tt>  | ||||
|  | ||||
|         <td>The function type being wrapped. The return type of the | ||||
|         function is not used, so it can be <tt>void</tt>.  The | ||||
|         function must be a model of <a | ||||
|         href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary | ||||
|         Function</a>.</td> | ||||
|     </table> | ||||
|  | ||||
|     <h3>Concept Model</h3> | ||||
|     The function output iterator class is a model of <a | ||||
|     href="http://www.sgi.com/tech/stl/OutputIterator.html">Output | ||||
|     Iterator</a>. | ||||
|  | ||||
|     <h2>Members</h3> | ||||
|     The function output iterator implements the member functions | ||||
|     and operators required of the <a | ||||
|     href="http://www.sgi.com/tech/stl/OutputIterator.html">Output | ||||
|     Iterator</a> concept. In addition it has the following constructor: | ||||
| <pre> | ||||
| explicit function_output_iterator(const UnaryFunction& f = UnaryFunction()) | ||||
| </pre> | ||||
|    <br>     | ||||
|     <br> | ||||
|  | ||||
|     <hr> | ||||
|     <h2><a name="make_function_output_iterator">The Function Output Iterator Object | ||||
|     Generator</a></h2> | ||||
|  | ||||
|     The <tt>make_function_output_iterator()</tt> function provides a | ||||
|     more convenient way to create function output iterator objects. The | ||||
|     function saves the user the trouble of explicitly writing out the | ||||
|     iterator types. If the default argument is used, the function | ||||
|     type must be provided as an explicit template argument. | ||||
|  | ||||
|     <blockquote> | ||||
| <pre> | ||||
| template <class UnaryFunction> | ||||
| function_output_iterator<UnaryFunction> | ||||
| make_function_output_iterator(const UnaryFunction& f = UnaryFunction()) | ||||
| </pre> | ||||
|     </blockquote> | ||||
|  | ||||
|     <hr> | ||||
|  | ||||
|     <p>© Copyright Jeremy Siek 2001. Permission to copy, use, | ||||
|     modify, sell and distribute this document is granted provided this | ||||
|     copyright notice appears in all copies. This document is provided | ||||
|     "as is" without express or implied warranty, and with no claim as | ||||
|     to its suitability for any purpose. | ||||
|  | ||||
| </body> | ||||
| </html> | ||||
| @@ -1,366 +0,0 @@ | ||||
| // (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and | ||||
| // distribute this software is granted provided this copyright notice appears in | ||||
| // all copies. This software is provided "as is" without express or implied | ||||
| // warranty, and with no claim as to its suitability for any purpose. | ||||
| // | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
| // | ||||
| // Revision History | ||||
| // 11 Feb 2001  Compile with Borland, re-enable failing tests (David Abrahams) | ||||
| // 29 Jan 2001  Initial revision (David Abrahams) | ||||
|  | ||||
| #include <boost/half_open_range.hpp> | ||||
| #include <boost/utility.hpp> | ||||
| #include <iterator> | ||||
| #include <stdlib.h> | ||||
| #include <vector> | ||||
| #include <list> | ||||
| #include <cassert> | ||||
| #include <stdexcept> | ||||
| #ifndef BOOST_NO_LIMITS | ||||
| # include <limits> | ||||
| #endif | ||||
| #ifndef BOOST_NO_SLIST | ||||
| # include <slist> | ||||
| #endif | ||||
|  | ||||
| inline unsigned unsigned_random(unsigned max) | ||||
| { | ||||
|     return (max > 0) ? (unsigned)rand() % max : 0; | ||||
| } | ||||
|  | ||||
| // Special tests for ranges supporting random access | ||||
| template <class T> | ||||
| void category_test_1( | ||||
|     const boost::half_open_range<T>& r, std::random_access_iterator_tag) | ||||
| { | ||||
|     typedef boost::half_open_range<T> range; | ||||
|     typedef typename range::size_type size_type; | ||||
|     size_type size = r.size(); | ||||
|  | ||||
|     // pick a random offset | ||||
|     size_type offset = unsigned_random(size); | ||||
|  | ||||
|     typename range::value_type x = *(r.begin() + offset); | ||||
|     // test contains(value_type) | ||||
|     assert(r.contains(r.start()) == !r.empty()); | ||||
|     assert(!r.contains(r.finish())); | ||||
|     assert(r.contains(x) == (offset != size)); | ||||
|  | ||||
|     range::const_iterator p = r.find(x); | ||||
|     assert((p == r.end()) == (x == r.finish())); | ||||
|     assert(r.find(r.finish()) == r.end()); | ||||
|  | ||||
|     if (offset != size) | ||||
|     { | ||||
|         assert(x == r[offset]); | ||||
|         assert(x == r.at(offset)); | ||||
|     } | ||||
|  | ||||
|     bool caught_out_of_range = false; | ||||
|     try { | ||||
|         bool never_initialized = x == r.at(size); | ||||
|         (void)never_initialized; | ||||
|     } | ||||
|     catch(std::out_of_range&) | ||||
|     { | ||||
|         caught_out_of_range = true; | ||||
|     } | ||||
|     catch(...) | ||||
|     { | ||||
|     } | ||||
|     assert(caught_out_of_range); | ||||
| } | ||||
|  | ||||
| // Those tests must be skipped for other ranges | ||||
| template <class T> | ||||
| void category_test_1( | ||||
|     const boost::half_open_range<T>&, std::forward_iterator_tag) | ||||
| { | ||||
| } | ||||
|  | ||||
| unsigned indices[][2] = { {0,0},{0,1},{0,2},{0,3}, | ||||
|                                 {1,1},{1,2},{1,3}, | ||||
|                                       {2,2},{2,3}, | ||||
|                                             {3,3}}; | ||||
|  | ||||
| template <class Range> | ||||
| void category_test_2( | ||||
|     const std::vector<Range>& ranges, unsigned i, unsigned j, std::random_access_iterator_tag) | ||||
| { | ||||
|     typedef Range range; | ||||
|     const range& ri = ranges[i]; | ||||
|     const range& rj = ranges[j]; | ||||
|  | ||||
|     if (indices[i][0] <= indices[j][0] && indices[i][1] >= indices[j][1]) | ||||
|         assert(ri.contains(rj)); | ||||
|  | ||||
|     if (ri.contains(rj)) | ||||
|         assert((ri & rj) == rj); | ||||
|     assert(boost::intersects(ri, rj) == !(ri & rj).empty()); | ||||
|  | ||||
|     range t1(ri); | ||||
|     t1 &= rj; | ||||
|     assert(t1 == range(indices[i][0] > indices[j][0] ? ri.start() : rj.start(), | ||||
|                        indices[i][1] < indices[j][1] ? ri.finish() : rj.finish())); | ||||
|     assert(t1 == (ri & rj)); | ||||
|      | ||||
|     range t2(ri); | ||||
|     t2 |= rj; | ||||
|      | ||||
|     if (ri.empty()) | ||||
|         assert(t2 == rj); | ||||
|     else if (rj.empty()) | ||||
|         assert(t2 == ri); | ||||
|     else | ||||
|         assert(t2 == range(indices[i][0] < indices[j][0] ? ri.start() : rj.start(), | ||||
|                            indices[i][1] > indices[j][1] ? ri.finish() : rj.finish())); | ||||
|     assert(t2 == (ri | rj)); | ||||
|     if (i == j) | ||||
|         assert(ri == rj); | ||||
|      | ||||
|     if (ri.empty() || rj.empty()) | ||||
|         assert((ri == rj) == (ri.empty() && rj.empty())); | ||||
|     else | ||||
|         assert((ri == rj) == (ri.start() == rj.start() && ri.finish() == rj.finish())); | ||||
|  | ||||
|     assert((ri == rj) == !(ri != rj)); | ||||
|  | ||||
|     bool same = ri == rj; | ||||
|     bool one_empty = ri.empty() != rj.empty(); | ||||
|  | ||||
|     std::less<range> less; | ||||
|     std::less_equal<range> less_equal; | ||||
|     std::greater<range> greater; | ||||
|     std::greater_equal<range> greater_equal; | ||||
|      | ||||
|     if (same) | ||||
|     { | ||||
|         assert(greater_equal(ri,rj)); | ||||
|         assert(less_equal(ri,rj)); | ||||
|         assert(!greater(ri,rj)); | ||||
|         assert(!less(ri,rj)); | ||||
|     } | ||||
|     else if (one_empty) | ||||
|     { | ||||
|         const range& empty = ri.empty() ? ri : rj; | ||||
|         const range& non_empty = rj.empty() ? ri : rj; | ||||
|          | ||||
|         assert(less(empty,non_empty)); | ||||
|         assert(less_equal(empty,non_empty)); | ||||
|         assert(!greater(empty,non_empty)); | ||||
|         assert(!greater_equal(empty,non_empty)); | ||||
|         assert(!less(non_empty,empty)); | ||||
|         assert(!less_equal(non_empty,empty)); | ||||
|         assert(greater(non_empty,empty)); | ||||
|         assert(greater_equal(non_empty,empty)); | ||||
|     } | ||||
|     else { | ||||
|         if (indices[i][0] < indices[j][0] || | ||||
|             indices[i][0] == indices[j][0] && indices[i][1] < indices[j][1]) | ||||
|         { | ||||
|             assert(!greater_equal(ri,rj)); | ||||
|             assert(less(ri,rj)); | ||||
|         } | ||||
|  | ||||
|         if (indices[i][0] < indices[j][0] || | ||||
|             indices[i][0] == indices[j][0] && indices[i][1] <= indices[j][1]) | ||||
|         { | ||||
|             assert(!greater(ri,rj)); | ||||
|             assert(less_equal(ri,rj)); | ||||
|         } | ||||
|  | ||||
|         if (indices[i][0] > indices[j][0] || | ||||
|             indices[i][0] == indices[j][0] && indices[i][1] > indices[j][1]) | ||||
|         { | ||||
|             assert(!less_equal(ri,rj)); | ||||
|             assert(greater(ri,rj)); | ||||
|         } | ||||
|  | ||||
|         if (indices[i][0] > indices[j][0] || | ||||
|             indices[i][0] == indices[j][0] && indices[i][1] >= indices[j][1]) | ||||
|         { | ||||
|             assert(!less(ri,rj)); | ||||
|             assert(greater_equal(ri,rj)); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| template <class Range> | ||||
| void category_test_2( | ||||
|     const std::vector<Range>&, unsigned, unsigned, std::forward_iterator_tag) | ||||
| { | ||||
| } | ||||
|  | ||||
| template <class T> | ||||
| void category_test_2( | ||||
|     const std::vector<boost::half_open_range<T> >&, unsigned, unsigned, std::bidirectional_iterator_tag) | ||||
| { | ||||
| } | ||||
|  | ||||
| template <class Range> | ||||
| void test_back(Range& x, std::bidirectional_iterator_tag) | ||||
| { | ||||
|     assert(x.back() == boost::prior(x.finish())); | ||||
| } | ||||
|  | ||||
| template <class Range> | ||||
| void test_back(Range& x, std::forward_iterator_tag) | ||||
| { | ||||
| } | ||||
|  | ||||
| template <class T> | ||||
| boost::half_open_range<T> range_identity(const boost::half_open_range<T>& x) | ||||
| { | ||||
|     return x; | ||||
| } | ||||
|  | ||||
| template <class T> | ||||
| void test(T x0, T x1, T x2, T x3) | ||||
| { | ||||
|     std::vector<boost::half_open_range<T> > ranges; | ||||
|     typedef boost::half_open_range<T> range; | ||||
|  | ||||
|     T bounds[4] = { x0, x1, x2, x3 }; | ||||
|  | ||||
|     const std::size_t num_ranges = sizeof(indices)/sizeof(*indices); | ||||
|     // test construction | ||||
|     for (std::size_t n = 0; n < num_ranges;++n) | ||||
|     { | ||||
|         T start = bounds[indices[n][0]]; | ||||
|         T finish = bounds[indices[n][1]]; | ||||
|         boost::half_open_range<T> r(start, finish); | ||||
|         ranges.push_back(r); | ||||
|     } | ||||
|      | ||||
|     // test implicit conversion from std::pair<T,T> | ||||
|     range converted = std::pair<T,T>(x0,x0); | ||||
|     (void)converted; | ||||
|  | ||||
|     // test assignment, equality and inequality | ||||
|     range r00 = range(x0, x0); | ||||
|     assert(r00 == range(x0,x0)); | ||||
|     assert(r00 == range(x1,x1)); // empty ranges are all equal | ||||
|     if (x3 != x0) | ||||
|         assert(r00 != range(x0, x3)); | ||||
|     r00 = range(x0, x3); | ||||
|     assert(r00 == range(x0, x3)); | ||||
|     if (x3 != x0) | ||||
|         assert(r00 != range(x0, x0)); | ||||
|  | ||||
|     typedef typename range::iterator iterator; | ||||
|     typedef typename iterator::iterator_category category; | ||||
|      | ||||
|     for (unsigned i = 0; i < num_ranges; ++i) | ||||
|     { | ||||
|         const range& r = ranges[i]; | ||||
|              | ||||
|         // test begin(), end(), basic iteration. | ||||
|         unsigned count = 0; | ||||
|         for (range::const_iterator p = r.begin(), finish = r.end(); | ||||
|              p != finish; | ||||
|              ++p, ++count) | ||||
|         { | ||||
|             assert(count < 2100); | ||||
|         } | ||||
|  | ||||
|         // test size(), empty(), front(), back() | ||||
|         assert((unsigned)r.size() == count); | ||||
|         if (indices[i][0] == indices[i][1]) | ||||
|             assert(r.empty()); | ||||
|         if (r.empty()) | ||||
|             assert(r.size() == 0); | ||||
|         if (!r.empty()) | ||||
|         { | ||||
|             assert(r.front() == r.start()); | ||||
|             test_back(r, category()); | ||||
|         } | ||||
|  | ||||
|             // test swap | ||||
|         range r1(r); | ||||
|         range r2(x0,x3); | ||||
|         const bool same = r1 == r2; | ||||
|         r1.swap(r2); | ||||
|         assert(r1 == range(x0,x3)); | ||||
|         assert(r2 == r); | ||||
|         if (!same) { | ||||
|             assert(r1 != r); | ||||
|             assert(r2 != range(x0,x3)); | ||||
|         } | ||||
|  | ||||
|         // do individual tests for random-access iterators | ||||
|         category_test_1(r, category()); | ||||
|     } | ||||
|  | ||||
|     for (unsigned j = 0; j < num_ranges; ++j) { | ||||
|         for (unsigned k = 0; k < num_ranges; ++k) { | ||||
|             category_test_2(ranges, j, k, category()); | ||||
|         } | ||||
|     } | ||||
|      | ||||
| } | ||||
|  | ||||
| template <class Integer> | ||||
| void test_integer(Integer* = 0) // default arg works around MSVC bug | ||||
| { | ||||
|     Integer a = 0; | ||||
|     Integer b = a + unsigned_random(128 - a); | ||||
|     Integer c = b + unsigned_random(128 - b); | ||||
|     Integer d = c + unsigned_random(128 - c); | ||||
|  | ||||
|     test(a, b, c, d); | ||||
| } | ||||
|  | ||||
| template <class Container> | ||||
| void test_container(Container* = 0)  // default arg works around MSVC bug | ||||
| { | ||||
|     Container c(unsigned_random(1673)); | ||||
|  | ||||
|     const typename Container::size_type offset1 = unsigned_random(c.size()); | ||||
|     const typename Container::size_type offset2 = unsigned_random(c.size() - offset1); | ||||
|     typename Container::iterator internal1 = c.begin(); | ||||
|     std::advance(internal1, offset1); | ||||
|     typename Container::iterator internal2 = internal1; | ||||
|     std::advance(internal2, offset2); | ||||
|      | ||||
|     test(c.begin(), internal1, internal2, c.end()); | ||||
|  | ||||
|     typedef typename Container::const_iterator const_iterator; | ||||
|     test(const_iterator(c.begin()), | ||||
|          const_iterator(internal1), | ||||
|          const_iterator(internal2), | ||||
|          const_iterator(c.end())); | ||||
| } | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     // Test the built-in integer types. | ||||
|     test_integer<char>(); | ||||
|     test_integer<unsigned char>(); | ||||
|     test_integer<signed char>(); | ||||
|     test_integer<wchar_t>(); | ||||
|     test_integer<short>(); | ||||
|     test_integer<unsigned short>(); | ||||
|     test_integer<int>(); | ||||
|     test_integer<unsigned int>(); | ||||
|     test_integer<long>(); | ||||
|     test_integer<unsigned long>(); | ||||
| #if defined(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; | ||||
| } | ||||
| @@ -1,23 +0,0 @@ | ||||
| //  (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and | ||||
| //  distribute this software is granted provided this copyright notice appears | ||||
| //  in all copies. This software is provided "as is" without express or implied | ||||
| //  warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
| //  See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp | ||||
| //  for full copyright notices. | ||||
|  | ||||
| #ifndef BOOST_CALL_TRAITS_HPP | ||||
| #define BOOST_CALL_TRAITS_HPP | ||||
|  | ||||
| #ifndef BOOST_CONFIG_HPP | ||||
| #include <boost/config.hpp> | ||||
| #endif | ||||
|  | ||||
| #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| #include <boost/detail/ob_call_traits.hpp> | ||||
| #else | ||||
| #include <boost/detail/call_traits.hpp> | ||||
| #endif | ||||
|  | ||||
| #endif // BOOST_CALL_TRAITS_HPP | ||||
| @@ -1,23 +0,0 @@ | ||||
| //  (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and | ||||
| //  distribute this software is granted provided this copyright notice appears | ||||
| //  in all copies. This software is provided "as is" without express or implied | ||||
| //  warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
| //  See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp | ||||
| //  for full copyright notices. | ||||
|  | ||||
| #ifndef BOOST_COMPRESSED_PAIR_HPP | ||||
| #define BOOST_COMPRESSED_PAIR_HPP | ||||
|  | ||||
| #ifndef BOOST_CONFIG_HPP | ||||
| #include <boost/config.hpp> | ||||
| #endif | ||||
|  | ||||
| #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| #include <boost/detail/ob_compressed_pair.hpp> | ||||
| #else | ||||
| #include <boost/detail/compressed_pair.hpp> | ||||
| #endif | ||||
|  | ||||
| #endif // BOOST_COMPRESSED_PAIR_HPP | ||||
| @@ -1,141 +0,0 @@ | ||||
| //  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. | ||||
| //  Permission to copy, use, modify, sell and | ||||
| //  distribute this software is granted provided this copyright notice appears | ||||
| //  in all copies. This software is provided "as is" without express or implied | ||||
| //  warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| // call_traits: defines typedefs for function usage | ||||
| // (see libs/utility/call_traits.htm) | ||||
|  | ||||
| /* Release notes: | ||||
|    23rd July 2000: | ||||
|       Fixed array specialization. (JM) | ||||
|       Added Borland specific fixes for reference types | ||||
|       (issue raised by Steve Cleary). | ||||
| */ | ||||
|  | ||||
| #ifndef BOOST_DETAIL_CALL_TRAITS_HPP | ||||
| #define BOOST_DETAIL_CALL_TRAITS_HPP | ||||
|  | ||||
| #ifndef BOOST_CONFIG_HPP | ||||
| #include <boost/config.hpp> | ||||
| #endif | ||||
|  | ||||
| #ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP | ||||
| #include <boost/type_traits/arithmetic_traits.hpp> | ||||
| #endif | ||||
| #ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP | ||||
| #include <boost/type_traits/composite_traits.hpp> | ||||
| #endif | ||||
|  | ||||
| namespace boost{ | ||||
|  | ||||
| namespace detail{ | ||||
|  | ||||
| template <typename T, bool isp, bool b1, bool b2> | ||||
| struct ct_imp | ||||
| { | ||||
|    typedef const T& param_type; | ||||
| }; | ||||
|  | ||||
| template <typename T, bool isp> | ||||
| struct ct_imp<T, isp, true, true> | ||||
| { | ||||
|    typedef T const param_type; | ||||
| }; | ||||
|  | ||||
| template <typename T, bool b1, bool b2> | ||||
| struct ct_imp<T, true, b1, b2> | ||||
| { | ||||
|    typedef T const param_type; | ||||
| }; | ||||
|  | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| struct call_traits | ||||
| { | ||||
| public: | ||||
|    typedef T value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    // | ||||
|    // C++ Builder workaround: we should be able to define a compile time | ||||
|    // constant and pass that as a single template parameter to ct_imp<T,bool>, | ||||
|    // however compiler bugs prevent this - instead pass three bool's to | ||||
|    // ct_imp<T,bool,bool,bool> and add an extra partial specialisation | ||||
|    // of ct_imp to handle the logic. (JM) | ||||
|    typedef typename detail::ct_imp<T, ::boost::is_pointer<typename remove_const<T>::type>::value, ::boost::is_arithmetic<typename remove_const<T>::type>::value, sizeof(T) <= sizeof(void*)>::param_type param_type; | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| struct call_traits<T&> | ||||
| { | ||||
|    typedef T& value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    typedef T& param_type;  // hh removed const | ||||
| }; | ||||
|  | ||||
| #if defined(__BORLANDC__) && (__BORLANDC__ <= 0x551) | ||||
| // these are illegal specialisations; cv-qualifies applied to | ||||
| // references have no effect according to [8.3.2p1], | ||||
| // C++ Builder requires them though as it treats cv-qualified | ||||
| // references as distinct types... | ||||
| template <typename T> | ||||
| struct call_traits<T&const> | ||||
| { | ||||
|    typedef T& value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    typedef T& param_type;  // hh removed const | ||||
| }; | ||||
| template <typename T> | ||||
| struct call_traits<T&volatile> | ||||
| { | ||||
|    typedef T& value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    typedef T& param_type;  // hh removed const | ||||
| }; | ||||
| template <typename T> | ||||
| struct call_traits<T&const volatile> | ||||
| { | ||||
|    typedef T& value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    typedef T& param_type;  // hh removed const | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| template <typename T, std::size_t N> | ||||
| struct call_traits<T [N]> | ||||
| { | ||||
| private: | ||||
|    typedef T array_type[N]; | ||||
| public: | ||||
|    // degrades array to pointer: | ||||
|    typedef const T* value_type; | ||||
|    typedef array_type& reference; | ||||
|    typedef const array_type& const_reference; | ||||
|    typedef const T* const param_type; | ||||
| }; | ||||
|  | ||||
| template <typename T, std::size_t N> | ||||
| struct call_traits<const T [N]> | ||||
| { | ||||
| private: | ||||
|    typedef const T array_type[N]; | ||||
| public: | ||||
|    // degrades array to pointer: | ||||
|    typedef const T* value_type; | ||||
|    typedef array_type& reference; | ||||
|    typedef const array_type& const_reference; | ||||
|    typedef const T* const param_type; | ||||
| }; | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // BOOST_DETAIL_CALL_TRAITS_HPP | ||||
| @@ -1,428 +0,0 @@ | ||||
| //  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. | ||||
| //  Permission to copy, use, modify, sell and | ||||
| //  distribute this software is granted provided this copyright notice appears | ||||
| //  in all copies. This software is provided "as is" without express or implied | ||||
| //  warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| // compressed_pair: pair that "compresses" empty members | ||||
| // (see libs/utility/compressed_pair.htm) | ||||
| // | ||||
| // JM changes 25 Jan 2000: | ||||
| // Removed default arguments from compressed_pair_switch to get | ||||
| // C++ Builder 4 to accept them | ||||
| // rewriten swap to get gcc and C++ builder to compile. | ||||
| // added partial specialisations for case T1 == T2 to avoid duplicate constructor defs. | ||||
|  | ||||
| #ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP | ||||
| #define BOOST_DETAIL_COMPRESSED_PAIR_HPP | ||||
|  | ||||
| #include <algorithm> | ||||
| #ifndef BOOST_OBJECT_TYPE_TRAITS_HPP | ||||
| #include <boost/type_traits/object_traits.hpp> | ||||
| #endif | ||||
| #ifndef BOOST_SAME_TRAITS_HPP | ||||
| #include <boost/type_traits/same_traits.hpp> | ||||
| #endif | ||||
| #ifndef BOOST_CALL_TRAITS_HPP | ||||
| #include <boost/call_traits.hpp> | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| // compressed_pair | ||||
|  | ||||
| namespace details | ||||
| { | ||||
|    // JM altered 26 Jan 2000: | ||||
|    template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty> | ||||
|    struct compressed_pair_switch; | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    struct compressed_pair_switch<T1, T2, false, false, false> | ||||
|       {static const int value = 0;}; | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    struct compressed_pair_switch<T1, T2, false, true, true> | ||||
|       {static const int value = 3;}; | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    struct compressed_pair_switch<T1, T2, false, true, false> | ||||
|       {static const int value = 1;}; | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    struct compressed_pair_switch<T1, T2, false, false, true> | ||||
|       {static const int value = 2;}; | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    struct compressed_pair_switch<T1, T2, true, true, true> | ||||
|       {static const int value = 4;}; | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    struct compressed_pair_switch<T1, T2, true, false, false> | ||||
|       {static const int value = 5;}; | ||||
|  | ||||
|    template <class T1, class T2, int Version> class compressed_pair_imp; | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
|    // workaround for GCC (JM): | ||||
|    using std::swap; | ||||
| #endif | ||||
|    // | ||||
|    // can't call unqualified swap from within classname::swap | ||||
|    // as Koenig lookup rules will find only the classname::swap | ||||
|    // member function not the global declaration, so use cp_swap | ||||
|    // as a forwarding function (JM): | ||||
|    template <typename T> | ||||
|    inline void cp_swap(T& t1, T& t2) | ||||
|    { | ||||
| #ifndef __GNUC__ | ||||
|       using std::swap; | ||||
| #endif | ||||
|       swap(t1, t2); | ||||
|    } | ||||
|  | ||||
|    // 0    derive from neither | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    class compressed_pair_imp<T1, T2, 0> | ||||
|    { | ||||
|    public: | ||||
|       typedef T1                                                 first_type; | ||||
|       typedef T2                                                 second_type; | ||||
|       typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|       typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|       typedef typename call_traits<first_type>::reference        first_reference; | ||||
|       typedef typename call_traits<second_type>::reference       second_reference; | ||||
|       typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|       typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|       compressed_pair_imp() {}  | ||||
|  | ||||
|       compressed_pair_imp(first_param_type x, second_param_type y) | ||||
|          : first_(x), second_(y) {} | ||||
|  | ||||
|       explicit compressed_pair_imp(first_param_type x) | ||||
|          : first_(x) {} | ||||
|  | ||||
|       explicit compressed_pair_imp(second_param_type y) | ||||
|          : second_(y) {} | ||||
|  | ||||
|       first_reference       first()       {return first_;} | ||||
|       first_const_reference first() const {return first_;} | ||||
|  | ||||
|       second_reference       second()       {return second_;} | ||||
|       second_const_reference second() const {return second_;} | ||||
|  | ||||
|       void swap(compressed_pair_imp& y) | ||||
|       { | ||||
|          cp_swap(first_, y.first_); | ||||
|          cp_swap(second_, y.second_); | ||||
|       } | ||||
|    private: | ||||
|       first_type first_; | ||||
|       second_type second_; | ||||
|    }; | ||||
|  | ||||
|    // 1    derive from T1 | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    class compressed_pair_imp<T1, T2, 1> | ||||
|       : private T1 | ||||
|    { | ||||
|    public: | ||||
|       typedef T1                                                 first_type; | ||||
|       typedef T2                                                 second_type; | ||||
|       typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|       typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|       typedef typename call_traits<first_type>::reference        first_reference; | ||||
|       typedef typename call_traits<second_type>::reference       second_reference; | ||||
|       typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|       typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|       compressed_pair_imp() {} | ||||
|  | ||||
|       compressed_pair_imp(first_param_type x, second_param_type y) | ||||
|          : first_type(x), second_(y) {} | ||||
|  | ||||
|       explicit compressed_pair_imp(first_param_type x) | ||||
|          : first_type(x) {} | ||||
|  | ||||
|       explicit compressed_pair_imp(second_param_type y) | ||||
|          : second_(y) {} | ||||
|  | ||||
|       first_reference       first()       {return *this;} | ||||
|       first_const_reference first() const {return *this;} | ||||
|  | ||||
|       second_reference       second()       {return second_;} | ||||
|       second_const_reference second() const {return second_;} | ||||
|  | ||||
|       void swap(compressed_pair_imp& y) | ||||
|       { | ||||
|          // no need to swap empty base class: | ||||
|          cp_swap(second_, y.second_); | ||||
|       } | ||||
|    private: | ||||
|       second_type second_; | ||||
|    }; | ||||
|  | ||||
|    // 2    derive from T2 | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    class compressed_pair_imp<T1, T2, 2> | ||||
|       : private T2 | ||||
|    { | ||||
|    public: | ||||
|       typedef T1                                                 first_type; | ||||
|       typedef T2                                                 second_type; | ||||
|       typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|       typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|       typedef typename call_traits<first_type>::reference        first_reference; | ||||
|       typedef typename call_traits<second_type>::reference       second_reference; | ||||
|       typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|       typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|       compressed_pair_imp() {} | ||||
|  | ||||
|       compressed_pair_imp(first_param_type x, second_param_type y) | ||||
|          : second_type(y), first_(x) {} | ||||
|  | ||||
|       explicit compressed_pair_imp(first_param_type x) | ||||
|          : first_(x) {} | ||||
|  | ||||
|       explicit compressed_pair_imp(second_param_type y) | ||||
|          : second_type(y) {} | ||||
|  | ||||
|       first_reference       first()       {return first_;} | ||||
|       first_const_reference first() const {return first_;} | ||||
|  | ||||
|       second_reference       second()       {return *this;} | ||||
|       second_const_reference second() const {return *this;} | ||||
|  | ||||
|       void swap(compressed_pair_imp& y) | ||||
|       { | ||||
|          // no need to swap empty base class: | ||||
|          cp_swap(first_, y.first_); | ||||
|       } | ||||
|  | ||||
|    private: | ||||
|       first_type first_; | ||||
|    }; | ||||
|  | ||||
|    // 3    derive from T1 and T2 | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    class compressed_pair_imp<T1, T2, 3> | ||||
|       : private T1, | ||||
|         private T2 | ||||
|    { | ||||
|    public: | ||||
|       typedef T1                                                 first_type; | ||||
|       typedef T2                                                 second_type; | ||||
|       typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|       typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|       typedef typename call_traits<first_type>::reference        first_reference; | ||||
|       typedef typename call_traits<second_type>::reference       second_reference; | ||||
|       typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|       typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|       compressed_pair_imp() {} | ||||
|  | ||||
|       compressed_pair_imp(first_param_type x, second_param_type y) | ||||
|          : first_type(x), second_type(y) {} | ||||
|  | ||||
|       explicit compressed_pair_imp(first_param_type x) | ||||
|          : first_type(x) {} | ||||
|  | ||||
|       explicit compressed_pair_imp(second_param_type y) | ||||
|          : second_type(y) {} | ||||
|  | ||||
|       first_reference       first()       {return *this;} | ||||
|       first_const_reference first() const {return *this;} | ||||
|  | ||||
|       second_reference       second()       {return *this;} | ||||
|       second_const_reference second() const {return *this;} | ||||
|       // | ||||
|       // no need to swap empty bases: | ||||
|       void swap(compressed_pair_imp&) {} | ||||
|    }; | ||||
|  | ||||
|    // JM | ||||
|    // 4    T1 == T2, T1 and T2 both empty | ||||
|    //      Note does not actually store an instance of T2 at all - | ||||
|    //      but reuses T1 base class for both first() and second(). | ||||
|    template <class T1, class T2> | ||||
|    class compressed_pair_imp<T1, T2, 4> | ||||
|       : private T1 | ||||
|    { | ||||
|    public: | ||||
|       typedef T1                                                 first_type; | ||||
|       typedef T2                                                 second_type; | ||||
|       typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|       typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|       typedef typename call_traits<first_type>::reference        first_reference; | ||||
|       typedef typename call_traits<second_type>::reference       second_reference; | ||||
|       typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|       typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|       compressed_pair_imp() {} | ||||
|  | ||||
|       compressed_pair_imp(first_param_type x, second_param_type) | ||||
|          : first_type(x) {} | ||||
|  | ||||
|       explicit compressed_pair_imp(first_param_type x) | ||||
|          : first_type(x) {} | ||||
|  | ||||
|       first_reference       first()       {return *this;} | ||||
|       first_const_reference first() const {return *this;} | ||||
|  | ||||
|       second_reference       second()       {return *this;} | ||||
|       second_const_reference second() const {return *this;} | ||||
|  | ||||
|       void swap(compressed_pair_imp&) {} | ||||
|    private: | ||||
|    }; | ||||
|  | ||||
|    // 5    T1 == T2 and are not empty:   //JM | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    class compressed_pair_imp<T1, T2, 5> | ||||
|    { | ||||
|    public: | ||||
|       typedef T1                                                 first_type; | ||||
|       typedef T2                                                 second_type; | ||||
|       typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|       typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|       typedef typename call_traits<first_type>::reference        first_reference; | ||||
|       typedef typename call_traits<second_type>::reference       second_reference; | ||||
|       typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|       typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|       compressed_pair_imp() {} | ||||
|  | ||||
|       compressed_pair_imp(first_param_type x, second_param_type y) | ||||
|          : first_(x), second_(y) {} | ||||
|  | ||||
|       explicit compressed_pair_imp(first_param_type x) | ||||
|          : first_(x), second_(x) {} | ||||
|  | ||||
|       first_reference       first()       {return first_;} | ||||
|       first_const_reference first() const {return first_;} | ||||
|  | ||||
|       second_reference       second()       {return second_;} | ||||
|       second_const_reference second() const {return second_;} | ||||
|  | ||||
|       void swap(compressed_pair_imp<T1, T2, 5>& y) | ||||
|       { | ||||
|          cp_swap(first_, y.first_); | ||||
|          cp_swap(second_, y.second_); | ||||
|       } | ||||
|    private: | ||||
|       first_type first_; | ||||
|       second_type second_; | ||||
|    }; | ||||
|  | ||||
| }  // details | ||||
|  | ||||
| template <class T1, class T2> | ||||
| class compressed_pair | ||||
|    : private ::boost::details::compressed_pair_imp<T1, T2, | ||||
|              ::boost::details::compressed_pair_switch< | ||||
|                     T1, | ||||
|                     T2, | ||||
|                     ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value, | ||||
|                     ::boost::is_empty<T1>::value, | ||||
|                     ::boost::is_empty<T2>::value>::value> | ||||
| { | ||||
| private: | ||||
|    typedef details::compressed_pair_imp<T1, T2, | ||||
|              ::boost::details::compressed_pair_switch< | ||||
|                     T1, | ||||
|                     T2, | ||||
|                     ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value, | ||||
|                     ::boost::is_empty<T1>::value, | ||||
|                     ::boost::is_empty<T2>::value>::value> base; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair() : base() {} | ||||
|             compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} | ||||
|    explicit compressed_pair(first_param_type x) : base(x) {} | ||||
|    explicit compressed_pair(second_param_type y) : base(y) {} | ||||
|  | ||||
|    first_reference       first()       {return base::first();} | ||||
|    first_const_reference first() const {return base::first();} | ||||
|  | ||||
|    second_reference       second()       {return base::second();} | ||||
|    second_const_reference second() const {return base::second();} | ||||
|  | ||||
|    void swap(compressed_pair& y) { base::swap(y); } | ||||
| }; | ||||
|  | ||||
| // JM | ||||
| // Partial specialisation for case where T1 == T2: | ||||
| // | ||||
| template <class T> | ||||
| class compressed_pair<T, T> | ||||
|    : private details::compressed_pair_imp<T, T, | ||||
|              ::boost::details::compressed_pair_switch< | ||||
|                     T, | ||||
|                     T, | ||||
|                     ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value, | ||||
|                     ::boost::is_empty<T>::value, | ||||
|                     ::boost::is_empty<T>::value>::value> | ||||
| { | ||||
| private: | ||||
|    typedef details::compressed_pair_imp<T, T, | ||||
|              ::boost::details::compressed_pair_switch< | ||||
|                     T, | ||||
|                     T, | ||||
|                     ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value, | ||||
|                     ::boost::is_empty<T>::value, | ||||
|                     ::boost::is_empty<T>::value>::value> base; | ||||
| public: | ||||
|    typedef T                                                  first_type; | ||||
|    typedef T                                                  second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair() : base() {} | ||||
|             compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} | ||||
|    explicit compressed_pair(first_param_type x) : base(x) {} | ||||
|  | ||||
|    first_reference       first()       {return base::first();} | ||||
|    first_const_reference first() const {return base::first();} | ||||
|  | ||||
|    second_reference       second()       {return base::second();} | ||||
|    second_const_reference second() const {return base::second();} | ||||
|  | ||||
|    void swap(compressed_pair& y) { base::swap(y); } | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| inline | ||||
| void | ||||
| swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y) | ||||
| { | ||||
|    x.swap(y); | ||||
| } | ||||
|  | ||||
| } // boost | ||||
|  | ||||
| #endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -1,128 +0,0 @@ | ||||
| //  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. | ||||
| //  Permission to copy, use, modify, sell and | ||||
| //  distribute this software is granted provided this copyright notice appears | ||||
| //  in all copies. This software is provided "as is" without express or implied | ||||
| //  warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
| // | ||||
| //  Crippled version for crippled compilers: | ||||
| //  see libs/utility/call_traits.htm | ||||
| // | ||||
|  | ||||
| /* Release notes: | ||||
|    01st October 2000: | ||||
|       Fixed call_traits on VC6, using "poor man's partial specialisation", | ||||
|       using ideas taken from "Generative programming" by Krzysztof Czarnecki  | ||||
|       & Ulrich Eisenecker. | ||||
| */ | ||||
|  | ||||
| #ifndef BOOST_OB_CALL_TRAITS_HPP | ||||
| #define BOOST_OB_CALL_TRAITS_HPP | ||||
|  | ||||
| #ifndef BOOST_CONFIG_HPP | ||||
| #include <boost/config.hpp> | ||||
| #endif | ||||
|  | ||||
| #ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP | ||||
| #include <boost/type_traits/arithmetic_traits.hpp> | ||||
| #endif | ||||
| #ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP | ||||
| #include <boost/type_traits/composite_traits.hpp> | ||||
| #endif | ||||
|  | ||||
| namespace boost{ | ||||
|  | ||||
| #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) | ||||
| // | ||||
| // use member templates to emulate | ||||
| // partial specialisation: | ||||
| // | ||||
| namespace detail{ | ||||
|  | ||||
| template <class T> | ||||
| struct standard_call_traits | ||||
| { | ||||
|    typedef T value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    typedef const T& param_type; | ||||
| }; | ||||
| template <class T> | ||||
| struct simple_call_traits | ||||
| { | ||||
|    typedef T value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    typedef const T param_type; | ||||
| }; | ||||
| template <class T> | ||||
| struct reference_call_traits | ||||
| { | ||||
|    typedef T value_type; | ||||
|    typedef T reference; | ||||
|    typedef T const_reference; | ||||
|    typedef T param_type; | ||||
| }; | ||||
| template <bool simple, bool reference> | ||||
| struct call_traits_chooser | ||||
| { | ||||
|    template <class T> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef standard_call_traits<T> type; | ||||
|    }; | ||||
| }; | ||||
| template <> | ||||
| struct call_traits_chooser<true, false> | ||||
| { | ||||
|    template <class T> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef simple_call_traits<T> type; | ||||
|    }; | ||||
| }; | ||||
| template <> | ||||
| struct call_traits_chooser<false, true> | ||||
| { | ||||
|    template <class T> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef reference_call_traits<T> type; | ||||
|    }; | ||||
| }; | ||||
| } // namespace detail | ||||
| template <typename T> | ||||
| struct call_traits | ||||
| { | ||||
| private: | ||||
|    typedef detail::call_traits_chooser<(is_pointer<T>::value || is_arithmetic<T>::value) && sizeof(T) <= sizeof(void*), is_reference<T>::value> chooser; | ||||
|    typedef typename chooser::template rebind<T> bound_type; | ||||
|    typedef typename bound_type::type call_traits_type; | ||||
| public: | ||||
|    typedef typename call_traits_type::value_type       value_type; | ||||
|    typedef typename call_traits_type::reference        reference; | ||||
|    typedef typename call_traits_type::const_reference  const_reference; | ||||
|    typedef typename call_traits_type::param_type       param_type; | ||||
| }; | ||||
|  | ||||
| #else | ||||
| // | ||||
| // sorry call_traits is completely non-functional | ||||
| // blame your broken compiler: | ||||
| // | ||||
|  | ||||
| template <typename T> | ||||
| struct call_traits | ||||
| { | ||||
|    typedef T value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    typedef const T& param_type; | ||||
| }; | ||||
|  | ||||
| #endif // member templates | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // BOOST_OB_CALL_TRAITS_HPP | ||||
| @@ -1,509 +0,0 @@ | ||||
| //  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. | ||||
| //  Permission to copy, use, modify, sell and | ||||
| //  distribute this software is granted provided this copyright notice appears | ||||
| //  in all copies. This software is provided "as is" without express or implied | ||||
| //  warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
| //  see libs/utility/compressed_pair.hpp | ||||
| // | ||||
| /* Release notes: | ||||
|    20 Jan 2001: | ||||
|         Fixed obvious bugs (David Abrahams) | ||||
| 	07 Oct 2000: | ||||
| 		Added better single argument constructor support. | ||||
|    03 Oct 2000: | ||||
|       Added VC6 support (JM). | ||||
|    23rd July 2000: | ||||
|       Additional comments added. (JM) | ||||
|    Jan 2000: | ||||
|       Original version: this version crippled for use with crippled compilers | ||||
|       - John Maddock Jan 2000. | ||||
| */ | ||||
|  | ||||
|  | ||||
| #ifndef BOOST_OB_COMPRESSED_PAIR_HPP | ||||
| #define BOOST_OB_COMPRESSED_PAIR_HPP | ||||
|  | ||||
| #include <algorithm> | ||||
| #ifndef BOOST_OBJECT_TYPE_TRAITS_HPP | ||||
| #include <boost/type_traits/object_traits.hpp> | ||||
| #endif | ||||
| #ifndef BOOST_SAME_TRAITS_HPP | ||||
| #include <boost/type_traits/same_traits.hpp> | ||||
| #endif | ||||
| #ifndef BOOST_CALL_TRAITS_HPP | ||||
| #include <boost/call_traits.hpp> | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
| #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) | ||||
| // | ||||
| // use member templates to emulate | ||||
| // partial specialisation.  Note that due to | ||||
| // problems with overload resolution with VC6 | ||||
| // each of the compressed_pair versions that follow | ||||
| // have one template single-argument constructor | ||||
| // in place of two specific constructors: | ||||
| // | ||||
|  | ||||
| template <class T1, class T2> | ||||
| class compressed_pair; | ||||
|  | ||||
| namespace detail{ | ||||
|  | ||||
| template <class A, class T1, class T2> | ||||
| struct best_conversion_traits | ||||
| { | ||||
|    typedef char one; | ||||
|    typedef char (&two)[2]; | ||||
|    static A a; | ||||
|    static one test(T1); | ||||
|    static two test(T2); | ||||
|  | ||||
|    enum { value = sizeof(test(a)) }; | ||||
| }; | ||||
|  | ||||
| template <int> | ||||
| struct init_one; | ||||
|  | ||||
| template <> | ||||
| struct init_one<1> | ||||
| { | ||||
|    template <class A, class T1, class T2> | ||||
|    static void init(const A& a, T1* p1, T2*) | ||||
|    { | ||||
|       *p1 = a; | ||||
|    } | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct init_one<2> | ||||
| { | ||||
|    template <class A, class T1, class T2> | ||||
|    static void init(const A& a, T1*, T2* p2) | ||||
|    { | ||||
|       *p2 = a; | ||||
|    } | ||||
| }; | ||||
|  | ||||
|  | ||||
| // T1 != T2, both non-empty | ||||
| template <class T1, class T2> | ||||
| class compressed_pair_0 | ||||
| { | ||||
| private: | ||||
|    T1 _first; | ||||
|    T2 _second; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair_0() : _first(), _second() {} | ||||
|             compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {} | ||||
|    template <class A> | ||||
|    explicit compressed_pair_0(const A& val) | ||||
|    { | ||||
|       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second); | ||||
|    } | ||||
|    compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x) | ||||
|       : _first(x.first()), _second(x.second()) {} | ||||
|  | ||||
| #if 0 | ||||
|   compressed_pair_0& operator=(const compressed_pair_0& x) { | ||||
|     cout << "assigning compressed pair 0" << endl; | ||||
|     _first = x._first; | ||||
|     _second = x._second; | ||||
|     cout << "finished assigning compressed pair 0" << endl; | ||||
|     return *this; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|    first_reference       first()       { return _first; } | ||||
|    first_const_reference first() const { return _first; } | ||||
|  | ||||
|    second_reference       second()       { return _second; } | ||||
|    second_const_reference second() const { return _second; } | ||||
|  | ||||
|    void swap(compressed_pair_0& y) | ||||
|    { | ||||
|       using std::swap; | ||||
|       swap(_first, y._first); | ||||
|       swap(_second, y._second); | ||||
|    } | ||||
| }; | ||||
|  | ||||
| // T1 != T2, T2 empty | ||||
| template <class T1, class T2> | ||||
| class compressed_pair_1 : T2 | ||||
| { | ||||
| private: | ||||
|    T1 _first; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair_1() : T2(), _first() {} | ||||
|             compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {} | ||||
|  | ||||
|    template <class A> | ||||
|    explicit compressed_pair_1(const A& val) | ||||
|    { | ||||
|       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this)); | ||||
|    } | ||||
|  | ||||
|    compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x) | ||||
|       : T2(x.second()), _first(x.first()) {} | ||||
|  | ||||
| #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; } | ||||
|  | ||||
|    second_reference       second()       { return *this; } | ||||
|    second_const_reference second() const { return *this; } | ||||
|  | ||||
|    void swap(compressed_pair_1& y) | ||||
|    { | ||||
|       // no need to swap empty base class: | ||||
|       using std::swap; | ||||
|       swap(_first, y._first); | ||||
|    } | ||||
| }; | ||||
|  | ||||
| // T1 != T2, T1 empty | ||||
| template <class T1, class T2> | ||||
| class compressed_pair_2 : T1 | ||||
| { | ||||
| private: | ||||
|    T2 _second; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair_2() : T1(), _second() {} | ||||
|             compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {} | ||||
|    template <class A> | ||||
|    explicit compressed_pair_2(const A& val) | ||||
|    { | ||||
|       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second); | ||||
|    } | ||||
|    compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x) | ||||
|       : T1(x.first()), _second(x.second()) {} | ||||
|  | ||||
| #if 0 | ||||
|   compressed_pair_2& operator=(const compressed_pair_2& x) { | ||||
|     cout << "assigning compressed pair 2" << endl; | ||||
|     T1::operator=(x); | ||||
|     _second = x._second; | ||||
|     cout << "finished assigning compressed pair 2" << endl; | ||||
|     return *this; | ||||
|   } | ||||
| #endif | ||||
|    first_reference       first()       { return *this; } | ||||
|    first_const_reference first() const { return *this; } | ||||
|  | ||||
|    second_reference       second()       { return _second; } | ||||
|    second_const_reference second() const { return _second; } | ||||
|  | ||||
|    void swap(compressed_pair_2& y) | ||||
|    { | ||||
|       // no need to swap empty base class: | ||||
|       using std::swap; | ||||
|       swap(_second, y._second); | ||||
|    } | ||||
| }; | ||||
|  | ||||
| // T1 != T2, both empty | ||||
| template <class T1, class T2> | ||||
| class compressed_pair_3 : T1, T2 | ||||
| { | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair_3() : T1(), T2() {} | ||||
|             compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {} | ||||
|    template <class A> | ||||
|    explicit compressed_pair_3(const A& val) | ||||
|    { | ||||
|       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this)); | ||||
|    } | ||||
|    compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x) | ||||
|       : T1(x.first()), T2(x.second()) {} | ||||
|  | ||||
|    first_reference       first()       { return *this; } | ||||
|    first_const_reference first() const { return *this; } | ||||
|  | ||||
|    second_reference       second()       { return *this; } | ||||
|    second_const_reference second() const { return *this; } | ||||
|  | ||||
|    void swap(compressed_pair_3& y) | ||||
|    { | ||||
|       // no need to swap empty base classes: | ||||
|    } | ||||
| }; | ||||
|  | ||||
| // T1 == T2, and empty | ||||
| template <class T1, class T2> | ||||
| class compressed_pair_4 : T1 | ||||
| { | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair_4() : T1() {} | ||||
|             compressed_pair_4(first_param_type x, second_param_type) : T1(x) {} | ||||
|    // only one single argument constructor since T1 == T2 | ||||
|    explicit compressed_pair_4(first_param_type x) : T1(x) {} | ||||
|    compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x) | ||||
|       : T1(x.first()){} | ||||
|  | ||||
|    first_reference       first()       { return *this; } | ||||
|    first_const_reference first() const { return *this; } | ||||
|  | ||||
|    second_reference       second()       { return *this; } | ||||
|    second_const_reference second() const { return *this; } | ||||
|  | ||||
|    void swap(compressed_pair_4& y) | ||||
|    { | ||||
|       // no need to swap empty base classes: | ||||
|    } | ||||
| }; | ||||
|  | ||||
| // T1 == T2, not empty | ||||
| template <class T1, class T2> | ||||
| class compressed_pair_5 | ||||
| { | ||||
| private: | ||||
|    T1 _first; | ||||
|    T2 _second; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair_5() : _first(), _second() {} | ||||
|             compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {} | ||||
|    // only one single argument constructor since T1 == T2 | ||||
|    explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {} | ||||
|    compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c)  | ||||
|       : _first(c.first()), _second(c.second()) {} | ||||
|  | ||||
|    first_reference       first()       { return _first; } | ||||
|    first_const_reference first() const { return _first; } | ||||
|  | ||||
|    second_reference       second()       { return _second; } | ||||
|    second_const_reference second() const { return _second; } | ||||
|  | ||||
|    void swap(compressed_pair_5& y) | ||||
|    { | ||||
|       using std::swap; | ||||
|       swap(_first, y._first); | ||||
|       swap(_second, y._second); | ||||
|    } | ||||
| }; | ||||
|  | ||||
| template <bool e1, bool e2, bool same> | ||||
| struct compressed_pair_chooser | ||||
| { | ||||
|    template <class T1, class T2> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef compressed_pair_0<T1, T2> type; | ||||
|    }; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct compressed_pair_chooser<false, true, false> | ||||
| { | ||||
|    template <class T1, class T2> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef compressed_pair_1<T1, T2> type; | ||||
|    }; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct compressed_pair_chooser<true, false, false> | ||||
| { | ||||
|    template <class T1, class T2> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef compressed_pair_2<T1, T2> type; | ||||
|    }; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct compressed_pair_chooser<true, true, false> | ||||
| { | ||||
|    template <class T1, class T2> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef compressed_pair_3<T1, T2> type; | ||||
|    }; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct compressed_pair_chooser<true, true, true> | ||||
| { | ||||
|    template <class T1, class T2> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef compressed_pair_4<T1, T2> type; | ||||
|    }; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct compressed_pair_chooser<false, false, true> | ||||
| { | ||||
|    template <class T1, class T2> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef compressed_pair_5<T1, T2> type; | ||||
|    }; | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_traits | ||||
| { | ||||
| private: | ||||
|    typedef compressed_pair_chooser<is_empty<T1>::value, is_empty<T2>::value, is_same<T1,T2>::value> chooser; | ||||
|    typedef typename chooser::template rebind<T1, T2> bound_type; | ||||
| public: | ||||
|    typedef typename bound_type::type type; | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| template <class T1, class T2> | ||||
| class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type | ||||
| { | ||||
| private: | ||||
|    typedef typename detail::compressed_pair_traits<T1, T2>::type base_type; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair() : base_type() {} | ||||
|             compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {} | ||||
|    template <class A> | ||||
|    explicit compressed_pair(const A& x) : base_type(x){} | ||||
|  | ||||
|    first_reference       first()       { return base_type::first(); } | ||||
|    first_const_reference first() const { return base_type::first(); } | ||||
|  | ||||
|    second_reference       second()       { return base_type::second(); } | ||||
|    second_const_reference second() const { return base_type::second(); } | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y) | ||||
| { | ||||
|    x.swap(y); | ||||
| } | ||||
|  | ||||
| #else | ||||
| // no partial specialisation, no member templates: | ||||
|  | ||||
| template <class T1, class T2> | ||||
| class compressed_pair | ||||
| { | ||||
| private: | ||||
|    T1 _first; | ||||
|    T2 _second; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair() : _first(), _second() {} | ||||
|             compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {} | ||||
|    explicit compressed_pair(first_param_type x) : _first(x), _second() {} | ||||
|    // can't define this in case T1 == T2: | ||||
|    // explicit compressed_pair(second_param_type y) : _first(), _second(y) {} | ||||
|  | ||||
|    first_reference       first()       { return _first; } | ||||
|    first_const_reference first() const { return _first; } | ||||
|  | ||||
|    second_reference       second()       { return _second; } | ||||
|    second_const_reference second() const { return _second; } | ||||
|  | ||||
|    void swap(compressed_pair& y) | ||||
|    { | ||||
|       using std::swap; | ||||
|       swap(_first, y._first); | ||||
|       swap(_second, y._second); | ||||
|    } | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y) | ||||
| { | ||||
|    x.swap(y); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| } // boost | ||||
|  | ||||
| #endif // BOOST_OB_COMPRESSED_PAIR_HPP | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -1,565 +0,0 @@ | ||||
| //  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. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  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 | ||||
| //            Dave Abrahams)  | ||||
| //  28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and | ||||
| //            Jeremy Siek (Dave Abrahams) | ||||
| //  20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5 | ||||
| //            (Mark Rodgers) | ||||
| //  20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy) | ||||
| //  10 Jun 00 Support for the base class chaining technique was added | ||||
| //            (Aleksey Gurtovoy). See documentation and the comments below  | ||||
| //            for the details.  | ||||
| //  12 Dec 99 Initial version with iterator operators (Jeremy Siek) | ||||
| //  18 Nov 99 Change name "divideable" to "dividable", remove unnecessary | ||||
| //            specializations of dividable, subtractable, modable (Ed Brey)  | ||||
| //  17 Nov 99 Add comments (Beman Dawes) | ||||
| //            Remove unnecessary specialization of operators<> (Ed Brey) | ||||
| //  15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two | ||||
| //            operators.(Beman Dawes) | ||||
| //  12 Nov 99 Add operators templates (Ed Brey) | ||||
| //  11 Nov 99 Add single template parameter version for compilers without | ||||
| //            partial specialization (Beman Dawes) | ||||
| //  10 Nov 99 Initial version | ||||
|  | ||||
| // 10 Jun 00: | ||||
| // An additional optional template parameter was added to most of  | ||||
| // operator templates to support the base class chaining technique (see  | ||||
| // documentation for the details). Unfortunately, a straightforward | ||||
| // implementation of this change would have broken compatibility with the | ||||
| // previous version of the library by making it impossible to use the same | ||||
| // template name (e.g. 'addable') for both the 1- and 2-argument versions of | ||||
| // an operator template. This implementation solves the backward-compatibility | ||||
| // issue at the cost of some simplicity. | ||||
| // | ||||
| // One of the complications is an existence of special auxiliary class template | ||||
| // 'is_chained_base<>' (see 'detail' namespace below), which is used | ||||
| // to determine whether its template parameter is a library's operator template | ||||
| // or not. You have to specialize 'is_chained_base<>' for each new  | ||||
| // operator template you add to the library. | ||||
| // | ||||
| // However, most of the non-trivial implementation details are hidden behind  | ||||
| // several local macros defined below, and as soon as you understand them, | ||||
| // you understand the whole library implementation.  | ||||
|  | ||||
| #ifndef BOOST_OPERATORS_HPP | ||||
| #define BOOST_OPERATORS_HPP | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <boost/iterator.hpp> | ||||
|  | ||||
| #if defined(__sgi) && !defined(__GNUC__) | ||||
| #pragma set woff 1234 | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_MSVC) | ||||
| #   pragma warning( disable : 4284 ) // complaint about return type of  | ||||
| #endif                               // operator-> not begin a UDT | ||||
|  | ||||
| namespace boost { | ||||
| namespace detail { | ||||
|  | ||||
| class empty_base {}; | ||||
|  | ||||
| } // namespace detail | ||||
| } // namespace boost | ||||
|  | ||||
| // In this section we supply the xxxx1 and xxxx2 forms of the operator | ||||
| // templates, which are explicitly targeted at the 1-type-argument and | ||||
| // 2-type-argument operator forms, respectively. Some compilers get confused | ||||
| // when inline friend functions are overloaded in namespaces other than the | ||||
| // global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of | ||||
| // these templates must go in the global namespace. | ||||
|  | ||||
| #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE | ||||
| namespace boost | ||||
| { | ||||
| #endif | ||||
|  | ||||
| //  Basic operator classes (contributed by Dave Abrahams) ------------------// | ||||
|  | ||||
| //  Note that friend functions defined in a class are implicitly inline. | ||||
| //  See the C++ std, 11.4 [class.friend] paragraph 5 | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct less_than_comparable2 : B | ||||
| { | ||||
|      friend bool operator<=(const T& x, const U& y) { return !(x > y); } | ||||
|      friend bool operator>=(const T& x, const U& y) { return !(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); } | ||||
|      friend bool operator>=(const U& x, const T& y) { return !(y > x); } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct less_than_comparable1 : B | ||||
| { | ||||
|      friend bool operator>(const T& x, const T& y)  { return y < x; } | ||||
|      friend bool operator<=(const T& x, const T& y) { return !(y < x); } | ||||
|      friend bool operator>=(const T& x, const T& y) { return !(x < y); } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct equality_comparable2 : B | ||||
| { | ||||
|      friend bool operator==(const U& y, const T& x) { return x == y; } | ||||
|      friend bool operator!=(const U& y, const T& x) { return !(x == y); } | ||||
|      friend bool operator!=(const T& y, const U& x) { return !(y == x); } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct equality_comparable1 : B | ||||
| { | ||||
|      friend bool operator!=(const T& x, const T& y) { return !(x == y); } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct multipliable2 : B | ||||
| { | ||||
|      friend T operator*(T x, const U& y) { return x *= y; } | ||||
|      friend T operator*(const U& y, T x) { return x *= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct multipliable1 : B | ||||
| { | ||||
|      friend T operator*(T x, const T& y) { return x *= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct addable2 : B | ||||
| { | ||||
|      friend T operator+(T x, const U& y) { return x += y; } | ||||
|      friend T operator+(const U& y, T x) { return x += y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct addable1 : B | ||||
| { | ||||
|      friend T operator+(T x, const T& y) { return x += y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct subtractable2 : B | ||||
| { | ||||
|      friend T operator-(T x, const U& y) { return x -= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct subtractable1 : B | ||||
| { | ||||
|      friend T operator-(T x, const T& y) { return x -= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct dividable2 : B | ||||
| { | ||||
|      friend T operator/(T x, const U& y) { return x /= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct dividable1 : B | ||||
| { | ||||
|      friend T operator/(T x, const T& y) { return x /= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct modable2 : B | ||||
| { | ||||
|      friend T operator%(T x, const U& y) { return x %= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct modable1 : B | ||||
| { | ||||
|      friend T operator%(T x, const T& y) { return x %= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct xorable2 : B | ||||
| { | ||||
|      friend T operator^(T x, const U& y) { return x ^= y; } | ||||
|      friend T operator^(const U& y, T x) { return x ^= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct xorable1 : B | ||||
| { | ||||
|      friend T operator^(T x, const T& y) { return x ^= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct andable2 : B | ||||
| { | ||||
|      friend T operator&(T x, const U& y) { return x &= y; } | ||||
|      friend T operator&(const U& y, T x) { return x &= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct andable1 : B | ||||
| { | ||||
|      friend T operator&(T x, const T& y) { return x &= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct orable2 : B | ||||
| { | ||||
|      friend T operator|(T x, const U& y) { return x |= y; } | ||||
|      friend T operator|(const U& y, T x) { return x |= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct orable1 : B | ||||
| { | ||||
|      friend T operator|(T x, const T& y) { return x |= y; } | ||||
| }; | ||||
|  | ||||
| //  incrementable and decrementable contributed by Jeremy Siek | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct incrementable : B | ||||
| { | ||||
|   friend T operator++(T& x, int) | ||||
|   { | ||||
|     incrementable_type tmp(x); | ||||
|     ++x; | ||||
|     return tmp; | ||||
|   } | ||||
| private: // The use of this typedef works around a Borland bug | ||||
|   typedef T incrementable_type; | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct decrementable : B | ||||
| { | ||||
|   friend T operator--(T& x, int) | ||||
|   { | ||||
|     decrementable_type tmp(x); | ||||
|     --x; | ||||
|     return tmp; | ||||
|   } | ||||
| private: // The use of this typedef works around a Borland bug | ||||
|   typedef T decrementable_type; | ||||
| }; | ||||
|  | ||||
| //  Iterator operator classes (contributed by Jeremy Siek) ------------------// | ||||
|  | ||||
| template <class T, class P, class B = ::boost::detail::empty_base> | ||||
| struct dereferenceable : B | ||||
| { | ||||
|   P operator->() const | ||||
|   {  | ||||
|     return &*static_cast<const T&>(*this);  | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <class T, class I, class R, class B = ::boost::detail::empty_base> | ||||
| struct indexable : B | ||||
| { | ||||
|   R operator[](I n) const | ||||
|   { | ||||
|     return *(static_cast<const T&>(*this) + n); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| #ifndef BOOST_NO_OPERATORS_IN_NAMESPACE | ||||
| } // namespace boost | ||||
| #endif // BOOST_NO_OPERATORS_IN_NAMESPACE | ||||
|  | ||||
|  | ||||
| // BOOST_IMPORT_TEMPLATE1/BOOST_IMPORT_TEMPLATE2 - | ||||
| // | ||||
| // 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 | ||||
| // for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for | ||||
| // two-argument forms. Note that these macros expect to be invoked from within | ||||
| // boost. | ||||
|  | ||||
| #if defined(BOOST_NO_OPERATORS_IN_NAMESPACE) | ||||
|  | ||||
| #  if defined(BOOST_NO_USING_TEMPLATE) | ||||
|  | ||||
|      // 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> {}; | ||||
|  | ||||
| #    define BOOST_IMPORT_TEMPLATE1(template_name)                              \ | ||||
|      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 | ||||
|  | ||||
| // | ||||
| // Here's where we put it all together, defining the xxxx forms of the templates | ||||
| // in namespace boost. We also define specializations of is_chained_base<> for | ||||
| // the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as | ||||
| // neccessary. | ||||
| // | ||||
| #if !defined(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 | ||||
| // 2nd argument type. | ||||
|  | ||||
| namespace boost { | ||||
| // A type parameter is used instead of a plain bool because Borland's compiler | ||||
| // didn't cope well with the more obvious non-type template parameter. | ||||
| namespace detail { | ||||
|   struct true_t {}; | ||||
|   struct false_t {}; | ||||
| } // namespace detail | ||||
|  | ||||
| // Unspecialized version assumes that most types are not being used for base | ||||
| // class chaining. We specialize for the operator templates defined in this | ||||
| // library. | ||||
| template<class T> struct is_chained_base { | ||||
|   typedef ::boost::detail::false_t value; | ||||
| }; | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| // 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)                  \ | ||||
|   BOOST_IMPORT_TEMPLATE2(template_name2)                           \ | ||||
|   template<class T, class U, class B>                              \ | ||||
|   struct is_chained_base< ::boost::template_name2<T, U, B> > {     \ | ||||
|     typedef ::boost::detail::true_t value;                         \ | ||||
|   }; | ||||
|  | ||||
| // Import a 1-type-argument operator template into boost (if neccessary) and | ||||
| // provide a specialization of 'is_chained_base<>' for it. | ||||
| # define BOOST_OPERATOR_TEMPLATE1(template_name1)                  \ | ||||
|   BOOST_IMPORT_TEMPLATE1(template_name1)                           \ | ||||
|   template<class T, class B>                                       \ | ||||
|   struct is_chained_base< ::boost::template_name1<T, B> > {        \ | ||||
|     typedef ::boost::detail::true_t value;                         \ | ||||
|   }; | ||||
|  | ||||
| // BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it | ||||
| // can be used for specifying both 1-argument and 2-argument forms. Requires the | ||||
| // existence of two previously defined class templates named '<template_name>1' | ||||
| // and '<template_name>2' which must implement the corresponding 1- and 2- | ||||
| // argument forms. | ||||
| // | ||||
| // The template type parameter O == is_chained_base<U>::value is used to | ||||
| // distinguish whether the 2nd argument to <template_name> is being used for | ||||
| // base class chaining from another boost operator template or is describing a | ||||
| // 2nd operand type. O == true_t only when U is actually an another operator | ||||
| // template from the library. Partial specialization is used to select an | ||||
| // implementation in terms of either '<template_name>1' or '<template_name>2'. | ||||
| // | ||||
|  | ||||
| # define BOOST_OPERATOR_TEMPLATE(template_name)                    \ | ||||
| template <class T                                                  \ | ||||
|          ,class U = T                                              \ | ||||
|          ,class B = ::boost::detail::empty_base                    \ | ||||
|          ,class O = typename is_chained_base<U>::value             \ | ||||
|          >                                                         \ | ||||
| struct template_name : template_name##2<T, U, B> {};               \ | ||||
|                                                                    \ | ||||
| template<class T, class U, class B>                                \ | ||||
| struct template_name<T, U, B, ::boost::detail::true_t>             \ | ||||
|   : template_name##1<T, U> {};                                     \ | ||||
|                                                                    \ | ||||
| template <class T, class B>                                        \ | ||||
| struct template_name<T, T, B, ::boost::detail::false_t>            \ | ||||
|   : template_name##1<T, B> {};                                     \ | ||||
|                                                                    \ | ||||
| template<class T, class U, class B, class O>                       \ | ||||
| struct is_chained_base< ::boost::template_name<T, U, B, O> > {     \ | ||||
|   typedef ::boost::detail::true_t value;                           \ | ||||
| };                                                                 \ | ||||
|                                                                    \ | ||||
| BOOST_OPERATOR_TEMPLATE2(template_name##2)                         \ | ||||
| BOOST_OPERATOR_TEMPLATE1(template_name##1) | ||||
|  | ||||
|  | ||||
| #else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|  | ||||
| #  define BOOST_OPERATOR_TEMPLATE2(template_name2) \ | ||||
|         BOOST_IMPORT_TEMPLATE2(template_name2) | ||||
| #  define BOOST_OPERATOR_TEMPLATE1(template_name1) \ | ||||
|         BOOST_IMPORT_TEMPLATE1(template_name1) | ||||
|  | ||||
|    // In this case we can only assume that template_name<> is equivalent to the | ||||
|    // more commonly needed template_name1<> form. | ||||
| #  define BOOST_OPERATOR_TEMPLATE(template_name)                   \ | ||||
|    template <class T, class B = ::boost::detail::empty_base>       \ | ||||
|    struct template_name : template_name##1<T, B> {}; | ||||
|  | ||||
| #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|  | ||||
| namespace boost { | ||||
|      | ||||
| BOOST_OPERATOR_TEMPLATE(less_than_comparable) | ||||
| BOOST_OPERATOR_TEMPLATE(equality_comparable) | ||||
| BOOST_OPERATOR_TEMPLATE(multipliable) | ||||
| BOOST_OPERATOR_TEMPLATE(addable) | ||||
| BOOST_OPERATOR_TEMPLATE(subtractable) | ||||
| BOOST_OPERATOR_TEMPLATE(dividable) | ||||
| BOOST_OPERATOR_TEMPLATE(modable) | ||||
| BOOST_OPERATOR_TEMPLATE(xorable) | ||||
| BOOST_OPERATOR_TEMPLATE(andable) | ||||
| BOOST_OPERATOR_TEMPLATE(orable) | ||||
|  | ||||
| BOOST_OPERATOR_TEMPLATE1(incrementable) | ||||
| BOOST_OPERATOR_TEMPLATE1(decrementable) | ||||
| BOOST_OPERATOR_TEMPLATE2(dereferenceable) | ||||
|  | ||||
| // 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 | ||||
|  | ||||
| #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 | ||||
|  | ||||
| #undef BOOST_OPERATOR_TEMPLATE | ||||
| #undef BOOST_OPERATOR_TEMPLATE2 | ||||
| #undef BOOST_OPERATOR_TEMPLATE1 | ||||
| #undef BOOST_IMPORT_TEMPLATE1 | ||||
| #undef BOOST_IMPORT_TEMPLATE2 | ||||
|  | ||||
| // 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 | ||||
|       > > > > > > > > > > {}; | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template <class T, class U = T> | ||||
| struct operators : operators2<T, U> {}; | ||||
|  | ||||
| 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 | ||||
|       > > > > > > > > > > > > {}; | ||||
|  | ||||
| //  Iterator helper classes (contributed by Jeremy Siek) -------------------// | ||||
| template <class T, | ||||
|           class V, | ||||
|           class D = std::ptrdiff_t, | ||||
|           class P = V*, | ||||
|           class R = V&> | ||||
| struct forward_iterator_helper | ||||
|   : equality_comparable<T | ||||
|   , incrementable<T | ||||
|   , dereferenceable<T,P | ||||
|   , boost::iterator<std::forward_iterator_tag,V,D,P,R | ||||
|     > > > > {}; | ||||
|  | ||||
| template <class T, | ||||
|           class V, | ||||
|           class D = std::ptrdiff_t, | ||||
|           class P = V*, | ||||
|           class R = V&> | ||||
| struct bidirectional_iterator_helper | ||||
|   : equality_comparable<T | ||||
|   , incrementable<T | ||||
|   , decrementable<T | ||||
|   , dereferenceable<T,P | ||||
|   , boost::iterator<std::bidirectional_iterator_tag,V,D,P,R | ||||
|     > > > > > {}; | ||||
|  | ||||
| template <class T, | ||||
|           class V,  | ||||
|           class D = std::ptrdiff_t, | ||||
|           class P = V*, | ||||
|           class R = V&> | ||||
| struct random_access_iterator_helper | ||||
|   : equality_comparable<T | ||||
|   , less_than_comparable<T | ||||
|   , incrementable<T | ||||
|   , decrementable<T | ||||
|   , dereferenceable<T,P | ||||
|   , addable2<T,D | ||||
|   , subtractable2<T,D | ||||
|   , indexable<T,D,R | ||||
|   , boost::iterator<std::random_access_iterator_tag,V,D,P,R | ||||
|     > > > > > > > > > | ||||
| { | ||||
| #ifndef __BORLANDC__ | ||||
|   friend D requires_difference_operator(const T& x, const T& y) { | ||||
|     return x - y; | ||||
|   } | ||||
| #endif | ||||
| }; // random_access_iterator_helper | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #if defined(__sgi) && !defined(__GNUC__) | ||||
| #pragma reset woff 1234 | ||||
| #endif | ||||
|  | ||||
| #endif // BOOST_OPERATORS_HPP | ||||
| @@ -1,96 +0,0 @@ | ||||
| //  boost utility.hpp header file  -------------------------------------------// | ||||
|  | ||||
| //  (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. | ||||
|  | ||||
| //  Classes appear in alphabetical order | ||||
|  | ||||
| //  Revision History | ||||
| //  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) | ||||
| //   3 Aug 99  cast templates added | ||||
| //  20 Jul 99  name changed to utility.hpp  | ||||
| //   9 Jun 99  protected noncopyable default ctor | ||||
| //   2 Jun 99  Initial Version. Class noncopyable only contents (Dave Abrahams) | ||||
|  | ||||
| #ifndef BOOST_UTILITY_HPP | ||||
| #define BOOST_UTILITY_HPP | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <cstddef>            // for size_t | ||||
| #include <utility>            // for std::pair | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| //  next() and prior() template functions  -----------------------------------// | ||||
|  | ||||
|     //  Helper functions for classes like bidirectional iterators not supporting | ||||
|     //  operator+ and operator-. | ||||
|     // | ||||
|     //  Usage: | ||||
|     //    const std::list<T>::iterator p = get_some_iterator(); | ||||
|     //    const std::list<T>::iterator prev = boost::prior(p); | ||||
|  | ||||
|     //  Contributed by Dave Abrahams | ||||
|  | ||||
|     template <class T> | ||||
|     T next(T x) { return ++x; } | ||||
|  | ||||
|     template <class T> | ||||
|     T prior(T x) { return --x; } | ||||
|  | ||||
|  | ||||
| //  class noncopyable  -------------------------------------------------------// | ||||
|  | ||||
|     //  Private copy constructor and copy assignment ensure classes derived from | ||||
|     //  class noncopyable cannot be copied. | ||||
|  | ||||
|     //  Contributed by Dave Abrahams | ||||
|  | ||||
|     class noncopyable | ||||
|     { | ||||
|     protected: | ||||
|         noncopyable(){} | ||||
|         ~noncopyable(){} | ||||
|     private:  // emphasize the following members are private | ||||
|         noncopyable( const noncopyable& ); | ||||
|         const noncopyable& operator=( const noncopyable& ); | ||||
|     }; // noncopyable | ||||
|  | ||||
| //  class tied  -------------------------------------------------------// | ||||
|  | ||||
|     // A helper for conveniently assigning the two values from a pair | ||||
|     // into separate variables. The idea for this comes from Jaakko J<>rvi's | ||||
|     // Binder/Lambda Library. | ||||
|  | ||||
|     // Constributed by Jeremy Siek | ||||
|  | ||||
|     template <class A, class B> | ||||
|     class tied { | ||||
|     public: | ||||
|       inline tied(A& a, B& b) : _a(a), _b(b) { } | ||||
|       template <class U, class V> | ||||
|       inline tied& operator=(const std::pair<U,V>& p) { | ||||
|         _a = p.first; | ||||
|         _b = p.second; | ||||
|         return *this; | ||||
|       } | ||||
|     protected: | ||||
|       A& _a; | ||||
|       B& _b; | ||||
|     }; | ||||
|  | ||||
|     template <class A, class B> | ||||
|     inline tied<A,B> tie(A& a, B& b) { return tied<A,B>(a, b); } | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // BOOST_UTILITY_HPP | ||||
|  | ||||
| @@ -1,61 +0,0 @@ | ||||
| // (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and | ||||
| // distribute this software is granted provided this copyright notice appears | ||||
| // in all copies. This software is provided "as is" without express or implied | ||||
| // warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
| #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, 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; | ||||
|  | ||||
|    | ||||
|   // 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; | ||||
| } | ||||
| @@ -1,27 +0,0 @@ | ||||
| //  Test boost/pending/iterator_adaptors.hpp | ||||
|  | ||||
| //  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, | ||||
| //  sell and distribute this software is granted provided this | ||||
| //  copyright notice appears in all copies. This software is provided | ||||
| //  "as is" without express or implied warranty, and with no claim as | ||||
| //  to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| // Revision History | ||||
| // 21 Jan 01 Initial version (Jeremy Siek) | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <list> | ||||
| #include <boost/pending/iterator_adaptors.hpp> | ||||
|  | ||||
| int main() | ||||
| { | ||||
|   typedef boost::iterator_adaptor<std::list<int>::iterator, | ||||
|     boost::default_iterator_policies, | ||||
|     int,int&,int*,std::bidirectional_iterator_tag> adaptor_type; | ||||
|    | ||||
|   adaptor_type i; | ||||
|   i += 4; | ||||
|   return 0; | ||||
| } | ||||
| @@ -1,28 +0,0 @@ | ||||
| //  Test boost/pending/iterator_adaptors.hpp | ||||
|  | ||||
| //  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, | ||||
| //  sell and distribute this software is granted provided this | ||||
| //  copyright notice appears in all copies. This software is provided | ||||
| //  "as is" without express or implied warranty, and with no claim as | ||||
| //  to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| // Revision History | ||||
| // 21 Jan 01 Initial version (Jeremy Siek) | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <iostream> | ||||
| #include <iterator> | ||||
| #include <boost/pending/iterator_adaptors.hpp> | ||||
|  | ||||
| int main() | ||||
| { | ||||
|   typedef boost::iterator_adaptor<std::istream_iterator<int>, | ||||
|     boost::default_iterator_policies, | ||||
|     int,int&,int*,std::input_iterator_tag> adaptor_type; | ||||
|    | ||||
|   adaptor_type iter; | ||||
|   --iter; | ||||
|   return 0; | ||||
| } | ||||
| @@ -1,47 +0,0 @@ | ||||
| // (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and | ||||
| // distribute this software is granted provided this copyright notice appears | ||||
| // in all copies. This software is provided "as is" without express or implied | ||||
| // warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
|  | ||||
| #include <functional> | ||||
| #include <algorithm> | ||||
| #include <iostream> | ||||
| #include <boost/pending/iterator_adaptors.hpp> | ||||
| #include <boost/pending/integer_range.hpp> | ||||
|  | ||||
| int | ||||
| main(int, char*[]) | ||||
| { | ||||
|   // This is a simple example of using the transform_iterators class to | ||||
|   // generate iterators that multiply the value returned by dereferencing | ||||
|   // the iterator. In this case we are multiplying by 2. | ||||
|   // Would be cooler to use lambda library in this example. | ||||
|  | ||||
|   int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; | ||||
|  | ||||
|   typedef std::binder1st< std::multiplies<int> > Function; | ||||
|   typedef boost::transform_iterator<Function, int*,  | ||||
|     boost::iterator<std::random_access_iterator_tag, int> | ||||
|   >::type doubling_iterator; | ||||
|  | ||||
|   doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)), | ||||
|     i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2)); | ||||
|  | ||||
|   std::cout << "multiplying the array by 2:" << std::endl; | ||||
|   while (i != i_end) | ||||
|     std::cout << *i++ << " "; | ||||
|   std::cout << std::endl; | ||||
|  | ||||
|   // Here is an example of counting from 0 to 5 using the integer_range class. | ||||
|  | ||||
|   boost::integer_range<int> r(0,5); | ||||
|  | ||||
|   std::cout << "counting to from 0 to 4:" << std::endl; | ||||
|   std::copy(r.begin(), r.end(), std::ostream_iterator<int>(std::cout, " ")); | ||||
|   std::cout << std::endl; | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -1,458 +0,0 @@ | ||||
| //  Demonstrate and test boost/operators.hpp on std::iterators  -------------// | ||||
|  | ||||
| //  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, | ||||
| //  sell and distribute this software is granted provided this | ||||
| //  copyright notice appears in all copies. This software is provided | ||||
| //  "as is" without express or implied warranty, and with no claim as | ||||
| //  to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  19 Feb 01 Take adavantage of improved iterator_traits to do more tests | ||||
| //            on MSVC. Hack around an MSVC-with-STLport internal compiler | ||||
| //            error. (David Abrahams) | ||||
| //  11 Feb 01 Added test of operator-> for forward and input iterators. | ||||
| //            (Jeremy Siek) | ||||
| //  11 Feb 01 Borland fixes (David Abrahams) | ||||
| //  10 Feb 01 Use new adaptors interface. (David Abrahams) | ||||
| //  10 Feb 01 Use new filter_ interface. (David Abrahams) | ||||
| //  09 Feb 01 Use new reverse_ and indirect_ interfaces. Replace | ||||
| //            BOOST_NO_STD_ITERATOR_TRAITS with | ||||
| //            BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION to prove we've | ||||
| //            normalized to core compiler capabilities (David Abrahams) | ||||
| //  08 Feb 01 Use Jeremy's new make_reverse_iterator form; add more | ||||
| //            comprehensive testing. Force-decay array function arguments to | ||||
| //            pointers. | ||||
| //  07 Feb 01 Added tests for the make_xxx_iterator() helper functions. | ||||
| //            (Jeremy Siek) | ||||
| //  07 Feb 01 Replaced use of xxx_pair_generator with xxx_generator where | ||||
| //            possible (which was all but the projection iterator). | ||||
| //            (Jeremy Siek) | ||||
| //  06 Feb 01 Removed now-defaulted template arguments where possible | ||||
| //            Updated names to correspond to new generator naming convention. | ||||
| //            Added a trivial test for make_transform_iterator(). | ||||
| //            Gave traits for const iterators a mutable value_type, per std. | ||||
| //            Resurrected my original tests for indirect iterators. | ||||
| //            (David Abrahams) | ||||
| //  04 Feb 01 Fix for compilers without standard iterator_traits | ||||
| //            (David Abrahams) | ||||
| //  13 Jun 00 Added const version of the iterator tests (Jeremy Siek) | ||||
| //  12 Dec 99 Initial version with iterator operators (Jeremy Siek) | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <iostream> | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <functional> | ||||
|  | ||||
| #include <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_adaptor<dummyT*,  | ||||
|   boost::default_iterator_policies, dummyT> my_iterator; | ||||
|  | ||||
| typedef boost::iterator_adaptor<const dummyT*,  | ||||
|   boost::default_iterator_policies, const dummyT> const_my_iterator; | ||||
|  | ||||
|  | ||||
| struct mult_functor { | ||||
|   typedef int result_type; | ||||
|   typedef int argument_type; | ||||
|   // Functors used with transform_iterator must be | ||||
|   // DefaultConstructible, as the transform_iterator must be | ||||
|   // DefaultConstructible to satisfy the requirements for | ||||
|   // TrivialIterator. | ||||
|   mult_functor() { } | ||||
|   mult_functor(int aa) : a(aa) { } | ||||
|   int operator()(int b) const { return a * b; } | ||||
|   int a; | ||||
| }; | ||||
|  | ||||
| template <class Pair> | ||||
| struct select1st_  | ||||
|   : public std::unary_function<Pair, typename Pair::first_type> | ||||
| { | ||||
|   const typename Pair::first_type& operator()(const Pair& x) const { | ||||
|     return x.first; | ||||
|   } | ||||
|   typename Pair::first_type& operator()(Pair& x) const { | ||||
|     return x.first; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| struct one_or_four { | ||||
|   bool operator()(dummyT x) const { | ||||
|     return x.foo() == 1 || x.foo() == 4; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| typedef std::deque<int> storage; | ||||
| typedef std::deque<int*> pointer_deque; | ||||
| typedef std::set<storage::iterator> iterator_set; | ||||
|  | ||||
| void more_indirect_iterator_tests() | ||||
| { | ||||
| // For some reason all heck breaks loose in the compiler under these conditions. | ||||
| #if !defined(BOOST_MSVC) || !defined(__STL_DEBUG) | ||||
|     storage store(1000); | ||||
|     std::generate(store.begin(), store.end(), rand); | ||||
|      | ||||
|     pointer_deque ptr_deque; | ||||
|     iterator_set iter_set; | ||||
|  | ||||
|     for (storage::iterator p = store.begin(); p != store.end(); ++p) | ||||
|     { | ||||
|         ptr_deque.push_back(&*p); | ||||
|         iter_set.insert(p); | ||||
|     } | ||||
|  | ||||
|     typedef boost::indirect_iterator_pair_generator< | ||||
|         pointer_deque::iterator | ||||
| #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|         , int | ||||
| #endif | ||||
|     > IndirectDeque; | ||||
|  | ||||
|     IndirectDeque::iterator db(ptr_deque.begin()); | ||||
|     IndirectDeque::iterator de(ptr_deque.end()); | ||||
|     assert(static_cast<std::size_t>(de - db) == store.size()); | ||||
|     assert(db + store.size() == de); | ||||
|     IndirectDeque::const_iterator dci(db); | ||||
|     assert(db == dci); | ||||
|     assert(dci == db); | ||||
|     assert(dci != de); | ||||
|     assert(dci < de); | ||||
|     assert(dci <= de); | ||||
|     assert(de >= dci); | ||||
|     assert(de > dci); | ||||
|     dci = de; | ||||
|     assert(dci == de); | ||||
|  | ||||
|     boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin())); | ||||
|      | ||||
|     *db = 999; | ||||
|     assert(store.front() == 999); | ||||
|  | ||||
|     typedef boost::indirect_iterator_generator< | ||||
|         iterator_set::iterator | ||||
| #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|         , int | ||||
| #endif | ||||
|         >::type indirect_set_iterator; | ||||
|  | ||||
|     typedef boost::indirect_iterator_generator< | ||||
|         iterator_set::iterator, | ||||
|         const int | ||||
|         >::type const_indirect_set_iterator; | ||||
|  | ||||
|     indirect_set_iterator sb(iter_set.begin()); | ||||
|     indirect_set_iterator se(iter_set.end()); | ||||
|     const_indirect_set_iterator sci(iter_set.begin()); | ||||
|     assert(sci == sb); | ||||
|     assert(sci != se); | ||||
|     sci = se; | ||||
|     assert(sci == se); | ||||
|      | ||||
|     *boost::prior(se) = 888; | ||||
|     assert(store.back() == 888); | ||||
|     assert(std::equal(sb, se, store.begin())); | ||||
|  | ||||
|     boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]); | ||||
|     assert(std::equal(db, de, store.begin())); | ||||
| #endif     | ||||
| } | ||||
|  | ||||
| int | ||||
| main() | ||||
| { | ||||
|   dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),  | ||||
|                      dummyT(3), dummyT(4), dummyT(5) }; | ||||
|   const int N = sizeof(array)/sizeof(dummyT); | ||||
|  | ||||
|   // sanity check, if this doesn't pass the test is buggy | ||||
|   boost::random_access_iterator_test(array,N,array); | ||||
|  | ||||
|   // Check that the policy concept checks and the default policy | ||||
|   // implementation match up. | ||||
|   boost::function_requires<  | ||||
|      boost::RandomAccessIteratorPoliciesConcept< | ||||
|        boost::default_iterator_policies, int*, | ||||
|        boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t, | ||||
|                       int*, int&> | ||||
|       > >(); | ||||
|  | ||||
|   // Test the iterator_adaptor | ||||
|   { | ||||
|     my_iterator i(array); | ||||
|     boost::random_access_iterator_test(i, N, array); | ||||
|      | ||||
|     const_my_iterator j(array); | ||||
|     boost::random_access_iterator_test(j, N, array); | ||||
|     boost::const_nonconst_iterator_test(i, ++j); | ||||
|   } | ||||
|  | ||||
|   // Test transform_iterator | ||||
|   { | ||||
|     int x[N], y[N]; | ||||
|     for (int k = 0; k < N; ++k) | ||||
|       x[k] = k; | ||||
|     std::copy(x, x + N, y); | ||||
|  | ||||
|     for (int k2 = 0; k2 < N; ++k2) | ||||
|       x[k2] = x[k2] * 2; | ||||
|  | ||||
|     boost::transform_iterator_generator<mult_functor, int*>::type | ||||
|       i(y, mult_functor(2)); | ||||
|     boost::input_iterator_test(i, x[0], x[1]); | ||||
|     boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_functor(2)), x[0], x[1]); | ||||
|   } | ||||
|    | ||||
|   // Test indirect_iterator_generator | ||||
|   { | ||||
|     dummyT* ptr[N]; | ||||
|     for (int k = 0; k < N; ++k) | ||||
|       ptr[k] = array + k; | ||||
|  | ||||
|     typedef boost::indirect_iterator_generator<dummyT** | ||||
| #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|         , dummyT | ||||
| #endif | ||||
|       >::type indirect_iterator; | ||||
|  | ||||
|     typedef boost::indirect_iterator_generator<dummyT**, const dummyT>::type const_indirect_iterator; | ||||
|  | ||||
|     indirect_iterator i(ptr); | ||||
|     boost::random_access_iterator_test(i, N, array); | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|     boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array); | ||||
| #endif | ||||
|      | ||||
|     // check operator-> | ||||
|     assert((*i).m_x == i->foo()); | ||||
|  | ||||
|     const_indirect_iterator j(ptr); | ||||
|     boost::random_access_iterator_test(j, N, array); | ||||
|  | ||||
|     dummyT*const* const_ptr = ptr; | ||||
|      | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|     boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array); | ||||
| #endif | ||||
|     boost::const_nonconst_iterator_test(i, ++j); | ||||
|  | ||||
|     more_indirect_iterator_tests(); | ||||
|   } | ||||
|  | ||||
|   // Test projection_iterator_pair_generator | ||||
|   {     | ||||
|     typedef std::pair<dummyT,dummyT> Pair; | ||||
|     Pair pair_array[N]; | ||||
|     for (int k = 0; k < N; ++k) | ||||
|       pair_array[k].first = array[k]; | ||||
|  | ||||
|     typedef boost::projection_iterator_pair_generator<select1st_<Pair>, | ||||
|       Pair*, const Pair* | ||||
|       > Projection; | ||||
|      | ||||
|     Projection::iterator i(pair_array); | ||||
|     boost::random_access_iterator_test(i, N, array); | ||||
|  | ||||
|     boost::random_access_iterator_test(boost::make_projection_iterator(pair_array, select1st_<Pair>()), N, array);     | ||||
|     boost::random_access_iterator_test(boost::make_projection_iterator< select1st_<Pair> >(pair_array), N, array);     | ||||
|  | ||||
|     Projection::const_iterator j(pair_array); | ||||
|     boost::random_access_iterator_test(j, N, array); | ||||
|  | ||||
|     boost::random_access_iterator_test(boost::make_const_projection_iterator(pair_array, select1st_<Pair>()), N, array); | ||||
|     boost::random_access_iterator_test(boost::make_const_projection_iterator<select1st_<Pair> >(pair_array), N, array); | ||||
|  | ||||
|     boost::const_nonconst_iterator_test(i, ++j); | ||||
|   } | ||||
|  | ||||
|   // Test reverse_iterator_generator | ||||
|   { | ||||
|     dummyT reversed[N]; | ||||
|     std::copy(array, array + N, reversed); | ||||
|     std::reverse(reversed, reversed + N); | ||||
|      | ||||
|     typedef boost::reverse_iterator_generator<dummyT* | ||||
| #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|         , dummyT | ||||
| #endif | ||||
|       >::type reverse_iterator; | ||||
|      | ||||
|     reverse_iterator i(reversed + N); | ||||
|     boost::random_access_iterator_test(i, N, array); | ||||
|  | ||||
| #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 }; | ||||
|     boost::integer_range<int> r(0, 5); | ||||
|     boost::random_access_iterator_test(r.begin(), r.size(), int_array); | ||||
|   } | ||||
|  | ||||
|   // Test filter iterator | ||||
|   { | ||||
|     // Using typedefs for filter_gen::type and filter_gen::policies_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; | ||||
|      | ||||
|     filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N)); | ||||
|     boost::forward_iterator_test(i, dummyT(1), dummyT(4)); | ||||
|  | ||||
|     enum { is_forward = boost::is_same< | ||||
|            filter_iter::iterator_category, | ||||
|            std::forward_iterator_tag>::value }; | ||||
|     BOOST_STATIC_ASSERT(is_forward); | ||||
|  | ||||
|     // 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; | ||||
|     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; | ||||
|     adaptor_type i(forward_iter); | ||||
|     if (0) // 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); | ||||
|     if (0) // don't do this, just make sure it compiles | ||||
|       assert((*i).m_x == i->foo());       | ||||
|   } | ||||
|  | ||||
|   std::cout << "test successful " << std::endl; | ||||
|   return 0; | ||||
| } | ||||
| @@ -1,789 +0,0 @@ | ||||
| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | ||||
|  | ||||
| <html> | ||||
| <head> | ||||
|     <meta name="generator" content="HTML Tidy, see www.w3.org"> | ||||
|     <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | ||||
|     <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> | ||||
|     <meta name="ProgId" content="FrontPage.Editor.Document"> | ||||
|  | ||||
|     <title>Boost Iterator Adaptor Library</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000"> | ||||
|  | ||||
|     <img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align= | ||||
|     "center" width="277" height="86">  | ||||
|  | ||||
|     <h1>Boost Iterator Adaptor Library</h1> | ||||
|  | ||||
|     <h2>Introduction</h2> | ||||
|  | ||||
|     <p>The Iterator Adaptor library allows you transform an arbitrary ``base'' | ||||
|     type into a standard-conforming iterator with the behaviors you choose. | ||||
|     Doing so is especially easy if the ``base'' type is itself an iterator. The | ||||
|     library also supplies several example <a href= | ||||
|     "../../more/generic_programming.html#adaptors">adaptors</a> which apply | ||||
|     specific useful behaviors to arbitrary base iterators. | ||||
|  | ||||
|     <h2>Table of Contents</h2> | ||||
|  | ||||
|     <ul> | ||||
|       <li> | ||||
|         Header <tt><a href= | ||||
|         "../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a></tt> | ||||
|          | ||||
|  | ||||
|         <ul> | ||||
|           <li> | ||||
|             Generalized Iterator Adaptor  | ||||
|  | ||||
|             <ul> | ||||
|               <li>Class template <tt><a href= | ||||
|               "#iterator_adaptor">iterator_adaptor</a></tt> | ||||
|  | ||||
|               <li><a href="#template_parameters">Template Parameters</a> | ||||
|  | ||||
|               <li><a href="#policies">The Policies Class</a> | ||||
|  | ||||
|               <li><a href="#additional_members">Additional Class Members</a> | ||||
|  | ||||
|               <li><a href="#example">Example</a> | ||||
|  | ||||
|               <li>(<tt>const</tt>/non-<tt>const</tt>) <a href= | ||||
|               "#iterator_interactions">Iterator Interactions</a> | ||||
|  | ||||
|               <li><a href="#challenge">Challenge</a> | ||||
|  | ||||
|               <li><a href="#concept_model">Concept Model</a> | ||||
|  | ||||
|               <li><a href="#declaration_synopsis">Declaration Synopsis</a> | ||||
|  | ||||
|               <li><a href="#notes">Notes</a> | ||||
|             </ul> | ||||
|  | ||||
|           <li> | ||||
|             Specialized Iterator Adaptors  | ||||
|  | ||||
|             <ul> | ||||
|               <li><a href="indirect_iterator.htm">Indirect Iterator Adaptor</a> | ||||
|  | ||||
|               <li><a href="reverse_iterator.htm">Reverse Iterator Adaptor</a> | ||||
|  | ||||
|               <li><a href="transform_iterator.htm">Transform Iterator | ||||
|               Adaptor</a> | ||||
|  | ||||
|               <li><a href="projection_iterator.htm">Projection Iterator | ||||
|               Adaptor</a> | ||||
|  | ||||
|               <li><a href="filter_iterator.htm">Filter Iterator Adaptor</a> | ||||
|             </ul> | ||||
|         </ul> | ||||
|  | ||||
|       <li>Header <tt><a href= | ||||
|       "../../boost/counting_iterator.hpp">boost/counting_iterator.hpp</a></tt><br> | ||||
|  | ||||
|        <a href="counting_iterator.htm">Counting Iterator Adaptor</a> | ||||
|  | ||||
|       <li>Header <tt><a href= | ||||
|       "../../boost/function_output_iterator.hpp">boost/function_output_iterator.hpp</a></tt><br> | ||||
|  | ||||
|        <a href="function_output_iterator.htm">Function Output Iterator Adaptor</a> | ||||
|     </ul> | ||||
|  | ||||
|     <p><b><a href="http://www.boost.org/people/dave_abrahams.htm">Dave | ||||
|     Abrahams</a></b> started the library, applying <a href= | ||||
|     "../../more/generic_programming.html#policy">policy class</a> technique and | ||||
|     handling const/non-const iterator interactions. He also contributed the | ||||
|     <tt><a href="indirect_iterator.htm">indirect_</a></tt> and <tt><a href= | ||||
|     "reverse_iterator.htm">reverse_</a></tt> iterator generators, and expanded | ||||
|     <tt><a href="counting_iterator.htm">counting_iterator_generator</a></tt> to | ||||
|     cover all incrementable types. He edited most of the documentation, | ||||
|     sometimes heavily.<br> | ||||
|      <b><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy | ||||
|     Siek</a></b> contributed the <a href="transform_iterator.htm">transform | ||||
|     iterator</a> adaptor, the integer-only version of <tt><a href= | ||||
|     "counting_iterator.htm">counting_iterator_generator</a></tt>,  | ||||
|     the <a href="function_output_iterator.htm">function output iterator</a>  | ||||
|     adaptor, and most of the documentation.<br> | ||||
|      <b><a href="http://www.boost.org/people/john_potter.htm">John | ||||
|     Potter</a></b> contributed the <tt><a href= | ||||
|     "projection_iterator.htm">projection_</a></tt> and <tt><a href= | ||||
|     "filter_iterator.htm">filter_</a></tt> iterator generators and made some | ||||
|     simplifications to the main <tt><a href= | ||||
|     "#iterator_adaptor">iterator_adaptor</a></tt> template.<br> | ||||
|  | ||||
|  | ||||
|     <h2><a name="iterator_adaptor">Class template</a> | ||||
|     <tt>iterator_adaptor</tt></h2> | ||||
|     Implementing standard conforming iterators is a non-trivial task. There are | ||||
|     some fine points such as the interactions between an iterator and its | ||||
|     corresponding const_iterator, and there are myriad operators that should be | ||||
|     implemented but are easily forgotten or mishandled, such as | ||||
|     <tt>operator->()</tt>. Using <tt>iterator_adaptor</tt>, you can easily | ||||
|     implement an iterator class, and even more easily extend and <a href= | ||||
|     "../../more/generic_programming.html#adaptors">adapt</a> existing iterator | ||||
|     types. Moreover, it is easy to make a pair of interoperable <tt>const</tt> | ||||
|     and <tt>non-const</tt> iterators.  | ||||
|  | ||||
|     <p><tt>iterator_adaptor</tt> is declared like this: | ||||
| <pre> | ||||
| template <class Base, class Policies,  | ||||
|     class Value = typename std::iterator_traits<Base>::value_type, | ||||
|     class Reference = <i>...(see below)</i>, | ||||
|     class Pointer = <i>...(see below)</i>, | ||||
|     class Category = typename std::iterator_traits<Base>::iterator_category, | ||||
|     class Distance = typename std::iterator_traits<Base>::difference_type> | ||||
| struct iterator_adaptor; | ||||
| </pre> | ||||
|  | ||||
|     <h3><a name="template_parameters">Template Parameters</a></h3> | ||||
|  | ||||
|     <p>Although <tt>iterator_adaptor</tt> takes seven template parameters, | ||||
|     defaults have been carefully chosen to minimize the number of parameters | ||||
|     you must supply in most cases, especially if <tt>BaseType</tt> is an | ||||
|     iterator. | ||||
|  | ||||
|     <table border="1" summary="iterator_adaptor template parameters"> | ||||
|       <tr> | ||||
|         <th>Parameter | ||||
|  | ||||
|         <th>Description | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>BaseType</tt>  | ||||
|  | ||||
|         <td>The type being wrapped. | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>Policies</tt>  | ||||
|  | ||||
|         <td>A <a href="../../more/generic_programming.html#policy">policy | ||||
|         class</a> that supplies core functionality to the resulting iterator. A | ||||
|         detailed description can be found <a href="#policies">below</a>. | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>Value</tt>  | ||||
|  | ||||
|         <td>The <tt>value_type</tt> of the resulting iterator, unless const. If | ||||
|         Value is <tt>const X</tt> the | ||||
|         <tt>value_type</tt> will be (<i>non-</i><tt>const</tt>) <tt>X</tt><a href= | ||||
|         "#1">[1]</a>.<br> | ||||
|          <b>Default:</b> | ||||
|         <tt>std::iterator_traits<BaseType>::value_type</tt> <a href= | ||||
|         "#2">[2]</a> | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>Reference</tt>  | ||||
|  | ||||
|         <td>The <tt>reference</tt> type of the resulting iterator, and in | ||||
|         particular, the result type of <tt>operator*()</tt>.<br> | ||||
|          <b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&</tt> is | ||||
|         used. Otherwise | ||||
|         <tt>std::iterator_traits<BaseType>::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<BaseType>::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<BaseType>::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<BaseType>::difference_type</tt>  | ||||
|     </table> | ||||
|  | ||||
|     <h3><a name="policies">The Policies Class</a></h3> | ||||
|  | ||||
|     <p>The main task in using <tt>iterator_adaptor</tt> is creating an | ||||
|     appropriate <tt>Policies</tt> class. The <tt>Policies</tt> class will | ||||
|     become the functional heart of the iterator adaptor, supplying the core | ||||
|     iterator operations that will determine how your new adaptor class will | ||||
|     behave. The <tt>iterator_adaptor</tt> template defines all of the operators | ||||
|     required of a <a href= | ||||
|     "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access | ||||
|     Iterator</a>. Your <tt>Policies</tt> class must implement three, four, or | ||||
|     seven of the core iterator operations below depending on the iterator | ||||
|     categories you want it to support.<br> | ||||
|     <br> | ||||
|      | ||||
|  | ||||
|     <table border="1" summary="iterator_adaptor Policies operations"> | ||||
|       <caption> | ||||
|         <b>Core Iterator Operations</b><br> | ||||
|         <tt>T</tt>: iterator type; <tt>p</tt>: object of type T; <tt>n</tt>: <tt>T::size_type</tt>; <tt>x</tt>: <tt>T::difference_type</tt>; <tt>p1</tt>, <tt>p2</tt>: iterators | ||||
|       </caption> | ||||
|  | ||||
|       <tr> | ||||
|         <th>Operation | ||||
|  | ||||
|         <th>Effects | ||||
|  | ||||
|         <th>Implements Operations | ||||
|  | ||||
|         <th>Required for Iterator Categories | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>dereference</tt>  | ||||
|  | ||||
|         <td>returns an element of the iterator's <tt>reference</tt> type | ||||
|          | ||||
|         <td><tt>*p</tt>, <tt>p[n]</tt> | ||||
|  | ||||
|         <td rowspan="3"><a href= | ||||
|         "http://www.sgi.com/tech/stl/InputIterator.html">Input</a>/ <a href= | ||||
|         "http://www.sgi.com/tech/stl/OutputIterator.html">Output</a>/ <a href= | ||||
|         "http://www.sgi.com/tech/stl/ForwardIterator.html">Forward</a>/ <a | ||||
|         href= | ||||
|         "http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/ | ||||
|         <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random | ||||
|         Access</a>  | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>equal</tt>  | ||||
|  | ||||
|         <td>tests the iterator for equality | ||||
|  | ||||
|         <td><tt>p1 == p2</tt>, <tt>p1 != p2</tt> | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>increment</tt>  | ||||
|  | ||||
|         <td>increments the iterator | ||||
|  | ||||
|         <td><tt>++p</tt>, <tt>p++</tt> | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>decrement</tt>  | ||||
|  | ||||
|         <td>decrements the iterator | ||||
|  | ||||
|         <td><tt>--p</tt>, <tt>p--</tt> | ||||
|  | ||||
|         <td><a href= | ||||
|         "http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/ | ||||
|         <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random | ||||
|         Access</a>  | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>less</tt>  | ||||
|  | ||||
|         <td>imposes a <a href= | ||||
|         "http://www.sgi.com/tech/stl/StrictWeakOrdering.html">Strict Weak | ||||
|         Ordering</a> relation on iterators | ||||
|  | ||||
|         <td>  | ||||
|            <tt>p1 < p2</tt>, | ||||
|            <tt>p1 <= p2</tt>, | ||||
|            <tt>p1 > p2</tt>, | ||||
|            <tt>p1 >= p2</tt> | ||||
|  | ||||
|         <td rowspan="3"><a href= | ||||
|         "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random | ||||
|         Access</a>  | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>distance</tt>  | ||||
|  | ||||
|         <td>measures the distance between iterators | ||||
|  | ||||
|         <td><tt>p1 - p2</tt> | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>advance</tt>  | ||||
|  | ||||
|         <td>adds an integer offset to iterators | ||||
|  | ||||
|         <td> | ||||
| <tt>p + x</tt>, | ||||
| <tt>x + p</tt>, | ||||
| <tt>p += x</tt>, | ||||
| <tt>p - x</tt>, | ||||
| <tt>p -= x</tt> | ||||
|          | ||||
|     </table> | ||||
|  | ||||
|     <p>The library also supplies a "trivial" policy class, | ||||
|     <tt>default_iterator_policies</tt>, which implements all seven of the core | ||||
|     operations in the usual way. If you wish to create an iterator adaptor that | ||||
|     only changes a few of the base type's behaviors, then you can derive your | ||||
|     new policy class from <tt>default_iterator_policies</tt> to avoid retyping | ||||
|     the usual behaviors. You should also look at | ||||
|     <tt>default_iterator_policies</tt> as the ``boilerplate'' for your own | ||||
|     policy classes, defining functions with the same interface. This is the | ||||
|     definition of <tt>default_iterator_policies</tt>:<br> | ||||
|     <br> | ||||
|  | ||||
|     <blockquote> | ||||
| <pre> | ||||
| struct <a name="default_iterator_policies">default_iterator_policies</a> | ||||
| { | ||||
|   template <class Reference, class BaseType> | ||||
|   Reference dereference(type<Reference>, const BaseType& x) const | ||||
|     { return *x; } | ||||
|  | ||||
|   template <class BaseType> | ||||
|   static void increment(BaseType& x) | ||||
|     { ++x; } | ||||
|  | ||||
|   template <class BaseType1, class BaseType2> | ||||
|   bool equal(BaseType1& x, BaseType2& y) const | ||||
|     { return x == y; } | ||||
|  | ||||
|   template <class BaseType> | ||||
|   static void decrement(BaseType& x) | ||||
|     { --x; } | ||||
|  | ||||
|   template <class BaseType, class DifferenceType> | ||||
|   static void advance(BaseType& x, DifferenceType n) | ||||
|     { x += n; } | ||||
|  | ||||
|   template <class Difference, class BaseType1, class BaseType2> | ||||
|   Difference distance(type<Difference>, BaseType1& x, BaseType2& y) const | ||||
|     { return y - x; } | ||||
|  | ||||
|   template <class BaseType1, class BaseType2> | ||||
|   bool less(BaseType1& x, BaseType2& y) const | ||||
|     { return x < y; } | ||||
| }; | ||||
| </pre> | ||||
|     </blockquote> | ||||
|  | ||||
|     <p>Template member functions are used throughout | ||||
|     <tt>default_iterator_policies</tt> so that it can be employed with a wide | ||||
|     range of iterators. If we had used concrete types above, we'd have tied the | ||||
|     usefulness of <tt>default_iterator_policies</tt> to a particular range of | ||||
|     adapted iterators. If you follow the same pattern with your | ||||
|     <tt>Policies</tt> classes, you may achieve the same sort of reusability. | ||||
|  | ||||
|     <h3><a name="additional_members">Additional Members</a></h3> | ||||
|     In addition to all of the member functions required of a <a href= | ||||
|     "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access | ||||
|     Iterator</a>, the <tt>iterator_adaptor</tt> class template defines the | ||||
|     following members. <br> | ||||
|      <br> | ||||
|       | ||||
|  | ||||
|     <table border="1" summary="additional iterator_adaptor members"> | ||||
|       <tr> | ||||
|         <td><tt>explicit iterator_adaptor(const Base&, const Policies& = | ||||
|         Policies())</tt> | ||||
|          <br><br> | ||||
|          Construct an adapted iterator from a base object and a policies | ||||
|          object. As this constructor is <tt>explicit</tt>, it does not | ||||
|          provide for implicit conversions from the <tt>Base</tt> type to | ||||
|          the iterator adaptor. | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>template <class B, class V, class R, class P><br> | ||||
|          iterator_adaptor(const | ||||
|         iterator_adaptor<B,Policies,V,R,P,Category,Distance>&)</tt> | ||||
|         <br><br> | ||||
|          This constructor allows for conversion from non-<tt>const</tt> to | ||||
|         constant adapted iterators. See <a href= | ||||
|         "#iterator_interactions">below</a> for more details.<br> | ||||
|          Requires: <tt>B</tt> is convertible to <tt>Base</tt>. | ||||
|  | ||||
|       <tr> | ||||
|         <td><tt>base_type base() const;</tt> | ||||
|          <br><br> | ||||
|          Return a copy of the base object. | ||||
|     </table> | ||||
|  | ||||
|     <h3><a name="example">Example</a></h3> | ||||
|  | ||||
|     <p>It is often useful to automatically apply some function to the value | ||||
|     returned by dereferencing an iterator. The <a href= | ||||
|     "./transform_iterator.htm">transform iterator</a> makes it easy to create | ||||
|     an iterator adaptor which does just that. Here we will show how easy it is | ||||
|     to implement the transform iterator using the <tt>iterator_adaptor</tt> | ||||
|     template. | ||||
|  | ||||
|     <p>We want to be able to adapt a range of iterators and functions, so the | ||||
|     policies class will have a template parameter for the function type and it | ||||
|     will have a data member of that type. We know that the function takes one | ||||
|     argument and that we'll need to be able to deduce the <tt>result_type</tt> | ||||
|     of the function so we can use it for the adapted iterator's | ||||
|     <tt>value_type</tt>. <a href= | ||||
|     "http://www.sgi.com/Technology/STL/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a> | ||||
|     is the <a href="../../more/generic_programming.html#concept">Concept</a> | ||||
|     that fulfills those requirements. | ||||
|  | ||||
|     <p>To implement a transform iterator we will only change one of the base | ||||
|     iterator's behaviors, so the <tt>transform_iterator_policies</tt> class can | ||||
|     inherit the rest from <tt>default_iterator_policies</tt>. We will define | ||||
|     the <tt>dereference()</tt> member function, which is used to implement | ||||
|     <tt>operator*()</tt> of the adapted iterator. The implementation will | ||||
|     dereference the base iterator and apply the function object. The | ||||
|     <tt>type<Reference></tt> parameter is used to convey the appropriate | ||||
|     return type. The complete code for <tt>transform_iterator_policies</tt> | ||||
|     is:<br> | ||||
|     <br> | ||||
|  | ||||
|  | ||||
|     <blockquote> | ||||
| <pre> | ||||
|   template <class AdaptableUnaryFunction> | ||||
|   struct transform_iterator_policies : public default_iterator_policies | ||||
|   { | ||||
|     transform_iterator_policies() { } | ||||
|  | ||||
|     transform_iterator_policies(const AdaptableUnaryFunction& f) | ||||
|       : m_f(f) { } | ||||
|  | ||||
|     template <class Reference, class BaseIterator> | ||||
|     Reference dereference(type<Reference>, const BaseIterator& i) const | ||||
|       { return m_f(*i); } | ||||
|  | ||||
|     AdaptableUnaryFunction m_f; | ||||
|   }; | ||||
| </pre> | ||||
|     </blockquote> | ||||
|  | ||||
|     <p>The next step is to use the <tt>iterator_adaptor</tt> template to | ||||
|     construct the transform iterator type. The nicest way to package the | ||||
|     construction of the transform iterator is to create a <a href= | ||||
|     "../../more/generic_programming.html#type_generator">type generator</a>. | ||||
|     The first template parameter to the generator will be the type of the | ||||
|     function object and the second will be the base iterator type. We use | ||||
|     <tt>iterator_adaptor</tt> to define the transform iterator type as a nested | ||||
|     <tt>typedef</tt> inside the <tt>transform_iterator_generator</tt> class. | ||||
|     Because the function may return by-value, we must limit the | ||||
|     <tt>iterator_category</tt> to <a href= | ||||
|     "http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>, and | ||||
|     the iterator's <tt>reference</tt> type cannot be a true reference (the | ||||
|     standard allows this for input iterators), so in this case we can use few | ||||
|     of <tt>iterator_adaptor</tt>'s default template arguments.<br> | ||||
|     <br> | ||||
|  | ||||
|  | ||||
|     <blockquote> | ||||
| <pre> | ||||
| template <class AdaptableUnaryFunction, class Iterator> | ||||
| struct transform_iterator_generator | ||||
| { | ||||
|     typedef typename AdaptableUnaryFunction::result_type value_type; | ||||
| public: | ||||
|     typedef iterator_adaptor<Iterator,  | ||||
|         transform_iterator_policies<AdaptableUnaryFunction>, | ||||
|         value_type, value_type, value_type*, std::input_iterator_tag> | ||||
|       type; | ||||
| }; | ||||
| </pre> | ||||
|     </blockquote> | ||||
|  | ||||
|     <p>As a finishing touch, we will create an <a href= | ||||
|     "../../more/generic_programming.html#object_generator">object generator</a> | ||||
|     for the transform iterator. This is a function that makes it more | ||||
|     convenient to create a transform iterator.<br> | ||||
|     <br> | ||||
|  | ||||
|  | ||||
|     <blockquote> | ||||
| <pre> | ||||
| template <class AdaptableUnaryFunction, class Iterator> | ||||
| typename transform_iterator_generator<AdaptableUnaryFunction,Iterator>::type | ||||
| make_transform_iterator(Iterator base, | ||||
|                         const AdaptableUnaryFunction& f = AdaptableUnaryFunction()) | ||||
| { | ||||
|     typedef typename transform_iterator_generator<AdaptableUnaryFunction, | ||||
|       Iterator>::type result_t; | ||||
|     return result_t(base, f); | ||||
| } | ||||
| </pre> | ||||
|     </blockquote> | ||||
|  | ||||
|     <p>Here is an example that shows how to use a transform iterator to iterate | ||||
|     through a range of numbers, multiplying each of them by 2 and printing the | ||||
|     result to standard output.<br> | ||||
|     <br> | ||||
|  | ||||
|  | ||||
|     <blockquote> | ||||
| <pre> | ||||
| #include <functional> | ||||
| #include <algorithm> | ||||
| #include <iostream> | ||||
| #include <boost/iterator_adaptors.hpp> | ||||
|  | ||||
| int main(int, char*[]) | ||||
| { | ||||
|   int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; | ||||
|   const int N = sizeof(x)/sizeof(int); | ||||
|   std::cout << "multiplying the array by 2:" << std::endl; | ||||
|   std::copy(boost::make_transform_iterator(x, std::bind1st(std::multiplies<int>(), 2)), | ||||
|       boost::make_transform_iterator(x + N, std::bind1st(std::multiplies<int>(), 2)), | ||||
|       std::ostream_iterator<int>(std::cout, " ")); | ||||
|   std::cout << std::endl; | ||||
|   return 0; | ||||
| } | ||||
| </pre> | ||||
|       This output is:  | ||||
| <pre> | ||||
| 2 4 6 8 10 12 14 16 | ||||
| </pre> | ||||
|     </blockquote> | ||||
|  | ||||
|     <h3><a name="iterator_interactions">Iterator Interactions</a></h3> | ||||
|  | ||||
|     <p>C++ allows <tt>const</tt> and non-<tt>const</tt> pointers to interact in | ||||
|     the following intuitive ways: | ||||
|  | ||||
|     <ul> | ||||
|       <li>a non-<tt>const</tt> pointer to <tt>T</tt> can be implicitly | ||||
|       converted to a <tt>const</tt> pointer to <tt>T</tt>. | ||||
|  | ||||
|       <li><tt>const</tt> and non-<tt>const</tt> pointers to <tt>T</tt> can be | ||||
|       freely mixed in comparison expressions. | ||||
|  | ||||
|       <li><tt>const</tt> and non-<tt>const</tt> pointers to <tt>T</tt> can be | ||||
|       freely subtracted, in any order. | ||||
|     </ul> | ||||
|  | ||||
|     Getting user-defined iterators to work together that way is nontrivial (see | ||||
|     <a href="reverse_iterator.htm#interactions">here</a> for an example of where | ||||
|     the C++ standard got it wrong), but <tt>iterator_adaptor</tt> can make it | ||||
|     easy. The rules are as follows: | ||||
|  | ||||
|     <ul> | ||||
|       <li><a name="interoperable">Adapted iterators that share the same <tt>Policies</tt>, | ||||
|       <tt>Category</tt>, and <tt>Distance</tt> parameters are called | ||||
|       <i>interoperable</i>.</a> | ||||
|  | ||||
|       <li>An adapted iterator can be implicitly converted to any other adapted | ||||
|       iterator with which it is interoperable, so long as the <tt>Base</tt> | ||||
|       type of the source iterator can be converted to the <tt>Base</tt> type of | ||||
|       the target iterator. | ||||
|  | ||||
|       <li>Interoperable iterators can be freely mixed in comparison expressions | ||||
|       so long as the <tt>Policies</tt> class has <tt>equal</tt> (and, for | ||||
|       random access iterators, <tt>less</tt>) members that can accept both | ||||
|       <tt>Base</tt> types in either order. | ||||
|  | ||||
|       <li>Interoperable iterators can be freely mixed in subtraction | ||||
|       expressions so long as the <tt>Policies</tt> class has a | ||||
|       <tt>distance</tt> member that can accept both <tt>Base</tt> types in | ||||
|       either order. | ||||
|     </ul> | ||||
|  | ||||
|     <h4>Example</h4> | ||||
|      | ||||
|     <p>The <a href="projection_iterator.htm">Projection Iterator</a> adaptor is similar to the <a | ||||
| href="./transform_iterator.htm">transform iterator adaptor</a> in that | ||||
| its <tt>operator*()</tt> applies some function to the result of | ||||
| dereferencing the base iterator and then returns the result. The | ||||
| difference is that the function must return a reference to some | ||||
| existing object (for example, a data member within the | ||||
| <tt>value_type</tt> of the base iterator).  | ||||
|  | ||||
|     <p> | ||||
| The <a | ||||
|     href="projection_iterator.htm#projection_iterator_pair_generator">projection_iterator_pair_generator</a> template | ||||
|     is a special two-<a href="../../more/generic_programming.html#type_generator">type generator</a> for mutable and constant versions of a | ||||
|     projection iterator. It is defined as follows: | ||||
| <blockquote> | ||||
| <pre> | ||||
| template <class AdaptableUnaryFunction, class Iterator, class ConstIterator> | ||||
| struct projection_iterator_pair_generator { | ||||
|     typedef typename AdaptableUnaryFunction::result_type value_type; | ||||
|     typedef projection_iterator_policies<AdaptableUnaryFunction> policies; | ||||
| public: | ||||
|     typedef iterator_adaptor<Iterator,policies,value_type> iterator; | ||||
|     typedef iterator_adaptor<ConstIterator,policies,value_type, | ||||
|         const value_type&,const value_type*> const_iterator; | ||||
| }; | ||||
| </pre> | ||||
| </blockquote> | ||||
|  | ||||
| <p>It is assumed that the <tt>Iterator</tt> and <tt>ConstIterator</tt> arguments are corresponding mutable | ||||
| and constant iterators. <ul> | ||||
| <li> | ||||
| Clearly, then, the | ||||
| <tt>projection_iterator_pair_generator</tt>'s <tt>iterator</tt> and | ||||
| <tt>const_iterator</tt> are <a href="#interoperable">interoperable</a>, since | ||||
| they share the same <tt>Policies</tt> and since <tt>Category</tt> and | ||||
| <tt>Distance</tt> as supplied by <tt>std::iterator_traits</tt> through the | ||||
| <a href="#template_parameters">default template parameters</a> to | ||||
| <tt>iterator_adaptor</tt> should be the same. | ||||
|  | ||||
| <li>Since <tt>Iterator</tt> can presumably be converted to | ||||
| <tt>ConstIterator</tt>, the projection <tt>iterator</tt> will be convertible to | ||||
| the projection <tt>const_iterator</tt>. | ||||
|  | ||||
| <li> Since <tt>projection_iterator_policies</tt> implements only the | ||||
| <tt>dereference</tt> operation, and inherits all other behaviors from <tt><a | ||||
| href="#default_iterator_policies">default_iterator_policies</a></tt>, which has | ||||
| fully-templatized <tt>equal</tt>, <tt>less</tt>, and <tt>distance</tt> | ||||
| operations, the <tt>iterator</tt> and <tt>const_iterator</tt> can be freely | ||||
| mixed in comparison and subtraction expressions. | ||||
|  | ||||
| </ul> | ||||
|  | ||||
|     <h3><a name="challenge">Challenge</a></h3> | ||||
|  | ||||
|     <p>There is an unlimited number of ways the <tt>iterator_adaptors</tt> | ||||
|     class can be used to create iterators. One interesting exercise would be to | ||||
|     re-implement the iterators of <tt>std::list</tt> and <tt>std::slist</tt> | ||||
|     using <tt>iterator_adaptors</tt>, where the adapted <tt>Iterator</tt> types | ||||
|     would be node pointers. | ||||
|  | ||||
|     <h3><a name="concept_model">Concept Model</a></h3> | ||||
|     Depending on the <tt>Base</tt> and <tt>Policies</tt> template parameters, | ||||
|     an <tt>iterator_adaptor</tt> can be a <a href= | ||||
|     "http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>, <a | ||||
|     href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward | ||||
|     Iterator</a>, <a href= | ||||
|     "http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional | ||||
|     Iterator</a>, or <a href= | ||||
|     "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access | ||||
|     Iterator</a>.  | ||||
|  | ||||
|     <h3><a name="declaration_synopsis">Declaration Synopsis</a></h3> | ||||
| <pre> | ||||
| template <class Base, class Policies,  | ||||
|     class Value = typename std::iterator_traits<Base>::value_type, | ||||
|     class Reference = <i>...(see below)</i>, | ||||
|     class Pointer = <i>...(see below)</i>, | ||||
|     class Category = typename std::iterator_traits<Base>::iterator_category, | ||||
|     class Distance = typename std::iterator_traits<Base>::difference_type | ||||
|          > | ||||
| struct iterator_adaptor | ||||
| { | ||||
|     typedef Distance difference_type; | ||||
|     typedef typename boost::remove_const<Value>::type value_type; | ||||
|     typedef Pointer pointer; | ||||
|     typedef Reference reference; | ||||
|     typedef Category iterator_category; | ||||
|     typedef Base base_type; | ||||
|     typedef Policies policies_type; | ||||
|  | ||||
|     iterator_adaptor(); | ||||
|     explicit iterator_adaptor(const Base&, const Policies& = Policies()); | ||||
|  | ||||
|     base_type base() const; | ||||
|  | ||||
|     template <class B, class V, class R, class P> | ||||
|     iterator_adaptor( | ||||
|         const iterator_adaptor<B,Policies,V,R,P,Category,Distance>&); | ||||
|  | ||||
|     reference operator*() const; | ||||
|     <i>operator_arrow_result_type</i> operator->() const; <a href= | ||||
| "#3">[3]</a> | ||||
|     <i>value_type</i> operator[](difference_type n) const; <a href="#3">[4]</a> | ||||
|  | ||||
|     iterator_adaptor& operator++(); | ||||
|     iterator_adaptor& operator++(int); | ||||
|     iterator_adaptor& operator--(); | ||||
|     iterator_adaptor& operator--(int); | ||||
|  | ||||
|     iterator_adaptor& operator+=(difference_type n); | ||||
|     iterator_adaptor& operator-=(difference_type n); | ||||
|  | ||||
|     iterator_adaptor& operator-(Distance x) const; | ||||
| }; | ||||
|  | ||||
| template <class B, class P, class V, class R, class Ptr,  | ||||
|     class C, class D1, class D2> | ||||
| iterator_adaptor<B,P,V,R,Ptr,C,D1> | ||||
| operator+(iterator_adaptor<B,P,V,R,Ptr,C,D1>, D2); | ||||
|  | ||||
| template <class B, class P, class V, class R, class Ptr, | ||||
|     class C, class D1, class D2> | ||||
| iterator_adaptor<B,P,V,R,P,C,D1> | ||||
| operator+(D2, iterator_adaptor<B,P,V,R,Ptr,C,D1> p); | ||||
|  | ||||
| template <class B1, class B2, class P, class V1, class V2, | ||||
|     class R1, class R2, class P1, class P2, class C, class D> | ||||
| Distance operator-(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,  | ||||
|                    const iterator_adaptor<B2,P,V2,R2,P2,C,D>&); | ||||
|  | ||||
| template <class B1, class B2, class P, class V1, class V2, | ||||
|     class R1, class R2, class P1, class P2, class C, class D> | ||||
| bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,  | ||||
|                 const iterator_adaptor<B2,P,V2,R2,P2,C,D>&); | ||||
|  | ||||
| // and similarly for operators !=, <, <=, >=, > | ||||
| </pre> | ||||
|  | ||||
|     <h3><a name="notes">Notes</a></h3> | ||||
|  | ||||
|     <p><a name="1">[1]</a> The standard specifies that the <tt>value_type</tt> | ||||
|     of <tt>const</tt> iterators to <tt>T</tt> (e.g. <tt>const T*</tt>) is | ||||
|     <tt><i>non-</i>const T</tt>, while the <tt>pointer</tt> and | ||||
|     <tt>reference</tt> types for all <a href= | ||||
|     "http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterators</a> are | ||||
|     <tt>const T*</tt> and <tt>const T&</tt>, respectively. Stripping the | ||||
|     <tt>const</tt>-ness of <tt>Value</tt> allows you to easily | ||||
|     make a <tt>const</tt> iterator adaptor by supplying a <tt>const</tt> type | ||||
|     for <tt>Value</tt>, and allowing the defaults for the <tt>Pointer</tt> and | ||||
|     <tt>Reference</tt> parameters to take effect. Although compilers that don't | ||||
|     support partial specialization won't strip <tt>const</tt> for you, having a | ||||
|     <tt>const value_type</tt> is often harmless in practice. | ||||
|  | ||||
|     <p><a name="2">[2]</a> If your compiler does not support partial | ||||
|     specialization and the base iterator is a builtin pointer type, you | ||||
|     will not be able to use the default for <tt>Value</tt> and will have to | ||||
|     specify this type explicitly. | ||||
|  | ||||
|     <p><a name="3">[3]</a> The result type for the <tt>operator->()</tt> | ||||
|     depends on the category and value type of the iterator and is somewhat | ||||
|     complicated to describe. But be assured, it works in a stardard conforming | ||||
|     fashion, providing access to members of the objects pointed to by the | ||||
|     iterator. | ||||
|  | ||||
|     <p><a name="4">[4]</a> The result type of <tt>operator[]()</tt> is | ||||
|     <tt>value_type</tt> instead of <tt>reference</tt> as might be expected. | ||||
|     There are two reasons for this choice. First, the C++ standard only | ||||
|     requires that the return type of an arbitrary <a href= | ||||
|     "http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access | ||||
|     Iterator</a>'s <tt>operator[]</tt>be ``convertible to T'' (Table 76), so | ||||
|     when adapting an arbitrary base iterator we may not have a reference to | ||||
|     return. Second, and more importantly, for certain kinds of iterators, | ||||
|     returning a reference could cause serious memory problems due to the | ||||
|     reference being bound to a temporary object whose lifetime ends inside of | ||||
|     the <tt>operator[]</tt>. | ||||
|     <hr> | ||||
|  | ||||
|     <p>Revised  | ||||
|     <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->27 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14388" --> | ||||
|  | ||||
|  | ||||
|     <p>© Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy, | ||||
|     use, modify, sell and distribute this document is granted provided this | ||||
|     copyright notice appears in all copies. This document is provided "as is" | ||||
|     without express or implied warranty, and with no claim as to its | ||||
|     suitability for any purpose.  | ||||
|  | ||||
| </body> | ||||
|  | ||||
|     <!--  LocalWords:  HTML html charset alt gif abrahams htm const | ||||
|         incrementable david abrahams | ||||
|          --> | ||||
|       | ||||
|     <!--  LocalWords:  jeremy siek mishandled interoperable typename struct Iter iter src | ||||
|          --> | ||||
|       | ||||
|     <!--  LocalWords:  int bool ForwardIterator BidirectionalIterator BaseIterator | ||||
|          --> | ||||
|       | ||||
|     <!--  LocalWords:  RandomAccessIterator DifferenceType AdaptableUnaryFunction | ||||
|          --> | ||||
|       | ||||
|     <!--  LocalWords:  iostream hpp sizeof InputIterator constness ConstIterator | ||||
|          David Abrahams | ||||
|          --> | ||||
| </body> | ||||
| </html> | ||||
|  | ||||
| @@ -1,209 +0,0 @@ | ||||
| //  (C) Copyright David Abrahams 2001. Permission to copy, use, modify, | ||||
| //  sell and distribute this software is granted provided this | ||||
| //  copyright notice appears in all copies. This software is provided | ||||
| //  "as is" without express or implied warranty, and with no claim as | ||||
| //  to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  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) && !defined(__SGI_STL_PORT) | ||||
| 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; | ||||
| } | ||||
| @@ -1,169 +0,0 @@ | ||||
| //  Demonstrate and test boost/operators.hpp on std::iterators  --------------// | ||||
|  | ||||
| //  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, | ||||
| //  sell and distribute this software is granted provided this | ||||
| //  copyright notice appears in all copies. This software is provided | ||||
| //  "as is" without express or implied warranty, and with no claim as | ||||
| //  to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  12 Dec 99 Initial version with iterator operators (Jeremy Siek) | ||||
|  | ||||
| #include <string> | ||||
| #include <iostream> | ||||
| using namespace std; | ||||
|  | ||||
| #include <boost/operators.hpp> | ||||
| using namespace boost; | ||||
|  | ||||
|  | ||||
| template <class T, class R, class P> | ||||
| struct test_iter | ||||
|   : public boost::random_access_iterator_helper< | ||||
|      test_iter<T,R,P>, T, std::ptrdiff_t, P, R> | ||||
| { | ||||
|   typedef test_iter self; | ||||
|   typedef R Reference; | ||||
|   typedef std::ptrdiff_t Distance; | ||||
|  | ||||
| public: | ||||
|   test_iter(T* i) : _i(i) { } | ||||
|   test_iter(const self& x) : _i(x._i) { } | ||||
|   self& operator=(const self& x) { _i = x._i; return *this; } | ||||
|   Reference operator*() const { return *_i; } | ||||
|   self& operator++() { ++_i; return *this; } | ||||
|   self& operator--() { --_i; return *this; } | ||||
|   self& operator+=(Distance n) { _i += n; return *this; } | ||||
|   self& operator-=(Distance n) { _i -= n; return *this; } | ||||
|   bool operator==(const self& x) const { return _i == x._i; } | ||||
|   bool operator<(const self& x) const { return _i < x._i; } | ||||
|   friend Distance operator-(const self& x, const self& y) { | ||||
|     return x._i - y._i;  | ||||
|   } | ||||
| protected: | ||||
|   T* _i; | ||||
| }; | ||||
|  | ||||
|  | ||||
| int | ||||
| main() | ||||
| { | ||||
|   string array[] = { "apple", "orange", "pear", "peach", "grape", "plum"  }; | ||||
|   { | ||||
|     test_iter<string,string&,string*> i = array,  | ||||
|       ie = array + sizeof(array)/sizeof(string); | ||||
|  | ||||
|     // Tests for all of the operators added by random_access_iterator_helper | ||||
|  | ||||
|     // test i++ | ||||
|     while (i != ie) | ||||
|       cout << *i++ << " "; | ||||
|     cout << endl; | ||||
|     i = array; | ||||
|  | ||||
|     // test i-- | ||||
|     while (ie != i) { | ||||
|       ie--; | ||||
|       cout << *ie << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|     ie = array + sizeof(array)/sizeof(string); | ||||
|  | ||||
|     // test i->m | ||||
|     while (i != ie) { | ||||
|       cout << i->size() << " "; | ||||
|       ++i; | ||||
|     } | ||||
|     cout << endl; | ||||
|     i = array; | ||||
|  | ||||
|     // test i + n | ||||
|     while (i < ie) { | ||||
|       cout << *i << " "; | ||||
|       i = i + 2; | ||||
|     } | ||||
|     cout << endl; | ||||
|     i = array; | ||||
|  | ||||
|     // test n + i | ||||
|     while (i < ie) { | ||||
|       cout << *i << " "; | ||||
|       i = ptrdiff_t(2) + i; | ||||
|     } | ||||
|     cout << endl; | ||||
|     i = array; | ||||
|  | ||||
|     // test i - n | ||||
|     while (ie > i) { | ||||
|       ie = ie - 2; | ||||
|       cout << *ie << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|     ie = array + sizeof(array)/sizeof(string); | ||||
|  | ||||
|     // test i[n] | ||||
|     for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j) | ||||
|       cout << i[j] << " "; | ||||
|     cout << endl; | ||||
|   } | ||||
|   { | ||||
|     test_iter<string, const string&, const string*> i = array,  | ||||
|       ie = array + sizeof(array)/sizeof(string); | ||||
|  | ||||
|     // Tests for all of the operators added by random_access_iterator_helper | ||||
|  | ||||
|     // test i++ | ||||
|     while (i != ie) | ||||
|       cout << *i++ << " "; | ||||
|     cout << endl; | ||||
|     i = array; | ||||
|  | ||||
|     // test i-- | ||||
|     while (ie != i) { | ||||
|       ie--; | ||||
|       cout << *ie << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|     ie = array + sizeof(array)/sizeof(string); | ||||
|  | ||||
|     // test i->m | ||||
|     while (i != ie) { | ||||
|       cout << i->size() << " "; | ||||
|       ++i; | ||||
|     } | ||||
|     cout << endl; | ||||
|     i = array; | ||||
|  | ||||
|     // test i + n | ||||
|     while (i < ie) { | ||||
|       cout << *i << " "; | ||||
|       i = i + 2; | ||||
|     } | ||||
|     cout << endl; | ||||
|     i = array; | ||||
|  | ||||
|     // test n + i | ||||
|     while (i < ie) { | ||||
|       cout << *i << " "; | ||||
|       i = ptrdiff_t(2) + i; | ||||
|     } | ||||
|     cout << endl; | ||||
|     i = array; | ||||
|  | ||||
|     // test i - n | ||||
|     while (ie > i) { | ||||
|       ie = ie - 2; | ||||
|       cout << *ie << " "; | ||||
|     } | ||||
|     cout << endl; | ||||
|     ie = array + sizeof(array)/sizeof(string); | ||||
|  | ||||
|     // test i[n] | ||||
|     for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j) | ||||
|       cout << i[j] << " "; | ||||
|     cout << endl; | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
| @@ -1,38 +0,0 @@ | ||||
| //  boost class noncopyable test program  ------------------------------------// | ||||
|  | ||||
| //  (C) Copyright boost.org 1999. Permission to copy, use, modify, sell | ||||
| //  and distribute this software is granted provided this copyright | ||||
| //  notice appears in all copies. This software is provided "as is" without | ||||
| //  express or implied warranty, and with no claim as to its suitability for | ||||
| //  any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //   9 Jun 99  Add unnamed namespace | ||||
| //   2 Jun 99  Initial Version | ||||
|  | ||||
| #include <boost/utility.hpp> | ||||
| #include <iostream> | ||||
|  | ||||
| //  This program demonstrates compiler errors resulting from trying to copy | ||||
| //  construct or copy assign a class object derived from class noncopyable. | ||||
|  | ||||
| namespace | ||||
| { | ||||
|     class DontTreadOnMe : boost::noncopyable | ||||
|     { | ||||
|     public: | ||||
|          DontTreadOnMe() { std::cout << "defanged!" << std::endl; } | ||||
|     };   // DontTreadOnMe | ||||
|  | ||||
| }   // unnamed namespace | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     DontTreadOnMe object1; | ||||
|     DontTreadOnMe object2(object1); | ||||
|     object1 = object2; | ||||
|     return 0; | ||||
| }   // main | ||||
|    | ||||
| @@ -1,393 +0,0 @@ | ||||
| //  (C) Copyright David Abrahams 2001. Permission to copy, use, modify, | ||||
| //  sell and distribute this software is granted provided this | ||||
| //  copyright notice appears in all copies. This software is provided | ||||
| //  "as is" without express or implied warranty, and with no claim as | ||||
| //  to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  11 Feb 2001 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 | ||||
|  | ||||
| // A macro for declaring class compile-time constants. | ||||
| #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | ||||
| # define DECLARE_CLASS_CONST(type, init) static const type init | ||||
| #else | ||||
| # define DECLARE_CLASS_CONST(type, init) enum { init } | ||||
| #endif | ||||
|  | ||||
| // ================================================================================= | ||||
| // template class complement_traits<Number> -- | ||||
| // | ||||
| //    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 | ||||
| { | ||||
|     DECLARE_CLASS_CONST(Number, max = complement<size>::template traits<Number>::max); | ||||
|     DECLARE_CLASS_CONST(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: | ||||
|         DECLARE_CLASS_CONST(Number, max = | ||||
|                             Number(Number(prev::max) << CHAR_BIT) | ||||
|                             + Number(UCHAR_MAX)); | ||||
|          | ||||
|         DECLARE_CLASS_CONST(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 | ||||
|     { | ||||
|         DECLARE_CLASS_CONST(Number, min = 0); | ||||
|         DECLARE_CLASS_CONST(Number, max = UCHAR_MAX); | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| template <> struct complement_base<true> | ||||
| { | ||||
|     template <class Number> | ||||
|     struct values | ||||
|     { | ||||
|         DECLARE_CLASS_CONST(Number, min = SCHAR_MIN); | ||||
|         DECLARE_CLASS_CONST(Number, max = SCHAR_MAX); | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| // Base specialization of complement, puts an end to the recursion. | ||||
| template <> | ||||
| struct complement<1> | ||||
| { | ||||
|     template <class Number> | ||||
|     struct traits | ||||
|     { | ||||
|         DECLARE_CLASS_CONST(bool, is_signed = boost::detail::is_signed<Number>::value); | ||||
|         DECLARE_CLASS_CONST(Number, min = | ||||
|                             complement_base<is_signed>::template values<Number>::min); | ||||
|         DECLARE_CLASS_CONST(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 | ||||
| { | ||||
|     DECLARE_CLASS_CONST(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max)); | ||||
|     DECLARE_CLASS_CONST(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) // No intmax streaming built-in | ||||
|  | ||||
| // On this platform, __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) // 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; | ||||
| } | ||||
							
								
								
									
										597
									
								
								operators.htm
									
									
									
									
									
								
							
							
						
						
									
										597
									
								
								operators.htm
									
									
									
									
									
								
							| @@ -1,597 +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/operators.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/operators.hpp">boost/operators.hpp</a></h1> | ||||
| <p>Header <a href="../../boost/operators.hpp">boost/operators.hpp</a> supplies | ||||
| (in namespace boost) several sets of templates:</p> | ||||
| <ul> | ||||
|   <li><a href="#Arithmetic">Arithmetic operators</a>. | ||||
|   <li><a href="#deref and helpers">Dereference operators and iterator helpers.</a></li> | ||||
| </ul> | ||||
| <p>These templates define many global operators in terms of a minimal number of | ||||
| fundamental operators.</p> | ||||
| <h1><a name="Arithmetic">Arithmetic</a> Operators</h1> | ||||
| <p>If, for example, you declare a class like this:</p> | ||||
| <blockquote> | ||||
|   <pre>class MyInt : boost::operators<MyInt> | ||||
| { | ||||
|     bool operator<(const MyInt& x) const;  | ||||
|     bool operator==(const MyInt& x) const; | ||||
|     MyInt& operator+=(const MyInt& x);     | ||||
|     MyInt& operator-=(const MyInt& x);     | ||||
|     MyInt& operator*=(const MyInt& x);     | ||||
|     MyInt& operator/=(const MyInt& x);     | ||||
|     MyInt& operator%=(const MyInt& x);     | ||||
|     MyInt& operator|=(const MyInt& x);     | ||||
|     MyInt& operator&=(const MyInt& x);     | ||||
|     MyInt& operator^=(const MyInt& x);     | ||||
|     MyInt& operator++();     | ||||
|     MyInt& operator--();     | ||||
| };</pre> | ||||
| </blockquote> | ||||
| <p>then the <code>operators<></code> template adds more than a dozen | ||||
| additional operators, such as operator>, <=, >=, and +.  <a href="#two_arg">Two-argument | ||||
| forms</a> of the templates are also provided to allow interaction with other | ||||
| types.</p> | ||||
| <p><a href="http://www.boost.org/people/dave_abrahams.htm">Dave Abrahams</a> | ||||
| started the library and contributed the arithmetic operators in <a href="../../boost/operators.hpp">boost/operators.hpp</a>.<br> | ||||
| <a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a> | ||||
| contributed the <a href="#deref and helpers">dereference operators and iterator | ||||
| helpers</a> in <a href="../../boost/operators.hpp">boost/operators.hpp</a>.<br> | ||||
| <a href="http://www.boost.org/people/aleksey_gurtovoy.htm">Aleksey Gurtovoy</a> | ||||
| contributed the code to support <a href="#chaining">base class chaining</a> | ||||
| while remaining backward-compatible with old versions of the library.<br> | ||||
| <a href="http://www.boost.org/people/beman_dawes.html">Beman Dawes</a> | ||||
| contributed <a href="http://www.boost.org/libs/utility/operators_test.cpp">test_operators.cpp</a>.</p> | ||||
| <h2>Rationale</h2> | ||||
| <p>Overloaded operators for class types typically occur in groups. If you can | ||||
| write <code>x + y</code>, you probably also want to be able to write <code>x += | ||||
| y</code>. If you can write <code>x < y,</code> you also want <code>x > y, | ||||
| x >= y,</code> and <code>x <= y</code>. Moreover, unless your class has | ||||
| really surprising behavior, some of these related operators can be defined in | ||||
| terms of others (e.g. <code>x >= y <b><=></b> !(x < y)</code>). | ||||
| Replicating this boilerplate for multiple classes is both tedious and | ||||
| error-prone. The <a href="../../boost/operators.hpp">boost/operators.hpp</a> | ||||
| templates help by generating operators for you at namespace scope based on other | ||||
| operators you've defined in your class.</p> | ||||
| <a name="two_arg"> | ||||
| <h2>Two-Argument Template Forms</h2> | ||||
| </a> | ||||
| <p>The arguments to a binary operator commonly have identical types, but it is | ||||
| not unusual to want to define operators which combine different types. For <a href="#usage">example</a>, | ||||
| one might want to multiply a mathematical vector by a scalar. The two-argument | ||||
| template forms of the arithmetic operator templates are supplied for this | ||||
| purpose. When applying the two-argument form of a template, the desired return | ||||
| type of the operators typically determines which of the two types in question | ||||
| should be derived from the operator template. For example, if the result of <code>T + U</code> | ||||
| is of type <code>T</code>, then <code>T</code> (not <code>U</code>) should be | ||||
| derived from <code>addable<T,U></code>. The comparison templates <code><a href="#less_than_comparable">less_than_comparable<></a></code> | ||||
| and <code><a href="#equality_comparable">equality_comparable<></a></code> | ||||
| are exceptions to this guideline, since the return type of the operators they | ||||
| define is <code>bool</code>.</p> | ||||
| <p>On compilers which do not support partial specialization, the two-argument | ||||
| forms must be specified by using the names shown below with the trailing <code>'2'</code>. | ||||
| The single-argument forms with the trailing <code>'1'</code> are provided for | ||||
| symmetry and to enable certain applications of the <a href="#chaining">base | ||||
| class chaining</a> technique.</p> | ||||
| <h2>Arithmetic operators table</h2> | ||||
| <p>The requirements for the types used to instantiate operator templates are | ||||
| specified in terms of expressions which must be valid and by the return type of | ||||
| the expression. In the following table <code>t</code> and <code>t1</code> are | ||||
| values of type <code>T</code>, and <code>u</code> is a value of type <code>U</code>. | ||||
| Every template in the library other than <a href="#operators"><code>operators<></code></a> | ||||
| and <a href="#operators"><code>operators2<></code></a> has an additional | ||||
| optional template parameter <code>B</code> which is not shown in the table, but | ||||
| is explained <a href="#chaining">below</a></p> | ||||
| <table cellpadding="5" border="1"> | ||||
|   <tbody> | ||||
|     <tr> | ||||
|       <td><b>template</b></td> | ||||
|       <td><b>template will supply</b></td> | ||||
|       <td><b>Requirements</b></td> | ||||
|     </tr> | ||||
|     <a name="operators"> | ||||
|     <tr> | ||||
|       <td><code>operators<T></code></td> | ||||
|       <td>All the other <T> templates in this table.</td> | ||||
|       <td>All the <T> requirements in this table.</td> | ||||
|     <tr> | ||||
|       <td><code>operators<T,U><br> | ||||
|         operators2<T,U></code></td> | ||||
|       <td>All the other <T,U> templates in this table, plus incrementable<T> | ||||
|         and decrementable<T>.</td> | ||||
|       <td><b>All</b> the <T,U> requirements in this table</a><a href="#portability">*</a>, | ||||
|       plus incrementable<T> and decrementable<T>.</td> | ||||
|     </tr> | ||||
|     <a name="less_than_comparable"> | ||||
|     <tr> | ||||
|       <td><code>less_than_comparable<T><br> | ||||
|         less_than_comparable1<T></code></td> | ||||
|       <td><code>bool operator>(const T&, const T&) <br> | ||||
|         bool operator<=(const T&, const T&)<br> | ||||
|         bool operator>=(const T&, const T&)</code></td> | ||||
|       <td><code>t<t1</code>. Return convertible to bool</td> | ||||
|     <tr> | ||||
|       <td><code>less_than_comparable<T,U><br> | ||||
|         less_than_comparable2<T,U></code></td> | ||||
|       <td><code>bool operator<=(const T&, const U&)<br> | ||||
|         bool operator>=(const T&, const U&)<br> | ||||
|         bool operator>(const U&, const T&) <br> | ||||
|         bool operator<(const U&, const T&) <br> | ||||
|         bool operator<=(const U&, const T&)<br> | ||||
|         bool operator>=(const U&, const T&)</code></td> | ||||
|       <td><code>t<u</code>. Return convertible to bool<br> | ||||
|         <code>t>u</code>. Return convertible to bool</td> | ||||
|     </tr> | ||||
|     </a><a name="equality_comparable"> | ||||
|     <tr> | ||||
|       <td><code>equality_comparable<T><br> | ||||
|         equality_comparable1<T></code></td> | ||||
|       <td><code>bool operator!=(const T&, const T&)</code></td> | ||||
|       <td><code>t==t1</code>. Return convertible to bool</td> | ||||
|     <tr> | ||||
|       <td><code>equality_comparable<T,U><br> | ||||
|         equality_comparable2<T,U></code></td> | ||||
|       <td><code>friend bool operator==(const U&, const T&)<br> | ||||
|         friend bool operator!=(const U&, const T&)<br> | ||||
|         friend bool operator!=( const T&, const U&)</code></td> | ||||
|       <td><code>t==u</code>. Return convertible to bool</td> | ||||
|     </tr> | ||||
|     </a> | ||||
|     <tr> | ||||
|       <td><code>addable<T><br> | ||||
|         addable1<T></code></td> | ||||
|       <td><code>T operator+(T, const T&)</code></td> | ||||
|       <td><code>t+=t1</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>addable<T,U><br> | ||||
|         addable2<T,U></code></td> | ||||
|       <td><code>T operator+(T, const U&)<br> | ||||
|         T operator+(const U&, T )</code></td> | ||||
|       <td><code>t+=u</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>subtractable<T><br> | ||||
|         subtractable1<T></code></td> | ||||
|       <td><code>T operator-(T, const T&)</code></td> | ||||
|       <td><code>t-=t1</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>subtractable<T,U><br> | ||||
|         subtractable2<T,U></code></td> | ||||
|       <td><code>T operator-(T, const U&)</code></td> | ||||
|       <td><code>t-=u</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>multipliable<T><br> | ||||
|         multipliable1<T></code></td> | ||||
|       <td><code>T operator*(T, const T&)</code></td> | ||||
|       <td><code>t*=t1</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>multipliable<T,U><br> | ||||
|         multipliable2<T,U></code></td> | ||||
|       <td><code>T operator*(T, const U&)<br> | ||||
|         T operator*(const U&, T )</code></td> | ||||
|       <td><code>t*=u</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>dividable<T><br> | ||||
|         dividable1<T></code></td> | ||||
|       <td><code>T operator/(T, const T&)</code></td> | ||||
|       <td><code>t/=t1</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>dividable<T,U><br> | ||||
|         dividable2<T,U></code></td> | ||||
|       <td><code>T operator/(T, const U&)</code></td> | ||||
|       <td><code>t/=u</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>modable<T><br> | ||||
|         modable1<T></code></td> | ||||
|       <td><code>T operator%(T, const T&)</code></td> | ||||
|       <td><code>t%=t1</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>modable<T,U><br> | ||||
|         modable2<T,U></code></td> | ||||
|       <td><code>T operator%(T, const U&)</code></td> | ||||
|       <td><code>t%=u</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>orable<T><br> | ||||
|         orable1<T></code></td> | ||||
|       <td><code>T operator|(T, const T&)</code></td> | ||||
|       <td><code>t|=t1</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>orable<T,U><br> | ||||
|         orable2<T,U></code></td> | ||||
|       <td><code>T operator|(T, const U&)<br> | ||||
|         T operator|(const U&, T )</code></td> | ||||
|       <td><code>t|=u</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>andable<T><br> | ||||
|         andable1<T></code></td> | ||||
|       <td><code>T operator&(T, const T&)</code></td> | ||||
|       <td><code>t&=t1</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>andable<T,U><br> | ||||
|         andable2<T,U></code></td> | ||||
|       <td><code>T operator&(T, const U&)<br> | ||||
|         T operator&(const U&, T)</code></td> | ||||
|       <td><code>t&=u</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>xorable<T><br> | ||||
|         xorable1<T></code></td> | ||||
|       <td><code>T operator^(T, const T&)</code></td> | ||||
|       <td><code>t^=t1</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>xorable<T,U><br> | ||||
|         xorable2<T,U></code></td> | ||||
|       <td><code>T operator^(T, const U&)<br> | ||||
|         T operator^(const U&, T )</code></td> | ||||
|       <td><code>t^=u</code>. Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>incrementable<T><br> | ||||
|         incrementable1<T></code></td> | ||||
|       <td><code>T operator++(T& x, int)</code></td> | ||||
|       <td><code>T temp(x); ++x; return temp;</code><br> | ||||
|         Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>decrementable<T><br> | ||||
|         decrementable1<T></code></td> | ||||
|       <td><code>T operator--(T& x, int)</code></td> | ||||
|       <td><code>T temp(x); --x; return temp;</code><br> | ||||
|         Return convertible to <code>T</code></td> | ||||
|     </tr> | ||||
|   </tbody> | ||||
| </table> | ||||
| <br> | ||||
| <b><a name="portability">Portability Note:</a></b> many compilers (e.g. MSVC6.3, | ||||
| GCC 2.95.2) will not enforce the requirements in this table unless the | ||||
| operations which depend on them are actually used. This is not | ||||
| standard-conforming behavior. If you are trying to write portable code it is | ||||
| important not to rely on this bug. In particular, it would be convenient to | ||||
| derive all your classes which need binary operators from the <a href="#operators"><code>operators<></code></a> | ||||
| and <a href="#operators"><code>operators2<></code></a> templates, | ||||
| regardless of whether they implement all the requirements in the table. Even if | ||||
| this works with your compiler today, it may not work tomorrow. | ||||
| <h2><a name="chaining">Base Class Chaining</a> and Object Size</h2> | ||||
| <p>Every template listed in the table except <a href="#operators"><code>operators<></code></a> | ||||
| and <a href="#operators"><code>operators2<></code></a> has an additional | ||||
| optional template parameter <code>B</code>.  If supplied, <code>B</code> | ||||
| must be a class type; the resulting class will be publicly derived from B. This | ||||
| can be used to avoid the object size bloat commonly associated with multiple | ||||
| empty base classes (see the <a href="#old_lib_note">note for users of older | ||||
| versions</a> below for more details). To provide support for several groups of | ||||
| operators, use the additional parameter to chain operator templates into a | ||||
| single-base class hierarchy, as in the following <a href="#usage">example</a>.</p> | ||||
| <p><b>Caveat:</b> to chain to a base class which is <i>not</i> a boost operator | ||||
| template when using the <a href="#two_arg">single-argument form</a><a> of a | ||||
| boost operator template, you must specify the operator template with the | ||||
| trailing <code>'1'</code> in its name. Otherwise the library will assume you | ||||
| mean to define a binary operation combining the class you intend to use as a | ||||
| base class and the class you're deriving.</p> | ||||
| <p><b>Borland users</b>: even single-inheritance seems to cause an increase in | ||||
| object size in some cases. If you are not defining a template, you may get | ||||
| better object-size performance by avoiding derivation altogether, and instead | ||||
| explicitly instantiating the operator template as follows: | ||||
| <pre> | ||||
|     class myclass // lose the inheritance... | ||||
|     { | ||||
|         //... | ||||
|     }; | ||||
|     // explicitly instantiate the operators I need. | ||||
|     template class less_than_comparable<myclass>; | ||||
|     template class equality_comparable<myclass>; | ||||
|     template class incrementable<myclass>; | ||||
|     template class decrementable<myclass>; | ||||
|     template class addable<myclass,long>; | ||||
|     template class subtractable<myclass,long>; | ||||
| </pre> | ||||
| </a><a name="usage"> | ||||
| <h2>Usage example</h2> | ||||
| </a> | ||||
| <pre>template <class T> | ||||
| class point    // note: private inheritance is OK here! | ||||
|     : boost::addable< point<T>          // point + point | ||||
|     , boost::subtractable< point<T>     // point - point | ||||
|     , boost::dividable2< point<T>, T    // point / T | ||||
|     , boost::multipliable2< point<T>, T // point * T, T * point | ||||
|       > > > > | ||||
| { | ||||
| public: | ||||
|     point(T, T); | ||||
|     T x() const; | ||||
|     T y() const; | ||||
|  | ||||
|     point operator+=(const point&); | ||||
|     // point operator+(point, const point&) automatically | ||||
|     // generated by addable. | ||||
|  | ||||
|     point operator-=(const point&); | ||||
|     // point operator-(point, const point&) automatically | ||||
|     // generated by subtractable. | ||||
|  | ||||
|     point operator*=(T); | ||||
|     // point operator*(point, const T&) and | ||||
|     // point operator*(const T&, point) auto-generated | ||||
|     // by multipliable. | ||||
|  | ||||
|     point operator/=(T); | ||||
|     // point operator/(point, const T&) auto-generated | ||||
|     // by dividable. | ||||
| private: | ||||
|     T x_; | ||||
|     T y_; | ||||
| }; | ||||
|  | ||||
| // now use the point<> class: | ||||
|  | ||||
| template <class T> | ||||
| T length(const point<T> p) | ||||
| { | ||||
|     return sqrt(p.x()*p.x() + p.y()*p.y()); | ||||
| } | ||||
|  | ||||
| const point<float> right(0, 1); | ||||
| const point<float> up(1, 0); | ||||
| const point<float> pi_over_4 = up + right; | ||||
| const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4);</pre> | ||||
| <h2>Arithmetic operators demonstration and test program</h2> | ||||
| <p>The <a href="http://www.boost.org/libs/utility/operators_test.cpp">operators_test.cpp</a> | ||||
| program demonstrates the use of the arithmetic operator templates, and can also | ||||
| be used to verify correct operation.</p> | ||||
| <p>The test program has been compiled and run successfully with: </p> | ||||
| <ul> | ||||
|   <li>GCC 2.95.2 | ||||
|   <li>GCC 2.95.2 / STLport 4.0b8. | ||||
|   <li>Metrowerks Codewarrior 5.3 | ||||
|   <li>KAI C++ 3.3 | ||||
|   <li>Microsoft Visual C++ 6.0 SP3. | ||||
|   <li>Microsoft Visual C++ 6.0 SP3 / STLport 4.0b8.</li> | ||||
| </ul> | ||||
| <h1><a name="deref and helpers">Dereference</a> operators and iterator helpers</h1> | ||||
| <p>The <a href="#Iterator helpers">iterator helper</a> templates ease the task | ||||
| of creating a custom iterator. Similar to arithmetic types, a complete iterator | ||||
| has many operators that are "redundant" and can be implemented in | ||||
| terms of the core set of operators.</p> | ||||
| <p>The <a href="#dereference">dereference operators</a> were motivated by the <a href="#Iterator helpers">iterator | ||||
| helpers</a>, but are often useful in non-iterator contexts as well. Many of the | ||||
| redundant iterator operators are also arithmetic operators, so the iterator | ||||
| helper classes borrow many of the operators defined above. In fact, only two new | ||||
| operators need to be defined! (the pointer-to-member <code>operator-></code> | ||||
| and the subscript <code>operator[]</code>). </PP> | ||||
| <h3>Notation</h3> | ||||
| <table> | ||||
|   <tbody> | ||||
|     <tr> | ||||
|       <td valign="top"><code>T</code></td> | ||||
|       <td valign="top">is the user-defined type for which the operations are | ||||
|         being supplied.</td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td valign="top"><code>V</code></td> | ||||
|       <td valign="top">is the type which the resulting <code>dereferenceable</code> | ||||
|         type "points to", or the <code>value_type</code> of the custom | ||||
|         iterator.</td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td valign="top"><code>D</code></td> | ||||
|       <td valign="top">is the type used to index the resulting <code>indexable</code> | ||||
|         type or the <code>difference_type</code> of the custom iterator.</td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td valign="top"><code>P</code></td> | ||||
|       <td valign="top">is a type which can be dereferenced to access <code>V</code>, | ||||
|         or the <code>pointer</code> type of the custom iterator.</td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td valign="top"><code>R</code></td> | ||||
|       <td valign="top">is the type returned by indexing the <code>indexable</code> | ||||
|         type or the <code>reference</code> type of the custom iterator.</td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td valign="top"><code>i</code></td> | ||||
|       <td valign="top">is short for <code>static_cast<const T&>(*this)</code>, | ||||
|         where <code>this</code> is a pointer to the helper class.<br> | ||||
|         Another words, <code>i</code> should be an object of the custom iterator | ||||
|         type.</td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td valign="top"><code>x,x1,x2</code></td> | ||||
|       <td valign="top">are objects of type <code>T</code>.</td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td valign="top"><code>n</code></td> | ||||
|       <td valign="top">is an object of type <code>D</code>.</td> | ||||
|     </tr> | ||||
|   </tbody> | ||||
| </table> | ||||
| <p>The requirements for the types used to instantiate the dereference operators | ||||
| and iterator helpers are specified in terms of expressions which must be valid | ||||
| and their return type. </p> | ||||
| <h2><a name="dereference">Dereference operators</a></h2> | ||||
| <p>The dereference operator templates in this table all accept an optional | ||||
| template parameter (not shown) to be used for <a href="#chaining">base class | ||||
| chaining</a>. | ||||
| <table cellpadding="5" border="1"> | ||||
|   <tbody> | ||||
|     <tr> | ||||
|       <td><b>template</b></td> | ||||
|       <td><b>template will supply</b></td> | ||||
|       <td><b>Requirements</b></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>dereferenceable<T,P></code></td> | ||||
|       <td><code>P operator->() const</code></td> | ||||
|       <td><code>(&*i.)</code>. Return convertible to <code>P</code>.</td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>indexable<T,D,R></code></td> | ||||
|       <td><code>R operator[](D n) const</code></td> | ||||
|       <td><code>*(i + n)</code>. Return of type <code>R</code>.</td> | ||||
|     </tr> | ||||
|   </tbody> | ||||
| </table> | ||||
| <h2><a name="Iterator helpers">Iterator</a> helpers</h2> | ||||
| <p>There are three separate iterator helper classes, each for a different | ||||
| category of iterator. Here is a summary of the core set of operators that the | ||||
| custom iterator must define, and the extra operators that are created by the | ||||
| helper classes. For convenience, the helper classes also fill in all of the | ||||
| typedef's required of iterators by the C++ standard (<code>iterator_category</code>, | ||||
| <code>value_type</code>, etc.).</p> | ||||
| <table cellpadding="5" border="1" valign="top"> | ||||
|   <tbody> | ||||
|     <tr> | ||||
|       <td><b>template</b></td> | ||||
|       <td><b>template will supply</b></td> | ||||
|       <td><b>Requirements</b></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>forward_iterator_helper</code><br> | ||||
|         <code><T,V,D,P,R></code></td> | ||||
|       <td><code>bool operator!=(const T& x1, const T& x2)</code><br> | ||||
|         <code>T operator++(T& x, int)</code><br> | ||||
|         <code>V* operator->() const</code><br> | ||||
|       </td> | ||||
|       <td><code>x1==x2</code>. Return convertible to bool<br> | ||||
|         <code>T temp(x); ++x; return temp;</code><br> | ||||
|         <code>(&*i.)</code>. Return convertible to <code>V*</code>.</td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>bidirectional_iterator_helper</code><br> | ||||
|         <code><T,V,D,P,R></code></td> | ||||
|       <td>Same as above, plus<br> | ||||
|         <code>T operator--(T& x, int)</code></td> | ||||
|       <td>Same as above, plus<br> | ||||
|         <code>T temp(x); --x; return temp;</code></td> | ||||
|     </tr> | ||||
|     <tr> | ||||
|       <td><code>random_access_iterator_helper</code><br> | ||||
|         <code><T,V,D,P,R></code></td> | ||||
|       <td>Same as above, plus<br> | ||||
|         <code>T operator+(T x, const D&)<br> | ||||
|         T operator+(const D& n, T x)<br> | ||||
|         T operator-(T x, const D& n)<br> | ||||
|         R operator[](D n) const<br> | ||||
|         bool operator>(const T& x1, const T& x2) <br> | ||||
|         bool operator<=(const T& x1, const T& x2)<br> | ||||
|         bool operator>=(const T& x1, const T& x2)</code></td> | ||||
|       <td>Same as above, plus<br> | ||||
|         <code>x+=n</code>. Return convertible to <code>T</code><br> | ||||
|         <code>x-=n</code>. Return convertible to <code>T</code><br> | ||||
|         <code>x1<x2</code>. Return convertible to bool<br> | ||||
|         And to satisfy <a href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html">RandomAccessIterator</a>:<br> | ||||
|         <code>x1-x2</code>. Return convertible to <code>D</code></td> | ||||
|     </tr> | ||||
|   </tbody> | ||||
| </table> | ||||
| <h2>Iterator demonstration and test program</h2> | ||||
| <p>The <a href="http://www.boost.org/libs/utility/iterators_test.cpp">iterators_test.cpp</a> | ||||
| program demonstrates the use of the iterator templates, and can also be used to | ||||
| verify correct operation. The following is the custom iterator defined in the | ||||
| test program. It demonstrates a correct (though trivial) implementation of the | ||||
| core operations that must be defined in order for the iterator helpers to | ||||
| "fill in" the rest of the iterator operations.</p> | ||||
| <blockquote> | ||||
|   <pre>template <class T, class R, class P> | ||||
| struct test_iter | ||||
|   : public boost::random_access_iterator_helper< | ||||
|      test_iter<T,R,P>, T, std::ptrdiff_t, P, R> | ||||
| { | ||||
|   typedef test_iter self; | ||||
|   typedef R Reference; | ||||
|   typedef std::ptrdiff_t Distance; | ||||
|  | ||||
| public: | ||||
|   test_iter(T* i) : _i(i) { } | ||||
|   test_iter(const self& x) : _i(x._i) { } | ||||
|   self& operator=(const self& x) { _i = x._i; return *this; } | ||||
|   Reference operator*() const { return *_i; } | ||||
|   self& operator++() { ++_i; return *this; } | ||||
|   self& operator--() { --_i; return *this; } | ||||
|   self& operator+=(Distance n) { _i += n; return *this; } | ||||
|   self& operator-=(Distance n) { _i -= n; return *this; } | ||||
|   bool operator==(const self& x) const { return _i == x._i; } | ||||
|   bool operator<(const self& x) const { return _i < x._i; } | ||||
|   friend Distance operator-(const self& x, const self& y) { | ||||
|     return x._i - y._i;  | ||||
|   } | ||||
| protected: | ||||
|   T* _i; | ||||
| };</pre> | ||||
| </blockquote> | ||||
| <p>It has been compiled and run successfully with:</p> | ||||
| <ul> | ||||
|   <li>GCC 2.95.2 | ||||
|   <li>Metrowerks Codewarrior 5.2 | ||||
|   <li>Microsoft Visual C++ 6.0 SP3</li> | ||||
| </ul> | ||||
| <p><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a> | ||||
| contributed the iterator operators and helpers.  He also contributed <a href="http://www.boost.org/libs/utility/iterators_test.cpp">iterators_test.cpp</a>. </p> | ||||
| <hr> | ||||
| <h2><a name="old_lib_note">Note for users of older versions</a></h2> | ||||
| <p>The <a href="#chaining">changes in the library interface and recommended | ||||
| usage</a> were motivated by some practical issues described below. The new | ||||
| version of the library is still backward-compatible with the former one (so | ||||
| you're not <i>forced</i> change any existing code), but the old usage is | ||||
| deprecated. Though it was arguably simpler and more intuitive than using <a href="#chaining">base | ||||
| class chaining</a>, it has been discovered that the old practice of deriving | ||||
| from multiple operator templates can cause the resulting classes to be much | ||||
| larger than they should be. Most modern C++ compilers significantly bloat the | ||||
| size of classes derived from multiple empty base classes, even though the base | ||||
| classes themselves have no state. For instance, the size of <code>point<int></code> | ||||
| from the <a href="#usage">example</a> above was 12-24 bytes on various compilers | ||||
| for the Win32 platform, instead of the expected 8 bytes. | ||||
| <p>Strictly speaking, it was not the library's fault - the language rules allow | ||||
| the compiler to apply the empty base class optimization in that situation. In | ||||
| principle an arbitrary number of empty base classes can be allocated at the same | ||||
| offset, provided that none of them have a common ancestor (see section 10.5 [class.derived], | ||||
| par. 5 of the standard). But the language definition also doesn't <i>require</i> | ||||
| implementations to do the optimization, and few if any of today's compilers | ||||
| implement it when multiple inheritance is involved. What's worse, it is very | ||||
| unlikely that implementors will adopt it as a future enhancement to existing | ||||
| compilers, because it would break binary compatibility between code generated by | ||||
| two different versions of the same compiler. As Matt Austern said, "One of | ||||
| the few times when you have the freedom to do this sort of thing is when you're | ||||
| targeting a new architecture...". On the other hand, many common compilers | ||||
| will use the empty base optimization for single inheritance hierarchies.</p> | ||||
| <p>Given the importance of the issue for the users of the library (which aims to | ||||
| be useful for writing light-weight classes like <code>MyInt</code> or <code>point<></code>), | ||||
| and the forces described above, we decided to change the library interface so | ||||
| that the object size bloat could be eliminated even on compilers that support | ||||
| only the simplest form of the empty base class optimization. The current library | ||||
| interface is the result of those changes. Though the new usage is a bit more | ||||
| complicated than the old one, we think it's worth it to make the library more | ||||
| useful in real world. Alexy Gurtovoy contributed the code which supports the new | ||||
| usage idiom while allowing the library remain backward-compatible.</p> | ||||
| <hr> | ||||
| <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->28 Sep 2000<!--webbot bot="Timestamp" endspan i-checksum="14938" --></p> | ||||
| <p><EFBFBD> Copyright David Abrahams and Beman Dawes 1999-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> | ||||
| @@ -1,481 +0,0 @@ | ||||
| //  Demonstrate and test boost/operators.hpp  -------------------------------// | ||||
|  | ||||
| //  (C) Copyright Beman Dawes 1999. Permission to copy, use, modify, sell and | ||||
| //  distribute this software is granted provided this copyright notice appears | ||||
| //  in all copies. This software is provided "as is" without express or implied | ||||
| //  warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  04 Jun 00 Added regression test for a bug I found (David Abrahams) | ||||
| //  17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy) | ||||
| //  ?? ??? 00 Major update to randomly test all one- and two- argument forms by | ||||
| //            wrapping integral types and comparing the results of operations to | ||||
| //            the results for the raw types (David Abrahams) | ||||
| //  12 Dec 99 Minor update, output confirmation message. | ||||
| //  15 Nov 99 Initial version | ||||
|  | ||||
| #include <boost/operators.hpp> | ||||
| #include <cassert> | ||||
| #include <iostream> | ||||
| #include <boost/min_rand.hpp> | ||||
|  | ||||
|  | ||||
| namespace | ||||
| { | ||||
|     // avoiding a template version of true_value so as to not confuse VC++ | ||||
|     int true_value(int x) { return x; } | ||||
|     long true_value(long x) { return x; } | ||||
|     signed char true_value(signed char x) { return x; } | ||||
|     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; } | ||||
|  | ||||
|     // The use of operators<> here tended to obscure interactions with certain | ||||
|     // compiler bugs | ||||
|     template <class T> | ||||
|     class Wrapped1 : boost::operators<Wrapped1<T> > | ||||
|     { | ||||
|     public: | ||||
|         explicit Wrapped1( T v = T() ) : _value(v) {} | ||||
|         T value() const { return _value; } | ||||
|  | ||||
|         bool operator<(const Wrapped1& x) const { return _value < x._value; } | ||||
|         bool operator==(const Wrapped1& x) const { return _value == x._value; } | ||||
|          | ||||
|         Wrapped1& operator+=(const Wrapped1& x) | ||||
|           { _value += x._value; return *this; } | ||||
|         Wrapped1& operator-=(const Wrapped1& x) | ||||
|           { _value -= x._value; return *this; } | ||||
|         Wrapped1& operator*=(const Wrapped1& x) | ||||
|           { _value *= x._value; return *this; } | ||||
|         Wrapped1& operator/=(const Wrapped1& x) | ||||
|           { _value /= x._value; return *this; } | ||||
|         Wrapped1& operator%=(const Wrapped1& x) | ||||
|           { _value %= x._value; return *this; } | ||||
|         Wrapped1& operator|=(const Wrapped1& x) | ||||
|           { _value |= x._value; return *this; } | ||||
|         Wrapped1& operator&=(const Wrapped1& x) | ||||
|           { _value &= x._value; return *this; } | ||||
|         Wrapped1& operator^=(const Wrapped1& x) | ||||
|           { _value ^= x._value; return *this; } | ||||
|         Wrapped1& operator++()               { ++_value; return *this; } | ||||
|         Wrapped1& operator--()               { --_value; return *this; } | ||||
|          | ||||
|     private: | ||||
|         T _value; | ||||
|     }; | ||||
|     template <class T> | ||||
|     T true_value(Wrapped1<T> x) { return x.value(); }     | ||||
|  | ||||
|     template <class T, class U> | ||||
|     class Wrapped2 : | ||||
|         boost::operators<Wrapped2<T, U> >, | ||||
|         boost::operators2<Wrapped2<T, U>, U> | ||||
|     { | ||||
|     public: | ||||
|         explicit Wrapped2( T v = T() ) : _value(v) {} | ||||
|         T value() const { return _value; } | ||||
|  | ||||
|         bool operator<(const Wrapped2& x) const { return _value < x._value; } | ||||
|         bool operator==(const Wrapped2& x) const { return _value == x._value; } | ||||
|          | ||||
|         Wrapped2& operator+=(const Wrapped2& x) | ||||
|           { _value += x._value; return *this; } | ||||
|         Wrapped2& operator-=(const Wrapped2& x) | ||||
|           { _value -= x._value; return *this; } | ||||
|         Wrapped2& operator*=(const Wrapped2& x) | ||||
|           { _value *= x._value; return *this; } | ||||
|         Wrapped2& operator/=(const Wrapped2& x) | ||||
|           { _value /= x._value; return *this; } | ||||
|         Wrapped2& operator%=(const Wrapped2& x) | ||||
|           { _value %= x._value; return *this; } | ||||
|         Wrapped2& operator|=(const Wrapped2& x) | ||||
|           { _value |= x._value; return *this; } | ||||
|         Wrapped2& operator&=(const Wrapped2& x) | ||||
|           { _value &= x._value; return *this; } | ||||
|         Wrapped2& operator^=(const Wrapped2& x) | ||||
|           { _value ^= x._value; return *this; } | ||||
|         Wrapped2& operator++()                { ++_value; return *this; } | ||||
|         Wrapped2& operator--()                { --_value; return *this; } | ||||
|           | ||||
|         bool operator<(U u) const { return _value < u; } | ||||
|         bool operator>(U u) const { return _value > u; } | ||||
|         bool operator==(U u) const { return _value == u; } | ||||
|         Wrapped2& operator+=(U u) { _value += u; return *this; } | ||||
|         Wrapped2& operator-=(U u) { _value -= u; return *this; } | ||||
|         Wrapped2& operator*=(U u) { _value *= u; return *this; } | ||||
|         Wrapped2& operator/=(U u) { _value /= u; return *this; } | ||||
|         Wrapped2& operator%=(U u) { _value %= u; return *this; } | ||||
|         Wrapped2& operator|=(U u) { _value |= u; return *this; } | ||||
|         Wrapped2& operator&=(U u) { _value &= u; return *this; } | ||||
|         Wrapped2& operator^=(U u) { _value ^= u; return *this; } | ||||
|  | ||||
|     private: | ||||
|         T _value; | ||||
|     }; | ||||
|     template <class T, class U> | ||||
|     T true_value(Wrapped2<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; | ||||
|  | ||||
|     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)); | ||||
|     } | ||||
|  | ||||
|     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)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_less_than_comparable_aux(x1, y1, x2, y2); | ||||
|         test_less_than_comparable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 == y1) == (x2 == y2)); | ||||
|         assert((x1 != y1) == (x2 != y2)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_equality_comparable_aux(x1, y1, x2, y2); | ||||
|         test_equality_comparable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 * y1).value() == (x2 * y2)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_multipliable_aux(x1, y1, x2, y2); | ||||
|         test_multipliable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 + y1).value() == (x2 + y2)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_addable_aux(x1, y1, x2, y2); | ||||
|         test_addable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         assert((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); | ||||
|     } | ||||
|      | ||||
|     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); | ||||
|     } | ||||
|      | ||||
|     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)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_xorable_aux(x1, y1, x2, y2); | ||||
|         test_xorable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 & y1).value() == (x2 & y2)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_andable_aux(x1, y1, x2, y2); | ||||
|         test_andable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 | y1).value() == (x2 | y2)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_orable_aux(x1, y1, x2, y2); | ||||
|         test_orable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class X2> | ||||
|     void test_incrementable(X1 x1, X2 x2) | ||||
|     { | ||||
|         sanity_check(x1, x1, x2, x2); | ||||
|         assert(x1++.value() == x2++); | ||||
|         assert(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); | ||||
|     } | ||||
|      | ||||
|     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); | ||||
|     } | ||||
|      | ||||
|     template <class Big, class Small> | ||||
|     struct tester | ||||
|     { | ||||
|         void operator()(boost::min_rand& randomizer) const | ||||
|         { | ||||
|             Big b1 = Big(randomizer()); | ||||
|             Big b2 = Big(randomizer()); | ||||
|             Small s = Small(randomizer()); | ||||
|              | ||||
|             test_all(Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2); | ||||
|             test_all(Wrapped2<Big, Small>(b1), s, b1, s); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     // added as a regression test. We had a bug which this uncovered. | ||||
|     struct Point | ||||
|         : boost::addable<Point, | ||||
|         boost::subtractable<Point> > | ||||
|     { | ||||
|         Point( int h, int v ) : h(h), v(v) {} | ||||
|         Point() :h(0), v(0) {} | ||||
|         const Point& operator+=( const Point& rhs ) { h += rhs.h; v += rhs.v; return *this; } | ||||
|         const Point& operator-=( const Point& rhs ) { h -= rhs.h; v -= rhs.v; return *this; } | ||||
|  | ||||
|         int h; | ||||
|         int v; | ||||
|     }; | ||||
| } // unnamed namespace | ||||
|  | ||||
|  | ||||
| // workaround for MSVC bug; for some reasons the compiler doesn't instantiate | ||||
| // inherited operator templates at the moment it must, so the following | ||||
| // explicit instantiations force it to do that. | ||||
|  | ||||
| #if defined(BOOST_MSVC) && (_MSC_VER <= 1200) | ||||
| template Wrapped1<int>; | ||||
| template Wrapped1<long>; | ||||
| template Wrapped1<unsigned int>; | ||||
| template Wrapped1<unsigned long>; | ||||
|  | ||||
| template Wrapped2<int, int>; | ||||
| template Wrapped2<int, signed char>; | ||||
| template Wrapped2<long, signed char>; | ||||
| template Wrapped2<long, int>; | ||||
| template Wrapped2<long, long>; | ||||
| template Wrapped2<unsigned int, unsigned int>; | ||||
| template Wrapped2<unsigned int, unsigned char>; | ||||
| template Wrapped2<unsigned long, unsigned int>; | ||||
| template Wrapped2<unsigned long, unsigned char>; | ||||
| template Wrapped2<unsigned long, unsigned long>; | ||||
| #endif | ||||
|  | ||||
| #ifdef NDEBUG | ||||
| #error This program is pointless when NDEBUG disables assert()! | ||||
| #endif | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     // Regression test. | ||||
|     Point x; | ||||
|     x = x + Point(3, 4); | ||||
|     x = x - Point(3, 4); | ||||
|      | ||||
|     for (int n = 0; n < 10000; ++n) | ||||
|     { | ||||
|         boost::min_rand r; | ||||
|         tester<long, int>()(r); | ||||
|         tester<long, signed char>()(r); | ||||
|         tester<long, long>()(r); | ||||
|         tester<int, int>()(r); | ||||
|         tester<int, signed char>()(r); | ||||
|          | ||||
|         tester<unsigned long, unsigned int>()(r); | ||||
|         tester<unsigned long, unsigned char>()(r); | ||||
|         tester<unsigned long, unsigned long>()(r); | ||||
|         tester<unsigned int, unsigned int>()(r); | ||||
|         tester<unsigned int, unsigned char>()(r); | ||||
|     } | ||||
|      | ||||
|     MyInt i1(1); | ||||
|     MyInt i2(2); | ||||
|     MyInt i; | ||||
|  | ||||
|     assert( i1.value() == 1 ); | ||||
|     assert( i2.value() == 2 ); | ||||
|     assert( 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 ); | ||||
|  | ||||
|     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 ); | ||||
|      | ||||
|     MyLong j1(1); | ||||
|     MyLong j2(2); | ||||
|     MyLong j; | ||||
|  | ||||
|     assert( j1.value() == 1 ); | ||||
|     assert( j2.value() == 2 ); | ||||
|     assert( 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 ); | ||||
|  | ||||
|     assert( (j1 + 2) == 3 ); | ||||
|     assert( (1 + j2) == 3 ); | ||||
|     j = j1 + j2; assert( j.value() == 3 ); | ||||
|      | ||||
|     assert( (j + 2) == 5 ); | ||||
|     assert( (3 + j2) == 5 ); | ||||
|     j = j + j2; assert( j.value() == 5 ); | ||||
|      | ||||
|     assert( (j - 1) == 4 ); | ||||
|     j = j - j1; assert( j.value() == 4 ); | ||||
|      | ||||
|     assert( (j * 2) == 8 ); | ||||
|     assert( (4 * j2) == 8 ); | ||||
|     j = j * j2; assert( j.value() == 8 ); | ||||
|      | ||||
|     assert( (j / 2) == 4 ); | ||||
|     j = j / j2; assert( j.value() == 4 ); | ||||
|      | ||||
|     assert( (j % 3) == 1 ); | ||||
|     j = j % (j - j1); assert( j.value() == 1 ); | ||||
|      | ||||
|     j = j2 + j2; assert( j.value() == 4 ); | ||||
|      | ||||
|     assert( (1 | j2 | j) == 7 ); | ||||
|     assert( (j1 | 2 | j) == 7 ); | ||||
|     assert( (j1 | j2 | 4) == 7 ); | ||||
|     j = j1 | j2 | j; assert( j.value() == 7 ); | ||||
|      | ||||
|     assert( (7 & j2) == 2 ); | ||||
|     assert( (j & 2) == 2 ); | ||||
|     j = j & j2; assert( j.value() == 2 ); | ||||
|      | ||||
|     j = j | j1; assert( j.value() == 3 ); | ||||
|      | ||||
|     assert( (3 ^ j1) == 2 ); | ||||
|     assert( (j ^ 1) == 2 ); | ||||
|     j = j ^ j1; assert( j.value() == 2 ); | ||||
|      | ||||
|     j = (j+j1)*(j2|j1); assert( j.value() == 9 ); | ||||
|      | ||||
|     std::cout << "0 errors detected\n"; | ||||
|     return 0; | ||||
| } | ||||
| @@ -1,391 +0,0 @@ | ||||
| <html> | ||||
|  | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | ||||
| <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> | ||||
| <meta name="ProgId" content="FrontPage.Editor.Document"> | ||||
| <title>Projection Iterator Adaptor Documentation</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000"> | ||||
|  | ||||
| <img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" | ||||
| align="center" width="277" height="86"> | ||||
|  | ||||
| <h1>Projection Iterator Adaptor</h1> | ||||
|  | ||||
| Defined in header | ||||
| <a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a> | ||||
|  | ||||
| <p> | ||||
| The projection iterator adaptor is similar to the <a | ||||
| href="./transform_iterator.htm">transform iterator adaptor</a> in that | ||||
| its <tt>operator*()</tt> applies some function to the result of | ||||
| dereferencing the base iterator and then returns the result. The | ||||
| difference is that the function must return a reference to some | ||||
| existing object (for example, a data member within the | ||||
| <tt>value_type</tt> of the base iterator). The following | ||||
| <b>pseudo-code</b> gives the basic idea. The data member <tt>p</tt> is | ||||
| the function object. | ||||
|  | ||||
| <pre> | ||||
|   reference projection_iterator::operator*() const { | ||||
|     return this->p(*this->base_iterator); | ||||
|   } | ||||
| </pre> | ||||
|  | ||||
| <h2>Synopsis</h2> | ||||
|  | ||||
| <pre> | ||||
| namespace boost { | ||||
|   template <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 -->16 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14385" --></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 | ||||
|  --> | ||||
| @@ -1,96 +0,0 @@ | ||||
| // (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and | ||||
| // distribute this software is granted provided this copyright notice appears | ||||
| // in all copies. This software is provided "as is" without express or implied | ||||
| // warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <list> | ||||
| #include <iostream> | ||||
| #include <iterator> | ||||
| #include <algorithm> | ||||
| #include <string> | ||||
| #include <boost/iterator_adaptors.hpp> | ||||
|  | ||||
| struct personnel_record { | ||||
|   personnel_record(std::string n, int id) : m_name(n), m_ID(id) { } | ||||
|   std::string m_name; | ||||
|   int m_ID; | ||||
| }; | ||||
|  | ||||
| struct select_name { | ||||
|   typedef personnel_record argument_type; | ||||
|   typedef std::string result_type; | ||||
|   const std::string& operator()(const personnel_record& r) const { | ||||
|     return r.m_name; | ||||
|   } | ||||
|   std::string& operator()(personnel_record& r) const { | ||||
|     return r.m_name; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| struct select_ID { | ||||
|   typedef personnel_record argument_type; | ||||
|   typedef int result_type; | ||||
|   const int& operator()(const personnel_record& r) const { | ||||
|     return r.m_ID; | ||||
|   } | ||||
|   int& operator()(personnel_record& r) const { | ||||
|     return r.m_ID; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| int main(int, char*[]) | ||||
| { | ||||
|   std::list<personnel_record> personnel_list; | ||||
|  | ||||
|   personnel_list.push_back(personnel_record("Barney", 13423)); | ||||
|   personnel_list.push_back(personnel_record("Fred", 12343)); | ||||
|   personnel_list.push_back(personnel_record("Wilma", 62454)); | ||||
|   personnel_list.push_back(personnel_record("Betty", 20490)); | ||||
|  | ||||
|   // Example of using projection_iterator_generator | ||||
|   // to print out the names in the personnel list. | ||||
|  | ||||
|   boost::projection_iterator_generator<select_name, | ||||
|     std::list<personnel_record>::iterator>::type | ||||
|     personnel_first(personnel_list.begin()), | ||||
|     personnel_last(personnel_list.end()); | ||||
|  | ||||
|   std::copy(personnel_first, personnel_last, | ||||
|             std::ostream_iterator<std::string>(std::cout, "\n")); | ||||
|   std::cout << std::endl; | ||||
|    | ||||
|   // Example of using projection_iterator_pair_generator | ||||
|   // to assign new ID numbers to the personnel. | ||||
|    | ||||
|   typedef boost::projection_iterator_pair_generator<select_ID, | ||||
|     std::list<personnel_record>::iterator, | ||||
|     std::list<personnel_record>::const_iterator> PairGen; | ||||
|  | ||||
|   PairGen::iterator ID_first(personnel_list.begin()), | ||||
|     ID_last(personnel_list.end()); | ||||
|  | ||||
|   int new_id = 0; | ||||
|   while (ID_first != ID_last) { | ||||
|     *ID_first = new_id++; | ||||
|     ++ID_first; | ||||
|   } | ||||
|  | ||||
|   PairGen::const_iterator const_ID_first(personnel_list.begin()), | ||||
|     const_ID_last(personnel_list.end()); | ||||
|  | ||||
|   std::copy(const_ID_first, const_ID_last, | ||||
|             std::ostream_iterator<int>(std::cout, " ")); | ||||
|   std::cout << std::endl; | ||||
|   std::cout << std::endl; | ||||
|    | ||||
|   // Example of using make_const_projection_iterator() | ||||
|   // to print out the names in the personnel list again. | ||||
|    | ||||
|   std::copy | ||||
|     (boost::make_const_projection_iterator<select_name>(personnel_list.begin()), | ||||
|      boost::make_const_projection_iterator<select_name>(personnel_list.end()), | ||||
|      std::ostream_iterator<std::string>(std::cout, "\n")); | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
| @@ -1,331 +0,0 @@ | ||||
| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN"> | ||||
|  | ||||
| <html> | ||||
| <head> | ||||
|     <meta name="generator" content="HTML Tidy, see www.w3.org"> | ||||
|     <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | ||||
|     <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> | ||||
|     <meta name="ProgId" content="FrontPage.Editor.Document"> | ||||
|  | ||||
|     <title>Reverse Iterator Adaptor Documentation</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000"> | ||||
|     <img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align= | ||||
|     "center" width="277" height="86">  | ||||
|  | ||||
|     <h1>Reverse Iterator Adaptor</h1> | ||||
|     Defined in header <a href= | ||||
|     "../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>  | ||||
|  | ||||
|     <p>The reverse iterator adaptor flips the direction of a base iterator's | ||||
|     motion. Invoking <tt>operator++()</tt> moves the base iterator backward and | ||||
|     invoking <tt>operator--()</tt> moves the base iterator forward. The Boost | ||||
|     reverse iterator adaptor is better to use than the | ||||
|     <tt>std::reverse_iterator</tt> class in situations where pairs of | ||||
|     mutable/constant iterators are needed (e.g., in containers) because | ||||
|     comparisons and conversions between the mutable and const versions are | ||||
|     implemented correctly. | ||||
|  | ||||
|     <h2>Synopsis</h2> | ||||
| <pre> | ||||
| namespace boost { | ||||
|   template <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 -->26 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14386" --> | ||||
|  | ||||
|  | ||||
|     <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> | ||||
|  | ||||
| @@ -1,42 +0,0 @@ | ||||
| // (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and | ||||
| // distribute this software is granted provided this copyright notice appears | ||||
| // in all copies. This software is provided "as is" without express or implied | ||||
| // warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <iostream> | ||||
| #include <algorithm> | ||||
| #include <boost/iterator_adaptors.hpp> | ||||
|  | ||||
| int main(int, char*[]) | ||||
| { | ||||
|   char letters[] = "hello world!"; | ||||
|   const int N = sizeof(letters)/sizeof(char) - 1; | ||||
|   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; | ||||
| } | ||||
							
								
								
									
										137
									
								
								tie.html
									
									
									
									
									
								
							
							
						
						
									
										137
									
								
								tie.html
									
									
									
									
									
								
							| @@ -1,137 +0,0 @@ | ||||
| <HTML> | ||||
| <!-- | ||||
|   -- Copyright (c) Jeremy Siek, Lie-Quan Lee, and Andrew Lumsdaine  2000 | ||||
|   -- | ||||
|   -- Permission to use, copy, modify, distribute and sell this software | ||||
|   -- and its documentation for any purpose is hereby granted without fee, | ||||
|   -- provided that the above copyright notice appears in all copies and | ||||
|   -- that both that copyright notice and this permission notice appear | ||||
|   -- in supporting documentation.  We make no | ||||
|   -- representations about the suitability of this software for any | ||||
|   -- purpose.  It is provided "as is" without express or implied warranty. | ||||
|   --> | ||||
| <Head> | ||||
| <Title>Boost Tie</Title> | ||||
| <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"  | ||||
| 	ALINK="#ff0000">  | ||||
| <IMG SRC="../../c++boost.gif"  | ||||
|      ALT="C++ Boost" width="277" height="86">  | ||||
|  | ||||
| <BR Clear> | ||||
|  | ||||
| <H1><A NAME="sec:tie"></A> | ||||
| <TT>tie</TT> | ||||
| </H1> | ||||
|  | ||||
| <P> | ||||
| <PRE> | ||||
| template <class A, class B> | ||||
| tied<A,B> tie(A& a, B& b); | ||||
| </PRE> | ||||
|  | ||||
| <P> | ||||
| This is a utility function that makes it more convenient to work with | ||||
| a function which returns a std::pair<>. The effect of the <TT>tie()</TT> | ||||
| function is to allow the assignment of the two values of the pair to | ||||
| two separate variables. The idea for this comes from Jaakko | ||||
| Järvi's Binders [<A | ||||
| HREF="../graph/doc/bibliography.html#jaakko_tuple_assign">1</A>]. | ||||
|  | ||||
| <P> | ||||
|  | ||||
| <H3>Where Defined</H3> | ||||
|  | ||||
| <P> | ||||
| <a href="../../boost/utility.hpp"><TT>boost/utility.hpp</TT></a> | ||||
|  | ||||
| <P> | ||||
|  | ||||
| <H3>Example</H3> | ||||
|  | ||||
| <P> | ||||
| An example of using the <TT>tie()</TT> function with the | ||||
| <TT>vertices()</TT> function, which returns a pair of | ||||
| type <TT>std::pair<vertex_iterator,vertex_iterator></TT>.  The | ||||
| pair of iterators is assigned to the iterator variables <TT>i</TT> and | ||||
| <TT>end</TT>. | ||||
|  | ||||
| <P> | ||||
| <PRE> | ||||
|   graph_traits< adjacency_list<> >::vertex_iterator i, end; | ||||
|   for(tie(i,end) = vertices(G); i != end; ++i) | ||||
|     // ... | ||||
| </PRE> | ||||
|  | ||||
| <P> | ||||
| Here is another example that uses <TT>tie()</TT> for handling operations with <a | ||||
| href="http://www.sgi.com/Technology/STL/set.html"><TT>std::set</TT></a>. | ||||
|  | ||||
| <P> | ||||
| <PRE> | ||||
| #include <set> | ||||
| #include <algorithm> | ||||
| #include <iostream> | ||||
| #include <boost/utility.hpp> | ||||
|  | ||||
| int | ||||
| main(int, char*[]) | ||||
| { | ||||
|   { | ||||
|     typedef std::set<int> SetT; | ||||
|     SetT::iterator i, end; | ||||
|     bool inserted; | ||||
|      | ||||
|     int vals[5] = { 5, 2, 4, 9, 1 }; | ||||
|     SetT s(vals, vals + 5); | ||||
|      | ||||
|     // Using tie() with a return value of pair<iterator,bool> | ||||
|  | ||||
|     int new_vals[2] = { 3, 9 }; | ||||
|  | ||||
|     for (int k = 0; k < 2; ++k) { | ||||
|       boost::tie(i,inserted) = s.insert(new_vals[k]); | ||||
|       if (!inserted) | ||||
|         std::cout << *i << " was already in the set." << std::endl; | ||||
|       else | ||||
|         std::cout << *i << " successfully inserted." << std::endl;     | ||||
|     } | ||||
|   }     | ||||
|   { | ||||
|     int* i, *end; | ||||
|     int vals[6] = { 5, 2, 4, 4, 9, 1 }; | ||||
|     std::sort(vals, vals + 6); | ||||
|  | ||||
|     // Using tie() with a return value of pair<iterator,iterator> | ||||
|  | ||||
|     boost::tie(i,end) = std::equal_range(vals, vals + 6, 4); | ||||
|     std::cout << "There were " << std::distance(i,end) | ||||
|               << " occurrences of " << *i << "." << std::endl; | ||||
|     // Footnote: of course one would normally just use std::count() | ||||
|     // to get this information, but that would spoil the example :) | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
| </PRE> | ||||
| The output is: | ||||
| <PRE> | ||||
|   3 successfully inserted. | ||||
|   9 was already in the set. | ||||
|   There were 2 occurrences of 4. | ||||
| </PRE> | ||||
|  | ||||
| <br> | ||||
| <HR> | ||||
| <TABLE> | ||||
| <TR valign=top> | ||||
| <TD nowrap>Copyright © 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>)<br> | ||||
| <A HREF=http://www.lsc.nd.edu/~llee1>Lie-Quan Lee</A>, Univ.of Notre Dame (<A HREF="mailto:llee1@lsc.nd.edu">llee1@lsc.nd.edu</A>)<br> | ||||
| <A HREF=http://www.lsc.nd.edu/~lums>Andrew Lumsdaine</A>, | ||||
| Univ.of Notre Dame (<A | ||||
| HREF="mailto:lums@lsc.nd.edu">lums@lsc.nd.edu</A>) | ||||
| </TD></TR></TABLE> | ||||
|  | ||||
| </BODY> | ||||
| </HTML>  | ||||
| @@ -1,61 +0,0 @@ | ||||
| //  (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, | ||||
| //  sell and distribute this software is granted provided this | ||||
| //  copyright notice appears in all copies. This software is provided | ||||
| //  "as is" without express or implied warranty, and with no claim as | ||||
| //  to its suitability for any purpose. | ||||
| // | ||||
| // This is an example demonstrating how to use the tie() function. | ||||
| // The purpose of tie() is to make it easiery to deal with std::pair | ||||
| // return values. | ||||
| // | ||||
| // Contributed by Jeremy Siek | ||||
| // | ||||
| // Sample output | ||||
| // | ||||
| // 3 successfully inserted. | ||||
| // 9 was already in the set. | ||||
| // There were 2 occurances of 4. | ||||
|  | ||||
| #include <set> | ||||
| #include <algorithm> | ||||
| #include <iostream> | ||||
| #include <boost/utility.hpp> | ||||
|  | ||||
| int | ||||
| main(int, char*[]) | ||||
| { | ||||
|   { | ||||
|     typedef std::set<int> SetT; | ||||
|     SetT::iterator i, end; | ||||
|     bool inserted; | ||||
|      | ||||
|     int vals[5] = { 5, 2, 4, 9, 1 }; | ||||
|     SetT s(vals, vals + 5); | ||||
|      | ||||
|     // Using tie() with a return value of pair<iterator,bool> | ||||
|  | ||||
|     int new_vals[2] = { 3, 9 }; | ||||
|  | ||||
|     for (int k = 0; k < 2; ++k) { | ||||
|       boost::tie(i,inserted) = s.insert(new_vals[k]); | ||||
|       if (!inserted) | ||||
| 	std::cout << *i << " was already in the set." << std::endl; | ||||
|       else | ||||
| 	std::cout << *i << " successfully inserted." << std::endl;     | ||||
|     } | ||||
|   }     | ||||
|   { | ||||
|     int* i, *end; | ||||
|     int vals[6] = { 5, 2, 4, 4, 9, 1 }; | ||||
|     std::sort(vals, vals + 6); | ||||
|  | ||||
|     // Using tie() with a return value of pair<iterator,iterator> | ||||
|  | ||||
|     boost::tie(i,end) = std::equal_range(vals, vals + 6, 4); | ||||
|     std::cout << "There were " << std::distance(i,end) | ||||
| 	      << " occurances of " << *i << "." << std::endl; | ||||
|     // Footnote: of course one would normally just use std::count() | ||||
|     // to get this information, but that would spoil the example :) | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
| @@ -1,215 +0,0 @@ | ||||
| <html> | ||||
|  | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | ||||
| <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> | ||||
| <meta name="ProgId" content="FrontPage.Editor.Document"> | ||||
| <title>Transform Iterator Adaptor Documentation</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000"> | ||||
|  | ||||
| <img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" | ||||
| align="center" width="277" height="86"> | ||||
|  | ||||
| <h1>Transform Iterator Adaptor</h1> | ||||
|  | ||||
| Defined in header | ||||
| <a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a> | ||||
|  | ||||
| <p> | ||||
| The transform iterator adaptor augments an iterator by applying some | ||||
| function object to the result of dereferencing the iterator. Another | ||||
| words, the <tt>operator*</tt> of the transform iterator first | ||||
| dereferences the base iterator, passes the result of this to the | ||||
| function object, and then returns the result. The following | ||||
| <b>pseudo-code</b> shows the basic idea: | ||||
|  | ||||
| <pre> | ||||
|   value_type transform_iterator::operator*() const { | ||||
|     return this->f(*this->base_iterator); | ||||
|   } | ||||
| </pre> | ||||
|  | ||||
| All of the other operators of the transform iterator behave in the | ||||
| same fashion as those of the base iterator. | ||||
|  | ||||
|  | ||||
| <h2>Synopsis</h2> | ||||
|  | ||||
| <pre> | ||||
| namespace boost { | ||||
|   template <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. | ||||
|  | ||||
| <p> | ||||
| <PRE> | ||||
| #include <functional> | ||||
| #include <iostream> | ||||
| #include <boost/iterator_adaptors.hpp> | ||||
|  | ||||
| int | ||||
| main(int, char*[]) | ||||
| { | ||||
|   int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; | ||||
|  | ||||
|   typedef std::binder1st< std::multiplies<int> > Function; | ||||
|   typedef boost::transform_iterator_generator<Function, int*>::type doubling_iterator; | ||||
|  | ||||
|   doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)), | ||||
|     i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2)); | ||||
|  | ||||
|   std::cout << "multiplying the array by 2:" << std::endl; | ||||
|   while (i != i_end) | ||||
|     std::cout << *i++ << " "; | ||||
|   std::cout << std::endl; | ||||
|  | ||||
|   // 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.</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="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, std::bind1st(std::plus<int>(), 4)), | ||||
| 	    boost::make_transform_iterator(x + N, std::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 -->16 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14385" --></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> | ||||
| @@ -1,44 +0,0 @@ | ||||
| // (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and | ||||
| // distribute this software is granted provided this copyright notice appears | ||||
| // in all copies. This software is provided "as is" without express or implied | ||||
| // warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
|  | ||||
| #include <functional> | ||||
| #include <algorithm> | ||||
| #include <iostream> | ||||
| #include <boost/iterator_adaptors.hpp> | ||||
|  | ||||
| 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 std::binder1st< std::multiplies<int> > Function; | ||||
|   typedef boost::transform_iterator_generator<Function, int*>::type doubling_iterator; | ||||
|  | ||||
|   doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)), | ||||
|     i_end(x + N, std::bind1st(std::multiplies<int>(), 2)); | ||||
|  | ||||
|   std::cout << "multiplying the array by 2:" << std::endl; | ||||
|   while (i != i_end) | ||||
|     std::cout << *i++ << " "; | ||||
|   std::cout << std::endl; | ||||
|  | ||||
|   std::cout << "adding 4 to each element in the array:" << std::endl; | ||||
|  | ||||
|   std::copy(boost::make_transform_iterator(x, std::bind1st(std::plus<int>(), 4)), | ||||
| 	    boost::make_transform_iterator(x + N, std::bind1st(std::plus<int>(), 4)), | ||||
| 	    std::ostream_iterator<int>(std::cout, " ")); | ||||
|   std::cout << std::endl; | ||||
|    | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										104
									
								
								utility.htm
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								utility.htm
									
									
									
									
									
								
							| @@ -1,104 +0,0 @@ | ||||
| <html> | ||||
|  | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | ||||
| <title>Header boost/utility.hpp Documentation</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000"> | ||||
|  | ||||
| <h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" WIDTH="277" HEIGHT="86">Header | ||||
| <a href="../../boost/utility.hpp">boost/utility.hpp</a></h1> | ||||
|  | ||||
| <p>The entire contents of the header <code><a href="../../boost/utility.hpp"><boost/utility.hpp></a></code> | ||||
|  are in <code>namespace boost</code>.</p> | ||||
|  | ||||
| <h2>Contents</h2> | ||||
|  | ||||
| <ul> | ||||
|   <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> <a name="functions next">Function</a> templates next() and prior()</h2> | ||||
|  | ||||
| <p>Certain data types, such as the C++ Standard Library's forward and | ||||
| bidirectional iterators, do not provide addition and subtraction via operator+() | ||||
| or operator-().  This means that non-modifying computation of the next or | ||||
| prior value requires a temporary, even though operator++() or operator--() is | ||||
| provided.  It also means that writing code like <code>itr+1</code> inside a | ||||
| template restricts the iterator category to random access iterators.</p> | ||||
|  | ||||
| <p>The next() and prior() functions provide a simple way around these problems:</p> | ||||
|  | ||||
| <blockquote> | ||||
|  | ||||
| <pre>template <class T> | ||||
| T next(T x) { return ++x; } | ||||
|  | ||||
| template <class X> | ||||
| T prior(T x) { return --x; }</pre> | ||||
|  | ||||
| </blockquote> | ||||
|  | ||||
| <p>Usage is simple:</p> | ||||
|  | ||||
| <blockquote> | ||||
|  | ||||
| <pre>const std::list<T>::iterator p = get_some_iterator(); | ||||
| const std::list<T>::iterator prev = boost::prior(p);</pre> | ||||
|  | ||||
| </blockquote> | ||||
|  | ||||
| <p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.</p> | ||||
|  | ||||
| <h2><a name="Class noncopyable">Class noncopyable</a></h2> | ||||
|  | ||||
| <p>Class <strong>noncopyable</strong> is a base class.  Derive your own class from <strong>noncopyable</strong> | ||||
| when you want to prohibit copy construction and copy assignment.</p> | ||||
|  | ||||
| <p>Some objects, particularly those which hold complex resources like files or | ||||
| network connections, have no sensible copy semantics.  Sometimes there are | ||||
| possible copy semantics, but these would be of very limited usefulness and be | ||||
| very difficult to implement correctly.  Sometimes you're implementing a class that doesn't need to be copied | ||||
| just yet and you don't want to take the time to write the appropriate functions.  | ||||
| Deriving from <b> noncopyable</b> will prevent the otherwise implicitly-generated | ||||
| functions (which don't have the proper semantics) from becoming a trap for other programmers.</p> | ||||
|  | ||||
| <p>The traditional way to deal with these is to declare a private copy constructor and copy assignment, and then | ||||
| document why this is done.  But deriving from <b>noncopyable</b> is simpler | ||||
| and clearer, and doesn't require additional documentation.</p> | ||||
|  | ||||
| <p>The program <a href="noncopyable_test.cpp">noncopyable_test.cpp</a> can be | ||||
| used to verify class <b>noncopyable</b> works as expected. It has have been run successfully under | ||||
| GCC 2.95, Metrowerks | ||||
| CodeWarrior 5.0, and Microsoft Visual C++ 6.0 sp 3.</p> | ||||
|  | ||||
| <p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.</p> | ||||
|  | ||||
| <h3>Example</h3> | ||||
| <blockquote> | ||||
|   <pre>// inside one of your own headers ... | ||||
| #include <boost/utility.hpp> | ||||
|  | ||||
| class ResourceLadenFileSystem : boost::noncopyable { | ||||
| ...</pre> | ||||
| </blockquote> | ||||
|  | ||||
| <h3>Rationale</h3> | ||||
| <p>Class noncopyable has protected constructor and destructor members to | ||||
| emphasize that it is to be used only as a base class.  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> | ||||
| <hr> | ||||
| <p>Revised  <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan | ||||
| -->16 February, 2001<!--webbot bot="Timestamp" endspan i-checksum="40407" | ||||
| --> | ||||
| </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> | ||||
		Reference in New Issue
	
	Block a user