mirror of
				https://github.com/boostorg/utility.git
				synced 2025-10-20 20:15:30 +02:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			boost-1.34
			...
			svn-branch
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 41cfcb972d | 
							
								
								
									
										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="../../boost.png"  | ||||
|      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/tech/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>  | ||||
							
								
								
									
										648
									
								
								Collection.html
									
									
									
									
									
								
							
							
						
						
									
										648
									
								
								Collection.html
									
									
									
									
									
								
							| @@ -1,648 +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>Collection</Title> | ||||
| </HEAD> | ||||
|  | ||||
| <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"  | ||||
| 	ALINK="#ff0000">  | ||||
| <h1> | ||||
|    <img src="../../boost.png" alt="boost logo" | ||||
|     width="277" align="middle" height="86"> | ||||
|    <br>Collection | ||||
| </h1> | ||||
|  | ||||
| <h3>Description</h3> | ||||
|  | ||||
| A Collection is a <i>concept</i> similar to the STL <a | ||||
| href="http://www.sgi.com/tech/stl/Container.html">Container</a> | ||||
| concept.  A Collection provides iterators for accessing a range of | ||||
| elements and provides information about the number of elements in the | ||||
| Collection.  However, a Collection has fewer requirements than a | ||||
| Container. The motivation for the Collection concept is that there are | ||||
| many useful Container-like types that do not meet the full | ||||
| requirements of Container, and many algorithms that can be written | ||||
| with this reduced set of requirements. To summarize the reduction | ||||
| in requirements: | ||||
|  | ||||
| <UL> | ||||
| <LI>It is not required to "own" its elements: the lifetime | ||||
| of an element in a Collection does not have to match the lifetime of | ||||
| the Collection object, though the lifetime of the element should cover | ||||
| the lifetime of the Collection object. | ||||
| <LI>The semantics of copying a Collection object is not defined (it | ||||
| could be a deep or shallow copy or not even support copying).  | ||||
| <LI>The associated reference type of a Collection does | ||||
| not have to be a real C++ reference. | ||||
| </UL> | ||||
|  | ||||
|  | ||||
| Because of the reduced requirements, some care must be taken when | ||||
| writing code that is meant to be generic for all Collection types. | ||||
| In particular, a Collection object should be passed by-reference | ||||
| since assumptions can not be made about the behaviour of the | ||||
| copy constructor. | ||||
|  | ||||
| <p> | ||||
|  | ||||
| <h3>Associated types</h3> | ||||
|  | ||||
| <Table border> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Value type | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>X::value_type</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| The type of the object stored in a Collection.   | ||||
| If the Collection is <i>mutable</i> then | ||||
| the value type must be <A | ||||
| href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</A>. | ||||
| Otherwise the value type must be <a href="./CopyConstructible.html">CopyConstructible</a>. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Iterator type | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>X::iterator</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| The type of iterator used to iterate through a Collection's | ||||
|    elements.  The iterator's value type is expected to be the | ||||
|    Collection's value type.  A conversion | ||||
|    from the iterator type to the const iterator type must exist. | ||||
|    The iterator type must be an <A href="http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</A>. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Const iterator type | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>X::const_iterator</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| A type of iterator that may be used to examine, but not to modify, | ||||
|    a Collection's elements. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Reference type | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>X::reference</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| A type that behaves like a reference to the Collection's value type. | ||||
| <a href="#1">[1]</a> | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Const reference type | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>X::const_reference</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| A type that behaves like a const reference to the Collection's value type. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Pointer type | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>X::pointer</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| A type that behaves as a pointer to the Collection's value type. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Distance type | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>X::difference_type</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| A signed integral type used to represent the distance between two | ||||
|    of the Collection's iterators.  This type must be the same as  | ||||
|    the iterator's distance type. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Size type | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>X::size_type</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| An unsigned integral type that can represent any nonnegative value | ||||
|    of the Collection's distance type. | ||||
| </TD> | ||||
| </tr> | ||||
| </table> | ||||
| <h3>Notation</h3> | ||||
| <Table> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| <tt>X</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| A type that is a model of Collection. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| <tt>a</tt>, <tt>b</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Object of type <tt>X</tt>. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| <tt>T</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| The value type of <tt>X</tt>. | ||||
| </TD> | ||||
| </tr> | ||||
| </table> | ||||
|  | ||||
| <h3>Valid expressions</h3> | ||||
|  | ||||
| The following expressions must be valid. | ||||
| <p> | ||||
|  | ||||
| <Table border> | ||||
| <TR> | ||||
| <TH> | ||||
| Name | ||||
| </TH> | ||||
| <TH> | ||||
| Expression | ||||
| </TH> | ||||
| <TH> | ||||
| Return type | ||||
| </TH> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Beginning of range | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.begin()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>iterator</tt> if <tt>a</tt> is mutable, <tt>const_iterator</tt> otherwise | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| End of range | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.end()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>iterator</tt> if <tt>a</tt> is mutable, <tt>const_iterator</tt> otherwise | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Size | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.size()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>size_type</tt> | ||||
| </TD> | ||||
| </TR> | ||||
| <!-- | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Maximum size | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.max_size()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>size_type</tt> | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| --> | ||||
| <TD VAlign=top> | ||||
| Empty Collection | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.empty()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Convertible to <tt>bool</tt> | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Swap | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.swap(b)</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>void</tt> | ||||
| </TD> | ||||
| </tr> | ||||
| </table> | ||||
| <h3>Expression semantics</h3> | ||||
|  | ||||
| <Table border> | ||||
| <TR> | ||||
| <TH> | ||||
| Name | ||||
| </TH> | ||||
| <TH> | ||||
| Expression | ||||
| </TH> | ||||
| <TH> | ||||
| Semantics | ||||
| </TH> | ||||
| <TH> | ||||
| Postcondition | ||||
| </TH> | ||||
| </TR> | ||||
| <TD VAlign=top> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Beginning of range | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.begin()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Returns an iterator pointing to the first element in the Collection. | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.begin()</tt> is either dereferenceable or past-the-end.  It is | ||||
|    past-the-end if and only if <tt>a.size() == 0</tt>. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| End of range | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.end()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Returns an iterator pointing one past the last element in the | ||||
|    Collection. | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.end()</tt> is past-the-end. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Size | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.size()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Returns the size of the Collection, that is, its number of elements. | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.size() >= 0  | ||||
| </TD> | ||||
| </TR> | ||||
| <!-- | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Maximum size | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.max_size()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
|   | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Returns the largest size that this Collection can ever have. <A href="#8">[8]</A> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.max_size() >= 0 && a.max_size() >= a.size()</tt> | ||||
| </TD> | ||||
| </TR> | ||||
|  --> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Empty Collection | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.empty()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Equivalent to <tt>a.size() == 0</tt>.  (But possibly faster.) | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
|   | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Swap | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.swap(b)</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Equivalent to <tt>swap(a,b)</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
|   | ||||
| </TD> | ||||
| </tr> | ||||
| </table> | ||||
| <h3>Complexity guarantees</h3> | ||||
|  | ||||
| <tt>begin()</tt> and <tt>end()</tt> are amortized constant time. | ||||
| <P> | ||||
| <tt>size()</tt> is at most linear in the Collection's | ||||
| size. <tt>empty()</tt> is amortized constant time. | ||||
| <P> | ||||
| <tt>swap()</tt> is at most linear in the size of the two collections. | ||||
| <h3>Invariants</h3> | ||||
| <Table border> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Valid range | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| For any Collection <tt>a</tt>, <tt>[a.begin(), a.end())</tt> is a valid | ||||
|    range. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Range size | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.size()</tt> is equal to the distance from <tt>a.begin()</tt> to <tt>a.end()</tt>. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Completeness | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| An algorithm that iterates through the range <tt>[a.begin(), a.end())</tt> | ||||
|    will pass through every element of <tt>a</tt>. | ||||
| </TD> | ||||
| </tr> | ||||
| </table> | ||||
|  | ||||
|  | ||||
| <h3>Models</h3> | ||||
| <UL> | ||||
| <LI> <tt>array</tt> | ||||
| <LI> <tt>array_ptr</tt> | ||||
| <LI> <tt>vector<bool></tt> | ||||
| </UL> | ||||
|  | ||||
|  | ||||
| <h3>Collection Refinements</h3> | ||||
|  | ||||
| There are quite a few concepts that refine the Collection concept, | ||||
| similar to the concepts that refine the Container concept. Here | ||||
| is a brief overview of the refining concepts. | ||||
|  | ||||
| <h4>ForwardCollection</h4> | ||||
| The elements are arranged in some order that | ||||
| does not change spontaneously from one iteration to the next. As | ||||
| a result, a ForwardCollection is  | ||||
| <A | ||||
| href="http://www.sgi.com/tech/stl/EqualityComparable.html">EqualityComparable</A> | ||||
| and  | ||||
| <A | ||||
| href="http://www.sgi.com/tech/stl/LessThanComparable.html">LessThanComparable</A>. | ||||
| In addition, the iterator type of a ForwardCollection is a | ||||
| MultiPassInputIterator which is just an InputIterator with the added | ||||
| 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 ForwardCollection | ||||
| also has a <tt>front()</tt> method. | ||||
|  | ||||
| <p> | ||||
| <Table border> | ||||
| <TR> | ||||
| <TH> | ||||
| Name | ||||
| </TH> | ||||
| <TH> | ||||
| Expression | ||||
| </TH> | ||||
| <TH> | ||||
| Return type | ||||
| </TH> | ||||
| <TH> | ||||
| Semantics | ||||
| </TH> | ||||
| </TR> | ||||
|  | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Front | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.front()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>reference</tt> if <tt>a</tt> is mutable, <br> <tt>const_reference</tt> | ||||
| otherwise. | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Equivalent to <tt>*(a.begin())</tt>. | ||||
| </TD> | ||||
| </TR> | ||||
|  | ||||
| </table> | ||||
|  | ||||
|  | ||||
| <h4>ReversibleCollection</h4> | ||||
|  | ||||
| The container provides access to iterators that traverse in both | ||||
| directions (forward and reverse). The iterator type must meet all of | ||||
| the requirements of | ||||
| <a href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterator</a> | ||||
| except that the reference type does not have to be a real C++ | ||||
| reference. The ReversibleCollection adds the following requirements | ||||
| to those of ForwardCollection. | ||||
| <p> | ||||
|  | ||||
| <Table border> | ||||
| <TR> | ||||
| <TH> | ||||
| Name | ||||
| </TH> | ||||
| <TH> | ||||
| Expression | ||||
| </TH> | ||||
| <TH> | ||||
| Return type | ||||
| </TH> | ||||
| <TH> | ||||
| Semantics | ||||
| </TH> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Beginning of range | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.rbegin()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>reverse_iterator</tt> if <tt>a</tt> is mutable, | ||||
| <tt>const_reverse_iterator</tt> otherwise. | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Equivalent to <tt>X::reverse_iterator(a.end())</tt>. | ||||
| </TD> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| End of range | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.rend()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>reverse_iterator</tt> if <tt>a</tt> is mutable, | ||||
| <tt>const_reverse_iterator</tt> otherwise. | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Equivalent to <tt>X::reverse_iterator(a.begin())</tt>. | ||||
| </TD> | ||||
| </tr> | ||||
|  | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Back | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a.back()</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>reference</tt> if <tt>a</tt> is mutable, <br> <tt>const_reference</tt> | ||||
| otherwise. | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Equivalent to <tt>*(--a.end())</tt>. | ||||
| </TD> | ||||
| </TR> | ||||
|  | ||||
| </table> | ||||
|  | ||||
| <h4>SequentialCollection</h4> | ||||
|  | ||||
| The elements are arranged in a strict linear order. No extra methods | ||||
| are required. | ||||
|  | ||||
| <h4>RandomAccessCollection</h4> | ||||
|  | ||||
| The iterators of a RandomAccessCollection satisfy all of the | ||||
| requirements of <a | ||||
| href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a> | ||||
| except that the reference type does not have to be a real C++ | ||||
| reference. In addition, a RandomAccessCollection provides  | ||||
| an element access operator. | ||||
|  | ||||
| <p> | ||||
|  | ||||
| <Table border> | ||||
| <TR> | ||||
| <TH> | ||||
| Name | ||||
| </TH> | ||||
| <TH> | ||||
| Expression | ||||
| </TH> | ||||
| <TH> | ||||
| Return type | ||||
| </TH> | ||||
| <TH> | ||||
| Semantics | ||||
| </TH> | ||||
| </TR> | ||||
| <TR> | ||||
| <TD VAlign=top> | ||||
| Element Access | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>a[n]</tt> | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| <tt>reference</tt> if <tt>a</tt> is mutable, | ||||
| <tt>const_reference</tt> otherwise. | ||||
| </TD> | ||||
| <TD VAlign=top> | ||||
| Returns the nth element of the Collection. | ||||
| <tt>n</tt> must be convertible to <tt>size_type</tt>. | ||||
| Precondition: <tt>0 <= n < a.size()</tt>. | ||||
| </TD> | ||||
| </TR> | ||||
|  | ||||
| </table> | ||||
|  | ||||
| <h3>Notes</h3> | ||||
|  | ||||
| <P><A name="1">[1]</A>  | ||||
|  | ||||
| The reference type does not have to be a real C++ reference. The | ||||
| requirements of the reference type depend on the context within which | ||||
| the Collection is being used. Specifically it depends on the | ||||
| requirements the context places on the value type of the Collection. | ||||
| The reference type of the Collection must meet the same requirements | ||||
| as the value type. In addition, the reference objects must be | ||||
| equivalent to the value type objects in the collection (which is | ||||
| trivially true if they are the same object).  Also, in a mutable | ||||
| Collection, an assignment to the reference object must result in an | ||||
| assignment to the object in the Collection (again, which is trivially | ||||
| true if they are the same object, but non-trivial if the reference | ||||
| type is a proxy class). | ||||
|  | ||||
| <h3>See also</h3> | ||||
| <A href="http://www.sgi.com/tech/stl/Container.html">Container</A> | ||||
|  | ||||
|  | ||||
| <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 and C++ Library & Compiler Group/SGI (<A HREF="mailto:jsiek@engr.sgi.com">jsiek@engr.sgi.com</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>Copy Constructible</Title> | ||||
| </HEAD> | ||||
| <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"  | ||||
|         ALINK="#ff0000">  | ||||
| <IMG SRC="../../boost.png"  | ||||
|      ALT="C++ Boost" width="277" height="86">  | ||||
| <!--end header--> | ||||
| <BR Clear> | ||||
| <H1>Copy Constructible</H1> | ||||
|  | ||||
| <h3>Description</h3> | ||||
| A type is Copy Constructible 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 Copy Constructible | ||||
| </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/tech/stl/DefaultConstructible.html">Default Constructible</A> | ||||
| and  | ||||
| <A hrefa="./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="../../boost.png"  | ||||
|      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/tech/stl/EqualityComparable.html">EqualityComparable</A>, <A href="http://www.sgi.com/tech/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="../../boost.png"  | ||||
|      ALT="C++ Boost" width="277" height="86">  | ||||
|  | ||||
| <BR Clear> | ||||
|  | ||||
| <H2> | ||||
| <A NAME="concept:MultiPassInputIterator"></A> | ||||
| Multi-Pass Input Iterator | ||||
| </H2> | ||||
|  | ||||
| This concept is a refinement of <a | ||||
| href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>, | ||||
| adding the requirements that the iterator can be used to make multiple | ||||
| passes through a range, and that if <TT>it1 == it2</TT> and | ||||
| <TT>it1</TT> is dereferenceable then <TT>++it1 == ++it2</TT>. The | ||||
| Multi-Pass Input Iterator is very similar to the <a | ||||
| href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterator</a>. The | ||||
| only difference is that a <a | ||||
| href="http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterator</a> | ||||
| requires the <TT>reference</TT> type to be <TT>value_type&</TT>, whereas | ||||
| MultiPassInputIterator is like <a | ||||
| href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</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 Multi-Pass Input Iterator isn't the right | ||||
| solution. Do you also want to define Multi-Pass Bidirectionnal Iterator | ||||
| and Multi-Pass Random Access Iterator ? I don't, definitly. It only | ||||
| confuses the issue. The problem lies into the existing hierarchy of | ||||
| iterators, which mixes movabillity, modifiabillity and lvalue-ness, | ||||
| and these are clearly independant. | ||||
|  | ||||
| <p> The terms Forward, Bidirectionnal and Random Access are about | ||||
| movabillity and shouldn't be used to mean anything else.  In a | ||||
| completly orthogonal way, iterators can be immutable, mutable, or | ||||
| neither.  Lvalueness of iterators is also orthogonal with | ||||
| immutabillity.  With these clean concepts, your Multi-Pass Input Iterator | ||||
| is just called a Forward Iterator. | ||||
|  | ||||
| <p>                 | ||||
| Other translations are:<br> | ||||
| std::Forward Iterator -> ForwardIterator & Lvalue Iterator<br> | ||||
| std::Bidirectionnal Iterator -> Bidirectionnal Iterator & Lvalue Iterator<br> | ||||
| std::Random Access Iterator -> Random Access Iterator & Lvalue Iterator<br> | ||||
|  | ||||
| <p> | ||||
| Note that in practice the only operation not allowed on my  | ||||
| Forward Iterator which is allowed on std::Forward Iterator is  | ||||
| <tt>&*it</tt>. I think that <tt>&*</tt> is rarely needed in generic code. | ||||
|  | ||||
| <p> | ||||
| 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 Forward Iterator. The right course | ||||
| of action is to get Forward Iterator, etc. changed in the C++ standard. | ||||
| Once that is done we can drop Multi-Pass Input Iterator. | ||||
|  | ||||
|  | ||||
| <br> | ||||
| <HR> | ||||
| <TABLE> | ||||
| <TR valign=top> | ||||
| <TD nowrap>Copyright © 2000</TD><TD> | ||||
| <a HREF="../../people/jeremy_siek.htm">Jeremy Siek</a>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>) | ||||
| </TD></TR></TABLE> | ||||
|  | ||||
| </BODY> | ||||
| </HTML>  | ||||
| @@ -1,158 +0,0 @@ | ||||
| <HTML> | ||||
| <Head> | ||||
| <Title>OptionalPointee Concept</Title> | ||||
| </HEAD> | ||||
| <BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"  | ||||
|         ALINK="#ff0000">  | ||||
| <IMG SRC="../../boost.png"  | ||||
|      ALT="C++ Boost" width="277" height="86">  | ||||
| <!--end header--> | ||||
| <BR Clear> | ||||
| <H1>Concept: OptionalPointee</H1> | ||||
|  | ||||
| <h3>Description</h3> | ||||
| A type is a model of <i>OptionalPointee</i> if it points to (or refers to) a value  | ||||
| that may not exist. That is, if it has a <b>pointee</b> which might be <b>valid</b> | ||||
| (existent) or <b>invalid</b> (inexistent); and it is possible to test whether the  | ||||
| pointee is valid or not. | ||||
| This model does <u>not</u> imply pointer semantics: i.e., it does not imply shallow copy nor | ||||
| aliasing. | ||||
| <h3>Notation</h3> | ||||
| <Table> | ||||
|   <TR> | ||||
|     <TD VAlign=top> <tt>T</tt> </TD> | ||||
|     <TD VAlign=top> is a type that is a model of OptionalPointee</TD> | ||||
|   </TR> | ||||
|   <TR> | ||||
|     <TD VAlign=top> <tt>t</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>Value Access</TD> | ||||
|     <TD VAlign=top> <tt>*t</tt></TD> | ||||
|     <TD VAlign=top> <tt>T&</tt></TD> | ||||
|     <TD VAlign=top>If the pointee is valid returns a reference to | ||||
|       the pointee.<br> | ||||
|       If the pointee is invalid the result is <i>undefined</i>.</TD> | ||||
|     <TD VAlign=top> </TD> | ||||
|   </TR> | ||||
|   <TR> | ||||
|     <TD VAlign=top>Value Access</TD> | ||||
|     <TD VAlign=top> <tt>t-><i>xyz</i></tt></TD> | ||||
|     <TD VAlign=top> <tt>T*</tt></TD> | ||||
|     <TD VAlign=top>If the pointee is valid returns a builtin pointer to the pointee.<br> | ||||
|       If the pointee is invalid the result is <i>undefined</i> (It might not even return NULL).<br> | ||||
|     </TD> | ||||
|     <TD VAlign=top> </TD> | ||||
|   </TR> | ||||
|   <TR> | ||||
|     <TD VAlign=top>Validity Test</TD> | ||||
|     <TD VAlign=top> <tt>t</tt><br> | ||||
|       <tt>t != 0</tt><br> | ||||
|       <tt>!!t</tt> | ||||
|      </TD> | ||||
|     <TD VAlign=top> bool </TD> | ||||
|     <TD VAlign=top>If the pointee is valid returns true.<br> | ||||
|       If the pointee is invalid returns false.</TD> | ||||
|     <TD VAlign=top></TD> | ||||
|   </TR> | ||||
|   <TR> | ||||
|     <TD VAlign=top>Invalidity Test</TD> | ||||
|     <TD VAlign=top> <tt>t == 0</tt><br> | ||||
|                     <tt>!t</tt> | ||||
|     </TD> | ||||
|     <TD VAlign=top> bool </TD> | ||||
|     <TD VAlign=top>If the pointee is valid returns false.<br> | ||||
|       If the pointee is invalid returns true.</TD> | ||||
|     <TD VAlign=top></TD> | ||||
|   </TR> | ||||
| </table> | ||||
|  | ||||
|  | ||||
| <h3>Models</h3> | ||||
|  | ||||
| <UL> | ||||
|   <LI><tt>pointers, both builtin and smart.</tt> | ||||
|   <LI><tt>boost::optional<></tt> | ||||
| </UL> | ||||
|  | ||||
| <HR> | ||||
| <h3>OptionalPointee and relational operations</h3> | ||||
| <p>This concept does not define any particular semantic for relational operations, therefore, | ||||
| a type which models this concept might have either shallow or deep relational semantics.<br> | ||||
| For instance, pointers, which are models of OptionalPointee, have shallow relational operators: | ||||
| comparisons of pointers do not involve comparisons of pointees. | ||||
| This makes sense for pointers because they have shallow copy semantics.<br> | ||||
| But boost::optional<T>, on the other hand, which is also a model of OptionalPointee, has | ||||
| deep-copy and deep-relational semantics.<br> | ||||
| If generic code is written for this concept, it is important not to use relational | ||||
| operators directly because the semantics might be different depending on the actual type.<br> | ||||
| Still, the concept itsef can be used to define <i>deep</i> relational tests that can | ||||
| be used in generic code with any type which models OptionalPointee:</p> | ||||
| <a name="equal"></a> | ||||
| <p><u>Equivalence relation:</u></p> | ||||
| <pre>template<class OptionalPointee> | ||||
| inline | ||||
| bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y ) | ||||
| { | ||||
|   return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ; | ||||
| } | ||||
| template<class OptionalPointee> | ||||
| struct equal_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool> | ||||
| { | ||||
|   bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const | ||||
|     { return equal_pointees(x,y) ; } | ||||
| } ; | ||||
| </pre> | ||||
| <p>The preceding generic function and function object have the following semantics:<br> | ||||
| If both <b>x</b> and <b>y</b> have valid pointees, it compares values via <code>(*x == *y)</code>.<br> | ||||
| If only one has a valid pointee, returns <code>false</code>.<br> | ||||
| If both have invalid pointees, returns <code>true</code>.</p> | ||||
| <a name="less"></a> | ||||
| <p><u>Less-than relation:</u></p> | ||||
| <pre>template<class OptionalPointee> | ||||
| inline | ||||
| bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y ) | ||||
| { | ||||
|   return !y ? false : ( !x ? true : (*x) < (*y) ) ; | ||||
| } | ||||
| template<class OptionalPointee> | ||||
| struct less_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool> | ||||
| { | ||||
|   bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const | ||||
|     { return less_pointees(x,y) ; } | ||||
| } ; | ||||
| </pre> | ||||
| <p>The preceding generic function and function object have the following semantics:<br> | ||||
| If <b>y</b> has an invalid pointee, returns <code>false</code>.<br> | ||||
| Else, if <b>x</b> has an invalid pointee, returns <code>true</code>.<br> | ||||
| Else, ( <b>x</b> and <b>y</b> have valid pointees), compares values via <code>(*x <  | ||||
| *y).</code></p> | ||||
| <p><br> | ||||
| All these functions and function  | ||||
| objects are is implemented in <a href="../../boost/utility/compare_pointees.hpp">compare_pointees.hpp</a></p> | ||||
| <p>Notice that OptionalPointee does not imply aliasing (and optional<> for instance does not alias); | ||||
| so direct usage of relational operators with the implied aliasing of shallow semantics | ||||
| -as with pointers- should not be used with generic code written for this concept.</p> | ||||
|  | ||||
| <br> | ||||
| <HR> | ||||
| <TABLE> | ||||
| <TR valign=top> | ||||
| <TD nowrap>Copyright © 2003</TD><TD> | ||||
| <A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>, | ||||
| based on the original concept developed by Augustus Saunders. | ||||
| </TD></TR></TABLE> | ||||
|  | ||||
| </BODY> | ||||
| </HTML> | ||||
| @@ -1,94 +0,0 @@ | ||||
| // Copyright (C) 2002 Brad King (brad.king@kitware.com)  | ||||
| //                    Douglas Gregor (gregod@cs.rpi.edu) | ||||
| // | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| // For more information, see http://www.boost.org | ||||
|  | ||||
|  | ||||
| #include <boost/utility/addressof.hpp> | ||||
|  | ||||
| #if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) | ||||
| #pragma warning(push, 3) | ||||
| #endif | ||||
|  | ||||
| #include <iostream> | ||||
|  | ||||
| #if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) | ||||
| #pragma warning(pop) | ||||
| #endif | ||||
|  | ||||
| #include <boost/detail/lightweight_test.hpp> | ||||
|  | ||||
| template<class T> void scalar_test( T * = 0 ) | ||||
| { | ||||
|     T* px = new T(); | ||||
|  | ||||
|     T& x = *px; | ||||
|     BOOST_TEST( boost::addressof(x) == px ); | ||||
|  | ||||
|     const T& cx = *px; | ||||
|     const T* pcx = boost::addressof(cx); | ||||
|     BOOST_TEST( pcx == px ); | ||||
|  | ||||
|     volatile T& vx = *px; | ||||
|     volatile T* pvx = boost::addressof(vx); | ||||
|     BOOST_TEST( pvx == px ); | ||||
|  | ||||
|     const volatile T& cvx = *px; | ||||
|     const volatile T* pcvx = boost::addressof(cvx); | ||||
|     BOOST_TEST( pcvx == px ); | ||||
|  | ||||
|     delete px; | ||||
| } | ||||
|  | ||||
| template<class T> void array_test( T * = 0 ) | ||||
| { | ||||
|     T nrg[3] = {1,2,3}; | ||||
|     T (*pnrg)[3] = &nrg; | ||||
|     BOOST_TEST( boost::addressof(nrg) == pnrg ); | ||||
|  | ||||
|     T const cnrg[3] = {1,2,3}; | ||||
|     T const (*pcnrg)[3] = &cnrg; | ||||
|     BOOST_TEST( boost::addressof(cnrg) == pcnrg ); | ||||
| } | ||||
|  | ||||
| struct addressable | ||||
| { | ||||
|     addressable( int = 0 ) | ||||
|     { | ||||
|     } | ||||
| }; | ||||
|  | ||||
| struct useless_type {}; | ||||
|  | ||||
| class nonaddressable { | ||||
| public: | ||||
|  | ||||
|     nonaddressable( int = 0 ) | ||||
|     { | ||||
|     } | ||||
|  | ||||
|     void dummy(); // Silence GCC warning: all member of class are private | ||||
|  | ||||
| private: | ||||
|  | ||||
|     useless_type operator&() const; | ||||
| }; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     scalar_test<char>(); | ||||
|     scalar_test<int>(); | ||||
|     scalar_test<addressable>(); | ||||
|     scalar_test<nonaddressable>(); | ||||
|  | ||||
|     array_test<char>(); | ||||
|     array_test<int>(); | ||||
|     array_test<addressable>(); | ||||
|     array_test<nonaddressable>(); | ||||
|  | ||||
|     return boost::report_errors(); | ||||
| } | ||||
							
								
								
									
										57
									
								
								assert.html
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								assert.html
									
									
									
									
									
								
							| @@ -1,57 +0,0 @@ | ||||
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||||
| <html> | ||||
| 	<head> | ||||
| 		<title>Boost: assert.hpp documentation</title> | ||||
| 		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | ||||
| 	</head> | ||||
| 	<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%"> | ||||
| 		<table border="0" width="100%"> | ||||
| 			<tr> | ||||
| 				<td width="277"> | ||||
| 					<img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86"> | ||||
| 				</td> | ||||
| 				<td align="middle"> | ||||
| 					<h1>assert.hpp</h1> | ||||
| 				</td> | ||||
| 			</tr> | ||||
| 			<tr> | ||||
| 				<td colspan="2" height="64"> </td> | ||||
| 			</tr> | ||||
| 		</table> | ||||
| 		<p> | ||||
| 			The header <STRONG><boost/assert.hpp></STRONG> defines the macro <b>BOOST_ASSERT</b>,  | ||||
| 			which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG><cassert></STRONG>.  | ||||
| 			The macro is intended to be used in Boost libraries. | ||||
| 		</p> | ||||
| 		<P>By default, <tt>BOOST_ASSERT(expr)</tt> is equivalent to <tt>assert(expr)</tt>.</P> | ||||
| 		<P>When the macro <STRONG>BOOST_DISABLE_ASSERTS</STRONG> is defined when <STRONG><boost/assert.hpp></STRONG> | ||||
| 			is included, <tt>BOOST_ASSERT(expr)</tt> is defined as <tt>((void)0)</tt>. This  | ||||
| 			allows users to selectively disable <STRONG>BOOST_ASSERT</STRONG> without  | ||||
| 			affecting the definition of the standard <STRONG>assert</STRONG>.</P> | ||||
| 		<P>When the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG><boost/assert.hpp></STRONG> | ||||
| 			is included, <tt>BOOST_ASSERT(expr)</tt> evaluates <b>expr</b> and, if the  | ||||
| 			result is false, evaluates the expression</P> | ||||
| 		<P><tt>::boost::assertion_failed(#expr, <a href="current_function.html">BOOST_CURRENT_FUNCTION</a>,  | ||||
| 				__FILE__, __LINE__)</tt></P> | ||||
| 		<P><STRONG>assertion_failed</STRONG> is declared in <STRONG><boost/assert.hpp></STRONG> | ||||
| 			as</P> | ||||
| 		<pre> | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| void assertion_failed(char const * expr, char const * function, char const * file, long line); | ||||
|  | ||||
| } | ||||
| </pre> | ||||
| 		<p>but it is never defined. The user is expected to supply an appropriate  | ||||
| 			definition.</p> | ||||
| 		<P>As is the case with <STRONG><cassert></STRONG>, <STRONG><boost/assert.hpp></STRONG> | ||||
| 			can be included multiple times in a single translation unit. <STRONG>BOOST_ASSERT</STRONG> | ||||
| 			will be redefined each time as specified above.</P> | ||||
| 		<p><br> | ||||
| 			<small>Copyright <20> 2002 by Peter Dimov. 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.</small></p> | ||||
| 	</body> | ||||
| </html> | ||||
							
								
								
									
										109
									
								
								assert_test.cpp
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								assert_test.cpp
									
									
									
									
									
								
							| @@ -1,109 +0,0 @@ | ||||
| // | ||||
| //  assert_test.cpp - a test for boost/assert.hpp | ||||
| // | ||||
| //  Copyright (c) 2002 Peter Dimov and Multi Media Ltd. | ||||
| // | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
|  | ||||
| #include <boost/detail/lightweight_test.hpp> | ||||
|  | ||||
| #include <boost/assert.hpp> | ||||
|  | ||||
| void test_default() | ||||
| { | ||||
|     int x = 1; | ||||
|  | ||||
|     BOOST_ASSERT(1); | ||||
|     BOOST_ASSERT(x); | ||||
|     BOOST_ASSERT(x == 1); | ||||
|     BOOST_ASSERT(&x); | ||||
| } | ||||
|  | ||||
| #define BOOST_DISABLE_ASSERTS | ||||
| #include <boost/assert.hpp> | ||||
|  | ||||
| void test_disabled() | ||||
| { | ||||
|     int x = 1; | ||||
|  | ||||
|     BOOST_ASSERT(1); | ||||
|     BOOST_ASSERT(x); | ||||
|     BOOST_ASSERT(x == 1); | ||||
|     BOOST_ASSERT(&x); | ||||
|  | ||||
|     BOOST_ASSERT(0); | ||||
|     BOOST_ASSERT(!x); | ||||
|     BOOST_ASSERT(x == 0); | ||||
|  | ||||
|     void * p = 0; | ||||
|  | ||||
|     BOOST_ASSERT(p); | ||||
|  | ||||
|     // supress warnings | ||||
|     p = &x; | ||||
|     p = &p; | ||||
| } | ||||
|  | ||||
| #undef BOOST_DISABLE_ASSERTS | ||||
|  | ||||
| #define BOOST_ENABLE_ASSERT_HANDLER | ||||
| #include <boost/assert.hpp> | ||||
| #include <boost/config.hpp> | ||||
| #include <cstdio> | ||||
|  | ||||
| int handler_invoked = 0; | ||||
|  | ||||
| void boost::assertion_failed(char const * expr, char const * function, char const * file, long line) | ||||
| { | ||||
| #if !defined(BOOST_NO_STDC_NAMESPACE) | ||||
|     using std::printf; | ||||
| #endif | ||||
|  | ||||
|     printf("Expression: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n", expr, function, file, line); | ||||
|     ++handler_invoked; | ||||
| } | ||||
|  | ||||
| struct X | ||||
| { | ||||
|     static void f() | ||||
|     { | ||||
|         BOOST_ASSERT(0); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| void test_handler() | ||||
| { | ||||
|     int x = 1; | ||||
|  | ||||
|     BOOST_ASSERT(1); | ||||
|     BOOST_ASSERT(x); | ||||
|     BOOST_ASSERT(x == 1); | ||||
|     BOOST_ASSERT(&x); | ||||
|  | ||||
|     BOOST_ASSERT(0); | ||||
|     BOOST_ASSERT(!x); | ||||
|     BOOST_ASSERT(x == 0); | ||||
|  | ||||
|     void * p = 0; | ||||
|  | ||||
|     BOOST_ASSERT(p); | ||||
|  | ||||
|     X::f(); | ||||
|  | ||||
|     BOOST_ASSERT(handler_invoked == 5); | ||||
|     BOOST_TEST(handler_invoked == 5); | ||||
| } | ||||
|  | ||||
| #undef BOOST_ENABLE_ASSERT_HANDLER | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     test_default(); | ||||
|     test_disabled(); | ||||
|     test_handler(); | ||||
|  | ||||
|     return boost::report_errors(); | ||||
| } | ||||
| @@ -1,371 +0,0 @@ | ||||
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"> | ||||
| <html> | ||||
| <head> | ||||
| <title>Boost: Base-from-Member Idiom Documentation</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="white" link="blue" text="black" vlink="purple" alink="red">  | ||||
| <h1><img src="../../boost.png" alt="C++ Boost" align="middle" | ||||
| width="277" height="86">Base-from-Member Idiom</h1> | ||||
|  | ||||
| <p>The class template <code>boost::base_from_member</code> provides | ||||
| a workaround for a class that needs to initialize a base class with a | ||||
| member.  The class template is in <cite><a | ||||
| href="../../boost/utility/base_from_member.hpp">boost/utility/base_from_member.hpp</a></cite> | ||||
| which is included in <i><a href="../../boost/utility.hpp">boost/utility.hpp</a></i>.</p> | ||||
|  | ||||
| <p>There is test/example code in <cite><a | ||||
| href="base_from_member_test.cpp">base_from_member_test.cpp</a></cite>.</p> | ||||
|  | ||||
| <h2><a name="contents">Contents</a></h2> | ||||
|  | ||||
| <ul> | ||||
| 	<li><a href="#contents">Contents</a></li> | ||||
| 	<li><a href="#rationale">Rationale</a></li> | ||||
| 	<li><a href="#synopsis">Synopsis</a></li> | ||||
| 	<li><a href="#usage">Usage</a></li> | ||||
| 	<li><a href="#example">Example</a></li> | ||||
| 	<li><a href="#credits">Credits</a> | ||||
| 		<ul> | ||||
| 			<li><a href="#contributors">Contributors</a></li> | ||||
| 		</ul></li> | ||||
| </ul> | ||||
|  | ||||
| <h2><a name="rationale">Rationale</a></h2> | ||||
|  | ||||
| <p>When developing a class, sometimes a base class needs to be | ||||
| initialized with a member of the current class.  As a naïve | ||||
| example:</p> | ||||
|  | ||||
| <blockquote><pre> | ||||
| #include <streambuf>  <i>// for std::streambuf</i> | ||||
| #include <ostream>    <i>// for std::ostream</i> | ||||
|  | ||||
| class fdoutbuf | ||||
|     : public std::streambuf | ||||
| { | ||||
| public: | ||||
|     explicit fdoutbuf( int fd ); | ||||
|     //... | ||||
| }; | ||||
|  | ||||
| class fdostream | ||||
|     : public std::ostream | ||||
| { | ||||
| protected: | ||||
|     fdoutbuf buf; | ||||
| public: | ||||
|     explicit fdostream( int fd ) | ||||
|         : buf( fd ), std::ostream( &buf ) | ||||
|         {} | ||||
|     //... | ||||
| }; | ||||
| </pre></blockquote> | ||||
|  | ||||
| <p>This is undefined because C++'s initialization order mandates that | ||||
| the base class is initialized before the member it uses.  <a | ||||
| href="http://www.moocat.org">R. Samuel Klatchko</a> developed a way | ||||
| around this by using the initialization order in his favor.  Base | ||||
| classes are intialized in order of declaration, so moving the desired | ||||
| member to another base class, that is initialized before the desired | ||||
| base class, can ensure proper initialization.</p> | ||||
|  | ||||
| <p>A custom base class can be made for this idiom:</p> | ||||
|  | ||||
| <blockquote><pre> | ||||
| #include <streambuf>  <i>// for std::streambuf</i> | ||||
| #include <ostream>    <i>// for std::ostream</i> | ||||
|  | ||||
| class fdoutbuf | ||||
|     : public std::streambuf | ||||
| { | ||||
| public: | ||||
|     explicit fdoutbuf( int fd ); | ||||
|     //... | ||||
| }; | ||||
|  | ||||
| struct fdostream_pbase | ||||
| { | ||||
|     fdoutbuf sbuffer; | ||||
|  | ||||
|     explicit fdostream_pbase( int fd ) | ||||
|         : sbuffer( fd ) | ||||
|         {} | ||||
| }; | ||||
|  | ||||
| class fdostream | ||||
|     : private fdostream_pbase | ||||
|     , public std::ostream | ||||
| { | ||||
|     typedef fdostream_pbase  pbase_type; | ||||
|     typedef std::ostream     base_type; | ||||
|  | ||||
| public: | ||||
|     explicit fdostream( int fd ) | ||||
|         : pbase_type( fd ), base_type( &sbuffer ) | ||||
|         {} | ||||
|     //... | ||||
| }; | ||||
| </pre></blockquote> | ||||
|  | ||||
| <p>Other projects can use similar custom base classes.  The technique | ||||
| is basic enough to make a template, with a sample template class in | ||||
| this library.  The main template parameter is the type of the enclosed | ||||
| member.  The template class has several (explicit) constructor member | ||||
| templates, which implicitly type the constructor arguments and pass them | ||||
| to the member.  The template class uses implicit copy construction and | ||||
| assignment, cancelling them if the enclosed member is non-copyable.</p> | ||||
|  | ||||
| <p>Manually coding a base class may be better if the construction | ||||
| and/or copying needs are too complex for the supplied template class, | ||||
| or if the compiler is not advanced enough to use it.</p> | ||||
|  | ||||
| <p>Since base classes are unnamed, a class cannot have multiple (direct) | ||||
| base classes of the same type.  The supplied template class has an | ||||
| extra template parameter, an integer, that exists solely to provide type | ||||
| differentiation.  This parameter has a default value so a single use of a | ||||
| particular member type does not need to concern itself with the integer.</p> | ||||
|  | ||||
| <h2><a name="synopsis">Synopsis</a></h2> | ||||
|  | ||||
| <blockquote><pre> | ||||
| #ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY | ||||
| #define BOOST_BASE_FROM_MEMBER_MAX_ARITY  10 | ||||
| #endif | ||||
|  | ||||
| template < typename MemberType, int UniqueID = 0 > | ||||
| class boost::base_from_member | ||||
| { | ||||
| protected: | ||||
|     MemberType  member; | ||||
|  | ||||
|     base_from_member(); | ||||
|  | ||||
|     template< typename T1 > | ||||
|     explicit  base_from_member( T1 x1 ); | ||||
|  | ||||
|     template< typename T1, typename T2 > | ||||
|     base_from_member( T1 x1, T2 x2 ); | ||||
|  | ||||
|     //... | ||||
|  | ||||
|     template< typename T1, typename T2, typename T3, typename T4, | ||||
|      typename T5, typename T6, typename T7, typename T8, typename T9, | ||||
|      typename T10 > | ||||
|     base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, | ||||
|      T8 x8, T9 x9, T10 x10 ); | ||||
| }; | ||||
| </pre></blockquote> | ||||
|  | ||||
| <p>The class template has a first template parameter | ||||
| <var>MemberType</var> representing the type of the based-member. | ||||
| It has a last template parameter <var>UniqueID</var>, that is an | ||||
| <code>int</code>, to differentiate between multiple base classes that use | ||||
| the same based-member type.  The last template parameter has a default | ||||
| value of zero if it is omitted.  The class template has a protected | ||||
| data member called <var>member</var> that the derived class can use | ||||
| for later base classes (or itself).</p> | ||||
|  | ||||
| <p>There is a default constructor and several constructor member | ||||
| templates.  These constructor templates can take as many arguments | ||||
| (currently up to ten) as possible and pass them to a constructor of | ||||
| the data member.  Since C++ does not allow any way to explicitly state | ||||
| the template parameters of a templated constructor, make sure that | ||||
| the arguments are already close as possible to the actual type used in | ||||
| the data member's desired constructor.</p> | ||||
|  | ||||
| <p>The <var>BOOST_BASE_FROM_MEMBER_MAX_ARITY</var> macro constant specifies | ||||
| the maximum argument length for the constructor templates.  The constant | ||||
| may be overridden if more (or less) argument configurations are needed.  The | ||||
| constant may be read for code that is expandable like the class template and | ||||
| needs to maintain the same maximum size.  (Example code would be a class that | ||||
| uses this class template as a base class for a member with a flexible set of | ||||
| constructors.)</p> | ||||
|  | ||||
| <h2><a name="usage">Usage</a></h2> | ||||
|  | ||||
| <p>With the starting example, the <code>fdoutbuf</code> sub-object needs | ||||
| to be encapsulated in a base class that is inheirited before | ||||
| <code>std::ostream</code>.</p> | ||||
|  | ||||
| <blockquote><pre> | ||||
| #include <boost/utility/base_from_member.hpp> | ||||
|  | ||||
| #include <streambuf>  <i>// for std::streambuf</i> | ||||
| #include <ostream>    <i>// for std::ostream</i> | ||||
|  | ||||
| class fdoutbuf | ||||
|     : public std::streambuf | ||||
| { | ||||
| public: | ||||
|     explicit fdoutbuf( int fd ); | ||||
|     //... | ||||
| }; | ||||
|  | ||||
| class fdostream | ||||
|     : private boost::base_from_member<fdoutbuf> | ||||
|     , public std::ostream | ||||
| { | ||||
|     // Helper typedef's | ||||
|     typedef boost::base_from_member<fdoutbuf>  pbase_type; | ||||
|     typedef std::ostream                        base_type; | ||||
|  | ||||
| public: | ||||
|     explicit fdostream( int fd ) | ||||
|         : pbase_type( fd ), base_type( &member ) | ||||
|         {} | ||||
|     //... | ||||
| }; | ||||
| </pre></blockquote> | ||||
|  | ||||
| <p>The base-from-member idiom is an implementation detail, so it | ||||
| should not be visible to the clients (or any derived classes) of | ||||
| <code>fdostream</code>.  Due to the initialization order, the | ||||
| <code>fdoutbuf</code> sub-object will get initialized before the | ||||
| <code>std::ostream</code> sub-object does, making the former | ||||
| sub-object safe to use in the latter sub-object's construction.  Since the | ||||
| <code>fdoutbuf</code> sub-object of the final type is the only sub-object | ||||
| with the name "member," that name can be used | ||||
| unqualified within the final class.</p> | ||||
|  | ||||
| <h2><a name="example">Example</a></h2> | ||||
|  | ||||
| <p>The base-from-member class templates should commonly involve | ||||
| only one base-from-member sub-object, usually for attaching a | ||||
| stream-buffer to an I/O stream.  The next example demonstrates how | ||||
| to use multiple base-from-member sub-objects and the resulting | ||||
| qualification issues.</p> | ||||
|  | ||||
| <blockquote><pre> | ||||
| #include <boost/utility/base_from_member.hpp> | ||||
|  | ||||
| #include <cstddef>  <i>// for NULL</i> | ||||
|  | ||||
| struct an_int | ||||
| { | ||||
|     int  y; | ||||
|  | ||||
|     an_int( float yf ); | ||||
| }; | ||||
|  | ||||
| class switcher | ||||
| { | ||||
| public: | ||||
|     switcher(); | ||||
|     switcher( double, int * ); | ||||
|     //... | ||||
| }; | ||||
|  | ||||
| class flow_regulator | ||||
| { | ||||
| public: | ||||
|     flow_regulator( switcher &, switcher & ); | ||||
|     //... | ||||
| }; | ||||
|  | ||||
| template < unsigned Size > | ||||
| class fan | ||||
| { | ||||
| public: | ||||
|     explicit fan( switcher ); | ||||
|     //... | ||||
| }; | ||||
|  | ||||
| class system | ||||
|     : private boost::base_from_member<an_int> | ||||
|     , private boost::base_from_member<switcher> | ||||
|     , private boost::base_from_member<switcher, 1> | ||||
|     , private boost::base_from_member<switcher, 2> | ||||
|     , protected flow_regulator | ||||
|     , public fan<6> | ||||
| { | ||||
|     // Helper typedef's | ||||
|     typedef boost::base_from_member<an_int>       pbase0_type; | ||||
|     typedef boost::base_from_member<switcher>     pbase1_type; | ||||
|     typedef boost::base_from_member<switcher, 1>  pbase2_type; | ||||
|     typedef boost::base_from_member<switcher, 2>  pbase3_type; | ||||
|  | ||||
|     typedef flow_regulator  base1_type; | ||||
|     typedef fan<6>          base2_type; | ||||
|  | ||||
| public: | ||||
|     system( double x ); | ||||
|     //... | ||||
| }; | ||||
|  | ||||
| system::system( double x ) | ||||
|     : pbase0_type( 0.2 ) | ||||
|     , pbase1_type() | ||||
|     , pbase2_type( -16, &this->pbase0_type::member ) | ||||
|     , pbase3_type( x, static_cast<int *>(NULL) ) | ||||
|     , base1_type( pbase3_type::member, pbase1_type::member ) | ||||
|     , base2_type( pbase2_type::member ) | ||||
| { | ||||
|     //... | ||||
| } | ||||
| </pre></blockquote> | ||||
|  | ||||
| <p>The final class has multiple sub-objects with the name | ||||
| "member," so any use of that name needs qualification by | ||||
| a name of the appropriate base type.  (Using <code>typedef</code>s | ||||
| ease mentioning the base types.)  However, the fix introduces a new | ||||
| problem when a pointer is needed.  Using the address operator with | ||||
| a sub-object qualified with its class's name results in a pointer-to-member | ||||
| (here, having a type of <code>an_int boost::base_from_member<an_int, | ||||
| 0> :: *</code>) instead of a pointer to the member (having a type of | ||||
| <code>an_int *</code>).  The new problem is fixed by qualifying the | ||||
| sub-object with "<code>this-></code>," and is needed just | ||||
| for pointers, and not for references or values.</p> | ||||
|  | ||||
| <p>There are some argument conversions in the initialization.  The | ||||
| constructor argument for <code>pbase0_type</code> is converted from | ||||
| <code>double</code> to <code>float</code>.  The first constructor | ||||
| argument for <code>pbase2_type</code> is converted from <code>int</code> | ||||
| to <code>double</code>.  The second constructor argument for | ||||
| <code>pbase3_type</code> is a special case of necessary conversion; all | ||||
| forms of the null-pointer literal in C++ also look like compile-time | ||||
| integral expressions, so C++ always interprets such code as an integer | ||||
| when it has overloads that can take either an integer or a pointer.  The | ||||
| last conversion is necessary for the compiler to call a constructor form | ||||
| with the exact pointer type used in <code>switcher</code>'s constructor.</p> | ||||
|  | ||||
| <h2><a name="credits">Credits</a></h2> | ||||
|  | ||||
| <h3><a name="contributors">Contributors</a></h3> | ||||
|  | ||||
| <dl> | ||||
| 	<dt><a href="../../people/ed_brey.htm">Ed Brey</a> | ||||
| 	<dd>Suggested some interface changes. | ||||
|  | ||||
| 	<dt><a href="http://www.moocat.org">R. Samuel Klatchko</a> (<a | ||||
| 	href="mailto:rsk@moocat.org">rsk@moocat.org</a>, <a | ||||
| 	href="mailto:rsk@brightmail.com">rsk@brightmail.com</a>) | ||||
| 	<dd>Invented the idiom of how to use a class member for initializing | ||||
| 		a base class. | ||||
|  | ||||
| 	<dt><a href="../../people/dietmar_kuehl.htm">Dietmar Kuehl</a> | ||||
| 	<dd>Popularized the base-from-member idiom in his | ||||
| 		<a href="http://www.informatik.uni-konstanz.de/~kuehl/c++/iostream/">IOStream | ||||
| 		example classes</a>. | ||||
|  | ||||
| 	<dt>Jonathan Turkanis | ||||
| 	<dd>Supplied an implementation of generating the constructor templates that | ||||
| 		can be controlled and automated with macros.  The implementation uses | ||||
| 		the <a href="../preprocessor/">Preprocessor library</a>. | ||||
|  | ||||
| 	<dt><a href="../../people/daryle_walker.html">Daryle Walker</a> | ||||
| 	<dd>Started the library.  Contributed the test file <cite><a | ||||
| 		href="base_from_member_test.cpp">base_from_member_test.cpp</a></cite>. | ||||
| </dl> | ||||
|  | ||||
| <hr> | ||||
|  | ||||
| <p>Revised: 28 August 2004</p> | ||||
|  | ||||
| <p>Copyright 2001, 2003, 2004 Daryle Walker.  Use, modification, and distribution | ||||
| are subject to the Boost Software License, Version 1.0.  (See accompanying | ||||
| file <a href="../../LICENSE_1_0.txt">LICENSE_1_0.txt</a> or a copy at <<a | ||||
| href="http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt</a>>.)</p> | ||||
|  | ||||
| </body> | ||||
| </html> | ||||
| @@ -1,595 +0,0 @@ | ||||
| //  Boost test program for base-from-member class templates  -----------------// | ||||
|  | ||||
| //  Copyright 2001, 2003 Daryle Walker.  Use, modification, and distribution are | ||||
| //  subject to the Boost Software License, Version 1.0.  (See accompanying file | ||||
| //  LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.) | ||||
|  | ||||
| //  See <http://www.boost.org/libs/utility/> for the library's home page. | ||||
|  | ||||
| //  Revision History | ||||
| //  14 Jun 2003  Adjusted code for Boost.Test changes (Daryle Walker) | ||||
| //  29 Aug 2001  Initial Version (Daryle Walker) | ||||
|  | ||||
| #include <boost/test/minimal.hpp>  // for BOOST_CHECK, main | ||||
|  | ||||
| #include <boost/config.hpp>       // for BOOST_NO_MEMBER_TEMPLATES | ||||
| #include <boost/cstdlib.hpp>      // for boost::exit_success | ||||
| #include <boost/noncopyable.hpp>  // for boost::noncopyable | ||||
|  | ||||
| #include <boost/utility/base_from_member.hpp>  // for boost::base_from_member | ||||
|  | ||||
| #include <functional>  // for std::binary_function, std::less | ||||
| #include <iostream>    // for std::cout (std::ostream, std::endl indirectly) | ||||
| #include <set>         // for std::set | ||||
| #include <typeinfo>    // for std::type_info | ||||
| #include <utility>     // for std::pair, std::make_pair | ||||
| #include <vector>      // for std::vector | ||||
|  | ||||
|  | ||||
| // Control if extra information is printed | ||||
| #ifndef CONTROL_EXTRA_PRINTING | ||||
| #define CONTROL_EXTRA_PRINTING  1 | ||||
| #endif | ||||
|  | ||||
|  | ||||
| // A (sub)object can be identified by its memory location and its type. | ||||
| // Both are needed since an object can start at the same place as its | ||||
| // first base class subobject and/or contained subobject. | ||||
| typedef std::pair< void *, std::type_info const * >  object_id; | ||||
|  | ||||
| // Object IDs need to be printed | ||||
| std::ostream &  operator <<( std::ostream &os, object_id const &oi ); | ||||
|  | ||||
| // A way to generate an object ID | ||||
| template < typename T > | ||||
|   object_id  identify( T &obj ); | ||||
|  | ||||
| // A custom comparison type is needed | ||||
| struct object_id_compare | ||||
|     : std::binary_function<object_id, object_id, bool> | ||||
| { | ||||
|     bool  operator ()( object_id const &a, object_id const &b ) const; | ||||
|  | ||||
| };  // object_id_compare | ||||
|  | ||||
| // A singleton of this type coordinates the acknowledgements | ||||
| // of objects being created and used. | ||||
| class object_registrar | ||||
|     : private boost::noncopyable | ||||
| { | ||||
| public: | ||||
|  | ||||
|     #ifndef BOOST_NO_MEMBER_TEMPLATES | ||||
|     template < typename T > | ||||
|         void  register_object( T &obj ) | ||||
|             { this->register_object_imp( identify(obj) ); } | ||||
|     template < typename T, typename U > | ||||
|         void  register_use( T &owner, U &owned ) | ||||
|             { this->register_use_imp( identify(owner), identify(owned) ); } | ||||
|     template < typename T, typename U > | ||||
|         void  unregister_use( T &owner, U &owned ) | ||||
|             { this->unregister_use_imp( identify(owner), identify(owned) ); } | ||||
|     template < typename T > | ||||
|         void  unregister_object( T &obj ) | ||||
|             { this->unregister_object_imp( identify(obj) ); } | ||||
|     #endif | ||||
|  | ||||
|     void  register_object_imp( object_id obj ); | ||||
|     void  register_use_imp( object_id owner, object_id owned ); | ||||
|     void  unregister_use_imp( object_id owner, object_id owned ); | ||||
|     void  unregister_object_imp( object_id obj ); | ||||
|  | ||||
|     typedef std::set<object_id, object_id_compare>  set_type; | ||||
|  | ||||
|     typedef std::vector<object_id>  error_record_type; | ||||
|     typedef std::vector< std::pair<object_id, object_id> >  error_pair_type; | ||||
|  | ||||
|     set_type  db_; | ||||
|  | ||||
|     error_pair_type    defrauders_in_, defrauders_out_; | ||||
|     error_record_type  overeager_, overkilled_; | ||||
|  | ||||
| };  // object_registrar | ||||
|  | ||||
| // A sample type to be used by containing types | ||||
| class base_or_member | ||||
| { | ||||
| public: | ||||
|     explicit  base_or_member( int x = 1, double y = -0.25 ); | ||||
|              ~base_or_member(); | ||||
|  | ||||
| };  // base_or_member | ||||
|  | ||||
| // A sample type that uses base_or_member, used | ||||
| // as a base for the main demonstration classes | ||||
| class base_class | ||||
| { | ||||
| public: | ||||
|     explicit  base_class( base_or_member &x, base_or_member *y = 0, | ||||
|      base_or_member *z = 0 ); | ||||
|  | ||||
|     ~base_class(); | ||||
|  | ||||
| private: | ||||
|     base_or_member  *x_, *y_, *z_; | ||||
|  | ||||
| };  // base_class | ||||
|  | ||||
| // This bad class demonstrates the direct method of a base class needing | ||||
| // to be initialized by a member.  This is improper since the member | ||||
| // isn't initialized until after the base class. | ||||
| class bad_class | ||||
|     : public base_class | ||||
| { | ||||
| public: | ||||
|      bad_class(); | ||||
|     ~bad_class(); | ||||
|  | ||||
| private: | ||||
|     base_or_member  x_; | ||||
|  | ||||
| };  // bad_class | ||||
|  | ||||
| // The first good class demonstrates the correct way to initialize a | ||||
| // base class with a member.  The member is changed to another base | ||||
| // class, one that is initialized before the base that needs it. | ||||
| class good_class_1 | ||||
|     : private boost::base_from_member<base_or_member> | ||||
|     , public base_class | ||||
| { | ||||
|     typedef boost::base_from_member<base_or_member>  pbase_type; | ||||
|     typedef base_class                                base_type; | ||||
|  | ||||
| public: | ||||
|      good_class_1(); | ||||
|     ~good_class_1(); | ||||
|  | ||||
| };  // good_class_1 | ||||
|  | ||||
| // The second good class also demonstrates the correct way to initialize | ||||
| // base classes with other subobjects.  This class uses the other helpers | ||||
| // in the library, and shows the technique of using two base subobjects | ||||
| // of the "same" type. | ||||
| class good_class_2 | ||||
|     : private boost::base_from_member<base_or_member, 0> | ||||
|     , private boost::base_from_member<base_or_member, 1> | ||||
|     , private boost::base_from_member<base_or_member, 2> | ||||
|     , public base_class | ||||
| { | ||||
|     typedef boost::base_from_member<base_or_member, 0>  pbase_type0; | ||||
|     typedef boost::base_from_member<base_or_member, 1>  pbase_type1; | ||||
|     typedef boost::base_from_member<base_or_member, 2>  pbase_type2; | ||||
|     typedef base_class                                   base_type; | ||||
|  | ||||
| public: | ||||
|      good_class_2(); | ||||
|     ~good_class_2(); | ||||
|  | ||||
| };  // good_class_2 | ||||
|  | ||||
| // Declare/define the single object registrar | ||||
| object_registrar  obj_reg; | ||||
|  | ||||
|  | ||||
| // Main functionality | ||||
| int | ||||
| test_main( int , char * [] ) | ||||
| { | ||||
|     BOOST_CHECK( obj_reg.db_.empty() ); | ||||
|     BOOST_CHECK( obj_reg.defrauders_in_.empty() ); | ||||
|     BOOST_CHECK( obj_reg.defrauders_out_.empty() ); | ||||
|     BOOST_CHECK( obj_reg.overeager_.empty() ); | ||||
|     BOOST_CHECK( obj_reg.overkilled_.empty() ); | ||||
|  | ||||
|     // Make a separate block to examine pre- and post-effects | ||||
|     { | ||||
|         using std::cout; | ||||
|         using std::endl; | ||||
|  | ||||
|         bad_class  bc; | ||||
|         BOOST_CHECK( obj_reg.db_.size() == 3 ); | ||||
|         BOOST_CHECK( obj_reg.defrauders_in_.size() == 1 ); | ||||
|  | ||||
|         good_class_1  gc1; | ||||
|         BOOST_CHECK( obj_reg.db_.size() == 6 ); | ||||
|         BOOST_CHECK( obj_reg.defrauders_in_.size() == 1 ); | ||||
|  | ||||
|         good_class_2  gc2; | ||||
|         BOOST_CHECK( obj_reg.db_.size() == 11 ); | ||||
|         BOOST_CHECK( obj_reg.defrauders_in_.size() == 1 ); | ||||
|  | ||||
|         BOOST_CHECK( obj_reg.defrauders_out_.empty() ); | ||||
|         BOOST_CHECK( obj_reg.overeager_.empty() ); | ||||
|         BOOST_CHECK( obj_reg.overkilled_.empty() ); | ||||
|  | ||||
|         // Getting the addresses of the objects ensure | ||||
|         // that they're used, and not optimized away. | ||||
|         cout << "Object 'bc' is at " << &bc << '.' << endl; | ||||
|         cout << "Object 'gc1' is at " << &gc1 << '.' << endl; | ||||
|         cout << "Object 'gc2' is at " << &gc2 << '.' << endl; | ||||
|     } | ||||
|  | ||||
|     BOOST_CHECK( obj_reg.db_.empty() ); | ||||
|     BOOST_CHECK( obj_reg.defrauders_in_.size() == 1 ); | ||||
|     BOOST_CHECK( obj_reg.defrauders_out_.size() == 1 ); | ||||
|     BOOST_CHECK( obj_reg.overeager_.empty() ); | ||||
|     BOOST_CHECK( obj_reg.overkilled_.empty() ); | ||||
|  | ||||
|     return boost::exit_success; | ||||
| } | ||||
|  | ||||
|  | ||||
| // Print an object's ID | ||||
| std::ostream & | ||||
| operator << | ||||
| ( | ||||
|     std::ostream &     os, | ||||
|     object_id const &  oi | ||||
| ) | ||||
| { | ||||
|     // I had an std::ostringstream to help, but I did not need it since | ||||
|     // the program never screws around with formatting.  Worse, using | ||||
|     // std::ostringstream is an issue with some compilers. | ||||
|  | ||||
|     return os << '[' << ( oi.second ? oi.second->name() : "NOTHING" ) | ||||
|      << " at " << oi.first << ']'; | ||||
| } | ||||
|  | ||||
| // Get an object ID given an object | ||||
| template < typename T > | ||||
| inline | ||||
| object_id | ||||
| identify | ||||
| ( | ||||
|     T &  obj | ||||
| ) | ||||
| { | ||||
|     return std::make_pair( static_cast<void *>(&obj), &(typeid( obj )) ); | ||||
| } | ||||
|  | ||||
| // Compare two object IDs | ||||
| bool | ||||
| object_id_compare::operator () | ||||
| ( | ||||
|     object_id const &  a, | ||||
|     object_id const &  b | ||||
| ) const | ||||
| { | ||||
|     std::less<void *>  vp_cmp; | ||||
|     if ( vp_cmp(a.first, b.first) ) | ||||
|     { | ||||
|         return true; | ||||
|     } | ||||
|     else if ( vp_cmp(b.first, a.first) ) | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // object pointers are equal, compare the types | ||||
|         if ( a.second == b.second ) | ||||
|         { | ||||
|             return false; | ||||
|         } | ||||
|         else if ( !a.second ) | ||||
|         { | ||||
|             return true;   // NULL preceeds anything else | ||||
|         } | ||||
|         else if ( !b.second ) | ||||
|         { | ||||
|             return false;  // NULL preceeds anything else | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return a.second->before( *b.second ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Let an object register its existence | ||||
| void | ||||
| object_registrar::register_object_imp | ||||
| ( | ||||
|     object_id  obj | ||||
| ) | ||||
| { | ||||
|     if ( db_.count(obj) <= 0 ) | ||||
|     { | ||||
|         db_.insert( obj ); | ||||
|  | ||||
|         #if CONTROL_EXTRA_PRINTING | ||||
|         std::cout << "Registered " << obj << '.' << std::endl; | ||||
|         #endif | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         overeager_.push_back( obj ); | ||||
|  | ||||
|         #if CONTROL_EXTRA_PRINTING | ||||
|         std::cout << "Attempted to register a non-existant " << obj | ||||
|          << '.' << std::endl; | ||||
|         #endif | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Let an object register its use of another object | ||||
| void | ||||
| object_registrar::register_use_imp | ||||
| ( | ||||
|     object_id  owner, | ||||
|     object_id  owned | ||||
| ) | ||||
| { | ||||
|     if ( db_.count(owned) > 0 ) | ||||
|     { | ||||
|         // We don't care to record usage registrations | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         defrauders_in_.push_back( std::make_pair(owner, owned) ); | ||||
|  | ||||
|         #if CONTROL_EXTRA_PRINTING | ||||
|         std::cout << "Attempted to own a non-existant " << owned | ||||
|          << " by " << owner << '.' << std::endl; | ||||
|         #endif | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Let an object un-register its use of another object | ||||
| void | ||||
| object_registrar::unregister_use_imp | ||||
| ( | ||||
|     object_id  owner, | ||||
|     object_id  owned | ||||
| ) | ||||
| { | ||||
|     if ( db_.count(owned) > 0 ) | ||||
|     { | ||||
|         // We don't care to record usage un-registrations | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         defrauders_out_.push_back( std::make_pair(owner, owned) ); | ||||
|  | ||||
|         #if CONTROL_EXTRA_PRINTING | ||||
|         std::cout << "Attempted to disown a non-existant " << owned | ||||
|          << " by " << owner << '.' << std::endl; | ||||
|         #endif | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Let an object un-register its existence | ||||
| void | ||||
| object_registrar::unregister_object_imp | ||||
| ( | ||||
|     object_id  obj | ||||
| ) | ||||
| { | ||||
|     set_type::iterator const  i = db_.find( obj ); | ||||
|  | ||||
|     if ( i != db_.end() ) | ||||
|     { | ||||
|         db_.erase( i ); | ||||
|  | ||||
|         #if CONTROL_EXTRA_PRINTING | ||||
|         std::cout << "Unregistered " << obj << '.' << std::endl; | ||||
|         #endif | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         overkilled_.push_back( obj ); | ||||
|  | ||||
|         #if CONTROL_EXTRA_PRINTING | ||||
|         std::cout << "Attempted to unregister a non-existant " << obj | ||||
|          << '.' << std::endl; | ||||
|         #endif | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Macros to abstract the registration of objects | ||||
| #ifndef BOOST_NO_MEMBER_TEMPLATES | ||||
| #define PRIVATE_REGISTER_BIRTH(o)     obj_reg.register_object( (o) ) | ||||
| #define PRIVATE_REGISTER_DEATH(o)     obj_reg.unregister_object( (o) ) | ||||
| #define PRIVATE_REGISTER_USE(o, w)    obj_reg.register_use( (o), (w) ) | ||||
| #define PRIVATE_UNREGISTER_USE(o, w)  obj_reg.unregister_use( (o), (w) ) | ||||
| #else | ||||
| #define PRIVATE_REGISTER_BIRTH(o)     obj_reg.register_object_imp( \ | ||||
|  identify((o)) ) | ||||
| #define PRIVATE_REGISTER_DEATH(o)     obj_reg.unregister_object_imp( \ | ||||
|  identify((o)) ) | ||||
| #define PRIVATE_REGISTER_USE(o, w)    obj_reg.register_use_imp( identify((o)), \ | ||||
|  identify((w)) ) | ||||
| #define PRIVATE_UNREGISTER_USE(o, w)  obj_reg.unregister_use_imp( \ | ||||
|  identify((o)), identify((w)) ) | ||||
| #endif | ||||
|  | ||||
| // Create a base_or_member, with arguments to simulate member initializations | ||||
| base_or_member::base_or_member | ||||
| ( | ||||
|     int     x,  // = 1 | ||||
|     double  y   // = -0.25 | ||||
| ) | ||||
| { | ||||
|     PRIVATE_REGISTER_BIRTH( *this ); | ||||
|  | ||||
|     #if CONTROL_EXTRA_PRINTING | ||||
|     std::cout << "\tMy x-factor is " << x << " and my y-factor is " << y | ||||
|      << '.' << std::endl; | ||||
|     #endif | ||||
| } | ||||
|  | ||||
| // Destroy a base_or_member | ||||
| inline | ||||
| base_or_member::~base_or_member | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     PRIVATE_REGISTER_DEATH( *this ); | ||||
| } | ||||
|  | ||||
| // Create a base_class, registering any objects used | ||||
| base_class::base_class | ||||
| ( | ||||
|     base_or_member &  x, | ||||
|     base_or_member *  y,  // = 0 | ||||
|     base_or_member *  z   // = 0 | ||||
| ) | ||||
|     : x_( &x ), y_( y ), z_( z ) | ||||
| { | ||||
|     PRIVATE_REGISTER_BIRTH( *this ); | ||||
|  | ||||
|     #if CONTROL_EXTRA_PRINTING | ||||
|     std::cout << "\tMy x-factor is " << x_; | ||||
|     #endif | ||||
|  | ||||
|     PRIVATE_REGISTER_USE( *this, *x_ ); | ||||
|  | ||||
|     if ( y_ ) | ||||
|     { | ||||
|         #if CONTROL_EXTRA_PRINTING | ||||
|         std::cout << ", my y-factor is " << y_; | ||||
|         #endif | ||||
|  | ||||
|         PRIVATE_REGISTER_USE( *this, *y_ ); | ||||
|     } | ||||
|  | ||||
|     if ( z_ ) | ||||
|     { | ||||
|         #if CONTROL_EXTRA_PRINTING | ||||
|         std::cout << ", my z-factor is " << z_; | ||||
|         #endif | ||||
|  | ||||
|         PRIVATE_REGISTER_USE( *this, *z_ ); | ||||
|     } | ||||
|  | ||||
|     #if CONTROL_EXTRA_PRINTING | ||||
|     std::cout << '.' << std::endl; | ||||
|     #endif | ||||
| } | ||||
|  | ||||
| // Destroy a base_class, unregistering the objects it uses | ||||
| base_class::~base_class | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     PRIVATE_REGISTER_DEATH( *this ); | ||||
|  | ||||
|     #if CONTROL_EXTRA_PRINTING | ||||
|     std::cout << "\tMy x-factor was " << x_; | ||||
|     #endif | ||||
|  | ||||
|     PRIVATE_UNREGISTER_USE( *this, *x_ ); | ||||
|  | ||||
|     if ( y_ ) | ||||
|     { | ||||
|         #if CONTROL_EXTRA_PRINTING | ||||
|         std::cout << ", my y-factor was " << y_; | ||||
|         #endif | ||||
|  | ||||
|         PRIVATE_UNREGISTER_USE( *this, *y_ ); | ||||
|     } | ||||
|  | ||||
|     if ( z_ ) | ||||
|     { | ||||
|         #if CONTROL_EXTRA_PRINTING | ||||
|         std::cout << ", my z-factor was " << z_; | ||||
|         #endif | ||||
|  | ||||
|         PRIVATE_UNREGISTER_USE( *this, *z_ ); | ||||
|     } | ||||
|  | ||||
|     #if CONTROL_EXTRA_PRINTING | ||||
|     std::cout << '.' << std::endl; | ||||
|     #endif | ||||
| } | ||||
|  | ||||
| // Create a bad_class, noting the improper construction order | ||||
| bad_class::bad_class | ||||
| ( | ||||
| ) | ||||
|     : x_( -7, 16.75 ), base_class( x_ )  // this order doesn't matter | ||||
| { | ||||
|     PRIVATE_REGISTER_BIRTH( *this ); | ||||
|  | ||||
|     #if CONTROL_EXTRA_PRINTING | ||||
|     std::cout << "\tMy factor is at " << &x_ | ||||
|      << " and my base is at " << static_cast<base_class *>(this) << '.' | ||||
|      << std::endl; | ||||
|     #endif | ||||
| } | ||||
|  | ||||
| // Destroy a bad_class, noting the improper destruction order | ||||
| bad_class::~bad_class | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     PRIVATE_REGISTER_DEATH( *this ); | ||||
|  | ||||
|     #if CONTROL_EXTRA_PRINTING | ||||
|     std::cout << "\tMy factor was at " << &x_ | ||||
|      << " and my base was at " << static_cast<base_class *>(this) | ||||
|      << '.' << std::endl; | ||||
|     #endif | ||||
| } | ||||
|  | ||||
| // Create a good_class_1, noting the proper construction order | ||||
| good_class_1::good_class_1 | ||||
| ( | ||||
| ) | ||||
|     : pbase_type( 8 ), base_type( member ) | ||||
| { | ||||
|     PRIVATE_REGISTER_BIRTH( *this ); | ||||
|  | ||||
|     #if CONTROL_EXTRA_PRINTING | ||||
|     std::cout << "\tMy factor is at " << &member | ||||
|      << " and my base is at " << static_cast<base_class *>(this) << '.' | ||||
|      << std::endl; | ||||
|     #endif | ||||
| } | ||||
|  | ||||
| // Destroy a good_class_1, noting the proper destruction order | ||||
| good_class_1::~good_class_1 | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     PRIVATE_REGISTER_DEATH( *this ); | ||||
|  | ||||
|     #if CONTROL_EXTRA_PRINTING | ||||
|     std::cout << "\tMy factor was at " << &member | ||||
|      << " and my base was at " << static_cast<base_class *>(this) | ||||
|      << '.' << std::endl; | ||||
|     #endif | ||||
| } | ||||
|  | ||||
| // Create a good_class_2, noting the proper construction order | ||||
| good_class_2::good_class_2 | ||||
| ( | ||||
| ) | ||||
|     : pbase_type0(), pbase_type1(-16, 0.125), pbase_type2(2, -3) | ||||
|     , base_type( pbase_type1::member, &this->pbase_type0::member, | ||||
|        &this->pbase_type2::member ) | ||||
| { | ||||
|     PRIVATE_REGISTER_BIRTH( *this ); | ||||
|  | ||||
|     #if CONTROL_EXTRA_PRINTING | ||||
|     std::cout << "\tMy factors are at " << &this->pbase_type0::member | ||||
|      << ", " << &this->pbase_type1::member << ", " | ||||
|      << &this->pbase_type2::member << ", and my base is at " | ||||
|      << static_cast<base_class *>(this) << '.' << std::endl; | ||||
|     #endif | ||||
| } | ||||
|  | ||||
| // Destroy a good_class_2, noting the proper destruction order | ||||
| good_class_2::~good_class_2 | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     PRIVATE_REGISTER_DEATH( *this ); | ||||
|  | ||||
|     #if CONTROL_EXTRA_PRINTING | ||||
|     std::cout << "\tMy factors were at " << &this->pbase_type0::member | ||||
|      << ", " << &this->pbase_type1::member << ", " | ||||
|      << &this->pbase_type2::member << ", and my base was at " | ||||
|      << static_cast<base_class *>(this) << '.' << std::endl; | ||||
|     #endif | ||||
| } | ||||
| @@ -1,258 +0,0 @@ | ||||
| // (C) Copyright David Abrahams 2000. | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #include <vector> | ||||
| #include <string> | ||||
| #include <memory> | ||||
| #include <climits> | ||||
| #include <iostream> | ||||
| #include <cassert> | ||||
| #include <stdlib.h> // for rand(). Would use cstdlib but VC6.4 doesn't put it in std:: | ||||
| #include <list> | ||||
| #include <algorithm> | ||||
| #include <boost/detail/binary_search.hpp> | ||||
| #include <boost/detail/workaround.hpp> | ||||
| #include <cstddef> | ||||
|  | ||||
| #if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2) | ||||
| # define USE_SSTREAM | ||||
| #endif | ||||
|  | ||||
| #ifdef USE_SSTREAM | ||||
| # include <sstream> | ||||
| #else | ||||
| # include <strstream> | ||||
| #endif | ||||
|  | ||||
| namespace { | ||||
|  | ||||
| // In order to get ADL to find the comparison operators defined below, they have | ||||
| struct mystring : std::string | ||||
| { | ||||
|     typedef std::string base; | ||||
|      | ||||
|     mystring(std::string const& x) | ||||
|         : base(x) {} | ||||
| }; | ||||
|  | ||||
| typedef std::vector<mystring> string_vector; | ||||
|  | ||||
| const std::size_t sequence_length = 1000; | ||||
|  | ||||
| unsigned random_number() | ||||
| { | ||||
|     return static_cast<unsigned>(::rand()) % sequence_length; | ||||
| } | ||||
|  | ||||
| # ifndef USE_SSTREAM | ||||
| class unfreezer { | ||||
|  public: | ||||
|     unfreezer(std::ostrstream& s) : m_stream(s) {} | ||||
|     ~unfreezer() { m_stream.freeze(false); } | ||||
|  private: | ||||
|     std::ostrstream& m_stream; | ||||
| }; | ||||
| # endif | ||||
|  | ||||
| template <class T> | ||||
| void push_back_random_number_string(T& seq) | ||||
| { | ||||
|     unsigned value = random_number(); | ||||
| # if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2) | ||||
|     std::ostringstream s; | ||||
|     s << value; | ||||
|     seq.push_back(s.str()); | ||||
| # else | ||||
|     std::ostrstream s; | ||||
|     auto unfreezer unfreeze(s); | ||||
|     s << value << char(0); | ||||
|     seq.push_back(std::string(s.str())); | ||||
| # endif | ||||
| } | ||||
|  | ||||
| inline unsigned to_int(unsigned x) { return x; } | ||||
| inline unsigned to_int(const std::string& x) { return atoi(x.c_str()); } | ||||
|  | ||||
| struct cmp | ||||
| { | ||||
|     template <class A1, class A2> | ||||
|     inline bool operator()(const A1& a1, const A2& a2) const | ||||
|     { | ||||
|         return to_int(a1) < to_int(a2); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| inline bool operator<(const mystring& x, const unsigned y) | ||||
| { | ||||
|     return to_int(x) < y; | ||||
| } | ||||
|  | ||||
| inline bool operator<(const unsigned y, const mystring& x) | ||||
| { | ||||
|     return y < to_int(x); | ||||
| } | ||||
|  | ||||
| template <class T> | ||||
| void sort_by_value(T& x); | ||||
|  | ||||
| template <class T> | ||||
| void sort_by_value_(T& v, long) | ||||
| { | ||||
|     std::sort(v.begin(), v.end(), cmp()); | ||||
| } | ||||
|  | ||||
| template <class T> | ||||
| void random_sorted_sequence(T& seq) | ||||
| { | ||||
|     seq.clear(); | ||||
|     for (std::size_t i = 0; i < sequence_length; ++i) | ||||
|     { | ||||
|         push_back_random_number_string(seq); | ||||
|     } | ||||
|     sort_by_value(seq); | ||||
| } | ||||
|  | ||||
| template <class T, class A> | ||||
| void sort_by_value_(std::list<T,A>& l, int) | ||||
| { | ||||
| # if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) && !defined(__SGI_STL_PORT) | ||||
| // VC6's standard lib doesn't have a template member function for list::sort() | ||||
|     std::vector<T> seq; | ||||
|     seq.reserve(sequence_length); | ||||
|     std::copy(l.begin(), l.end(), std::back_inserter(seq)); | ||||
|     sort_by_value(seq); | ||||
|     std::copy(seq.begin(), seq.end(), l.begin()); | ||||
| # else | ||||
|     l.sort(cmp()); | ||||
| # endif | ||||
| } | ||||
|  | ||||
| template <class T> | ||||
| void sort_by_value(T& x) | ||||
| { | ||||
|     (sort_by_value_)(x, 1); | ||||
| } | ||||
|  | ||||
| // A way to select the comparisons with/without a Compare parameter for testing. | ||||
| template <class Compare> struct searches | ||||
| { | ||||
|     template <class Iterator, class Key> | ||||
|     static Iterator lower_bound(Iterator start, Iterator finish, Key key, Compare cmp) | ||||
|         { return boost::detail::lower_bound(start, finish, key, cmp); } | ||||
|  | ||||
|     template <class Iterator, class Key> | ||||
|     static Iterator upper_bound(Iterator start, Iterator finish, Key key, Compare cmp) | ||||
|         { return boost::detail::upper_bound(start, finish, key, cmp); } | ||||
|  | ||||
|     template <class Iterator, class Key> | ||||
|     static std::pair<Iterator, Iterator> equal_range(Iterator start, Iterator finish, Key key, Compare cmp) | ||||
|         { return boost::detail::equal_range(start, finish, key, cmp); } | ||||
|  | ||||
|     template <class Iterator, class Key> | ||||
|     static bool binary_search(Iterator start, Iterator finish, Key key, Compare cmp) | ||||
|         { return boost::detail::binary_search(start, finish, key, cmp); } | ||||
| }; | ||||
|  | ||||
| struct no_compare {}; | ||||
|  | ||||
| template <> struct searches<no_compare> | ||||
| { | ||||
|     template <class Iterator, class Key> | ||||
|     static Iterator lower_bound(Iterator start, Iterator finish, Key key, no_compare) | ||||
|         { return boost::detail::lower_bound(start, finish, key); } | ||||
|  | ||||
|     template <class Iterator, class Key> | ||||
|     static Iterator upper_bound(Iterator start, Iterator finish, Key key, no_compare) | ||||
|         { return boost::detail::upper_bound(start, finish, key); } | ||||
|  | ||||
|     template <class Iterator, class Key> | ||||
|     static std::pair<Iterator, Iterator> equal_range(Iterator start, Iterator finish, Key key, no_compare) | ||||
|         { return boost::detail::equal_range(start, finish, key); } | ||||
|  | ||||
|     template <class Iterator, class Key> | ||||
|     static bool binary_search(Iterator start, Iterator finish, Key key, no_compare) | ||||
|         { return boost::detail::binary_search(start, finish, key); } | ||||
| }; | ||||
|  | ||||
| template <class Sequence, class Compare> | ||||
| void test_loop(Sequence& x, Compare cmp, unsigned long test_count) | ||||
| { | ||||
|     typedef typename Sequence::const_iterator const_iterator; | ||||
|      | ||||
|     for (unsigned long i = 0; i < test_count; ++i) | ||||
|     { | ||||
|         random_sorted_sequence(x); | ||||
|         const const_iterator start = x.begin(); | ||||
|         const const_iterator finish = x.end(); | ||||
|          | ||||
|         unsigned key = random_number(); | ||||
|         const const_iterator l = searches<Compare>::lower_bound(start, finish, key, cmp); | ||||
|         const const_iterator u = searches<Compare>::upper_bound(start, finish, key, cmp); | ||||
|  | ||||
|         bool found_l = false; | ||||
|         bool found_u = false; | ||||
|         std::size_t index = 0; | ||||
|         std::size_t count = 0; | ||||
|         unsigned last_value = 0; | ||||
|         for (const_iterator p = start; p != finish; ++p) | ||||
|         { | ||||
|             if (p == l) | ||||
|                 found_l = true; | ||||
|              | ||||
|             if (p == u) | ||||
|             { | ||||
|                 assert(found_l); | ||||
|                 found_u = true; | ||||
|             } | ||||
|  | ||||
|             unsigned value = to_int(*p); | ||||
|             assert(value >= last_value); | ||||
|             last_value = value; | ||||
|              | ||||
|             if (!found_l) | ||||
|             { | ||||
|                 ++index; | ||||
|                 assert(to_int(*p) < key); | ||||
|             } | ||||
|             else if (!found_u) | ||||
|             { | ||||
|                 ++count; | ||||
|                 assert(to_int(*p) == key); | ||||
|             } | ||||
|             else | ||||
|                 assert(to_int(*p) > key); | ||||
|         } | ||||
|         assert(found_l || l == finish); | ||||
|         assert(found_u || u == finish); | ||||
|  | ||||
|         std::pair<const_iterator, const_iterator> | ||||
|             range = searches<Compare>::equal_range(start, finish, key, cmp); | ||||
|         assert(range.first == l); | ||||
|         assert(range.second == u); | ||||
|  | ||||
|         bool found = searches<Compare>::binary_search(start, finish, key, cmp); | ||||
|         assert(found == (u != l)); | ||||
|         std::cout << "found " << count << " copies of " << key << " at index " << index << "\n"; | ||||
|     } | ||||
| } | ||||
|  | ||||
| } | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     string_vector x; | ||||
|     std::cout << "=== testing random-access iterators with <: ===\n"; | ||||
|     test_loop(x, no_compare(), 25); | ||||
|     std::cout << "=== testing random-access iterators with compare: ===\n"; | ||||
|     test_loop(x, cmp(), 25); | ||||
|      | ||||
|     std::list<mystring> y; | ||||
|     std::cout << "=== testing bidirectional iterators with <: ===\n"; | ||||
|     test_loop(y, no_compare(), 25); | ||||
|     std::cout << "=== testing bidirectional iterators with compare: ===\n"; | ||||
|     test_loop(y, cmp(), 25); | ||||
|     std::cerr << "******TEST PASSED******\n"; | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										764
									
								
								call_traits.htm
									
									
									
									
									
								
							
							
						
						
									
										764
									
								
								call_traits.htm
									
									
									
									
									
								
							| @@ -1,764 +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="../../boost.png" 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="../type_traits/examples/fill_example.cpp">fill_example.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@johnmaddock.co.uk">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.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p> | ||||
|  | ||||
| <p>.</p> | ||||
|  | ||||
| <p> </p> | ||||
|  | ||||
| <p> </p> | ||||
| </body> | ||||
| </html> | ||||
| @@ -1,466 +0,0 @@ | ||||
| //  boost::compressed_pair test program    | ||||
|      | ||||
| //  (C) Copyright John Maddock 2000.  | ||||
| //  Use, modification and distribution are subject to the Boost Software License, | ||||
| //  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //  http://www.boost.org/LICENSE_1_0.txt). | ||||
|  | ||||
|  | ||||
| // standalone test program for <boost/call_traits.hpp> | ||||
| // 18 Mar 2002: | ||||
| //    Changed some names to prevent conflicts with some new type_traits additions. | ||||
| // 03 Oct 2000: | ||||
| //    Enabled extra tests for VC6. | ||||
|  | ||||
| #include <cassert> | ||||
| #include <iostream> | ||||
| #include <iomanip> | ||||
| #include <algorithm> | ||||
| #include <typeinfo> | ||||
| #include <boost/call_traits.hpp> | ||||
|  | ||||
| #include <libs/type_traits/test/test.hpp> | ||||
| #include <libs/type_traits/test/check_type.hpp> | ||||
|  | ||||
| // | ||||
| // define tests here | ||||
| unsigned failures = 0; | ||||
| unsigned test_count = 0; | ||||
| // | ||||
| // This must get defined within the test file. | ||||
| // All compilers have bugs, set this to the number of | ||||
| // regressions *expected* from a given compiler, | ||||
| // if there are no workarounds for the bugs, *and* | ||||
| // the regressions have been investigated. | ||||
| // | ||||
| extern unsigned int expected_failures; | ||||
| // | ||||
| // proc check_result() | ||||
| // Checks that there were no regressions: | ||||
| // | ||||
| int check_result(int argc, char** argv) | ||||
| { | ||||
|    std::cout << test_count << " tests completed, " | ||||
|       << failures << " failures found, " | ||||
|       << expected_failures << " failures expected from this compiler." << std::endl; | ||||
|    if((argc == 2)  | ||||
|       && (argv[1][0] == '-') | ||||
|       && (argv[1][1] == 'a') | ||||
|       && (argv[1][2] == 0)) | ||||
|    { | ||||
|       std::cout << "Press any key to continue..."; | ||||
|       std::cin.get(); | ||||
|    } | ||||
|    return (failures == expected_failures) | ||||
|        ? 0 | ||||
|        : (failures != 0) ? static_cast<int>(failures) : -1; | ||||
| } | ||||
|  | ||||
| // a way prevent warnings for unused variables | ||||
| template<class T> inline void unused_variable(const T&) {} | ||||
|  | ||||
| // | ||||
| // 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){} | ||||
|  | ||||
| }; | ||||
|  | ||||
| #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){} | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| template <class T> | ||||
| contained<typename boost::call_traits<T>::value_type> test_wrap_type(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()); | ||||
| #ifndef __ICL | ||||
|    //cout << "typeof contained<" << typeid(T).name() << ">::v_ is:           " << typeid(&contained<T>::v_).name() << endl; | ||||
|    cout << "typeof contained<" << typeid(T).name() << ">::value() is:      " << typeid(&contained<T>::value).name() << endl; | ||||
|    cout << "typeof contained<" << typeid(T).name() << ">::get() is:        " << typeid(&contained<T>::get).name() << endl; | ||||
|    cout << "typeof contained<" << typeid(T).name() << ">::const_get() is:  " << typeid(&contained<T>::const_get).name() << endl; | ||||
|    cout << "typeof contained<" << typeid(T).name() << ">::call() is:       " << typeid(&contained<T>::call).name() << endl; | ||||
|    cout << endl; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template <class T, std::size_t N> | ||||
| struct 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 W, class U> | ||||
| void check_wrap(const W& w, const U& u) | ||||
| { | ||||
|    cout << "checking " << typeid(W).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){} | ||||
|    comparible_UDT(const comparible_UDT& other) : i_(other.i_){} | ||||
|    comparible_UDT& operator=(const comparible_UDT& other) | ||||
|    {  | ||||
|       i_ = other.i_; | ||||
|       return *this; | ||||
|    } | ||||
|    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; | ||||
|    int a[2] = {1,2}; | ||||
| #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) && !defined(__ICL) | ||||
|    call_traits_checker<int*> c3; | ||||
|    c3(pi); | ||||
|    call_traits_checker<int&> c4; | ||||
|    c4(i); | ||||
|    call_traits_checker<const int&> c5; | ||||
|    c5(i); | ||||
| #if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__) && !defined(__SUNPRO_CC) | ||||
|    call_traits_checker<int[2]> c6; | ||||
|    c6(a); | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
|    check_wrap(test_wrap_type(2), 2); | ||||
| #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) | ||||
|    check_wrap(test_wrap_type(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; | ||||
|  | ||||
|    BOOST_CHECK_TYPE(comparible_UDT, boost::call_traits<comparible_UDT>::value_type); | ||||
|    BOOST_CHECK_TYPE(comparible_UDT&, boost::call_traits<comparible_UDT>::reference); | ||||
|    BOOST_CHECK_TYPE(const comparible_UDT&, boost::call_traits<comparible_UDT>::const_reference); | ||||
|    BOOST_CHECK_TYPE(const comparible_UDT&, boost::call_traits<comparible_UDT>::param_type); | ||||
|    BOOST_CHECK_TYPE(int, boost::call_traits<int>::value_type); | ||||
|    BOOST_CHECK_TYPE(int&, boost::call_traits<int>::reference); | ||||
|    BOOST_CHECK_TYPE(const int&, boost::call_traits<int>::const_reference); | ||||
|    BOOST_CHECK_TYPE(const int, boost::call_traits<int>::param_type); | ||||
|    BOOST_CHECK_TYPE(int*, boost::call_traits<int*>::value_type); | ||||
|    BOOST_CHECK_TYPE(int*&, boost::call_traits<int*>::reference); | ||||
|    BOOST_CHECK_TYPE(int*const&, boost::call_traits<int*>::const_reference); | ||||
|    BOOST_CHECK_TYPE(int*const, boost::call_traits<int*>::param_type); | ||||
| #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) | ||||
|    BOOST_CHECK_TYPE(int&, boost::call_traits<int&>::value_type); | ||||
|    BOOST_CHECK_TYPE(int&, boost::call_traits<int&>::reference); | ||||
|    BOOST_CHECK_TYPE(const int&, boost::call_traits<int&>::const_reference); | ||||
|    BOOST_CHECK_TYPE(int&, boost::call_traits<int&>::param_type); | ||||
| #if !(defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1))) | ||||
|    BOOST_CHECK_TYPE(int&, boost::call_traits<cr_type>::value_type); | ||||
|    BOOST_CHECK_TYPE(int&, boost::call_traits<cr_type>::reference); | ||||
|    BOOST_CHECK_TYPE(const int&, boost::call_traits<cr_type>::const_reference); | ||||
|    BOOST_CHECK_TYPE(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 | ||||
|    BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::value_type); | ||||
|    BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::reference); | ||||
|    BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::const_reference); | ||||
|    BOOST_CHECK_TYPE(const int&, boost::call_traits<const int&>::param_type); | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|    BOOST_CHECK_TYPE(const int*, boost::call_traits<int[3]>::value_type); | ||||
|    BOOST_CHECK_TYPE(int(&)[3], boost::call_traits<int[3]>::reference); | ||||
|    BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits<int[3]>::const_reference); | ||||
|    BOOST_CHECK_TYPE(const int*const, boost::call_traits<int[3]>::param_type); | ||||
|    BOOST_CHECK_TYPE(const int*, boost::call_traits<const int[3]>::value_type); | ||||
|    BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits<const int[3]>::reference); | ||||
|    BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits<const int[3]>::const_reference); | ||||
|    BOOST_CHECK_TYPE(const int*const, boost::call_traits<const int[3]>::param_type); | ||||
|    // test with abstract base class: | ||||
|    BOOST_CHECK_TYPE(test_abc1, boost::call_traits<test_abc1>::value_type); | ||||
|    BOOST_CHECK_TYPE(test_abc1&, boost::call_traits<test_abc1>::reference); | ||||
|    BOOST_CHECK_TYPE(const test_abc1&, boost::call_traits<test_abc1>::const_reference); | ||||
|    BOOST_CHECK_TYPE(const test_abc1&, boost::call_traits<test_abc1>::param_type); | ||||
| #else | ||||
|    std::cout << "You're compiler does not support partial template specialiation, skipping 8 tests (8 errors)" << std::endl; | ||||
|    failures += 12; | ||||
|    test_count += 12; | ||||
| #endif | ||||
| #else | ||||
|    std::cout << "You're compiler does not support partial template specialiation, skipping 20 tests (20 errors)" << std::endl; | ||||
|    failures += 24; | ||||
|    test_count += 24; | ||||
| #endif | ||||
|    // test with an incomplete type: | ||||
|    BOOST_CHECK_TYPE(incomplete_type, boost::call_traits<incomplete_type>::value_type); | ||||
|    BOOST_CHECK_TYPE(incomplete_type&, boost::call_traits<incomplete_type>::reference); | ||||
|    BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits<incomplete_type>::const_reference); | ||||
|    BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits<incomplete_type>::param_type); | ||||
|  | ||||
|    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); | ||||
|     | ||||
|    unused_variable(v2); | ||||
|    unused_variable(v3); | ||||
|    unused_variable(v4); | ||||
|    unused_variable(r2); | ||||
|    unused_variable(r3); | ||||
|    unused_variable(cr2); | ||||
|    unused_variable(cr3); | ||||
|    unused_variable(cr4); | ||||
|    unused_variable(cr5); | ||||
|    unused_variable(p2); | ||||
|    unused_variable(p3); | ||||
|    unused_variable(p4); | ||||
| } | ||||
| #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); | ||||
|     | ||||
|    unused_variable(v2); | ||||
|    unused_variable(v3); | ||||
|    unused_variable(v4); | ||||
|    unused_variable(v5); | ||||
| #ifndef __BORLANDC__ | ||||
|    unused_variable(r2); | ||||
|    unused_variable(cr2); | ||||
| #endif | ||||
|    unused_variable(cr3); | ||||
|    unused_variable(p2); | ||||
|    unused_variable(p3); | ||||
|    unused_variable(p4); | ||||
| } | ||||
| #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) | ||||
| template struct call_traits_test<int&>; | ||||
| template struct call_traits_test<const int&>; | ||||
| #if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) | ||||
| template struct call_traits_test<int[2], true>; | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| #if defined(BOOST_MSVC) && _MSC_VER <= 1300 | ||||
| unsigned int expected_failures = 12; | ||||
| #elif defined(__SUNPRO_CC) | ||||
| #if(__SUNPRO_CC <= 0x520) | ||||
| unsigned int expected_failures = 18; | ||||
| #elif(__SUNPRO_CC < 0x530) | ||||
| unsigned int expected_failures = 17; | ||||
| #else | ||||
| unsigned int expected_failures = 6; | ||||
| #endif | ||||
| #elif defined(__BORLANDC__) | ||||
| unsigned int expected_failures = 2; | ||||
| #elif (defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1))) | ||||
| unsigned int expected_failures = 4; | ||||
| #elif defined(__HP_aCC) | ||||
| unsigned int expected_failures = 24; | ||||
| #else | ||||
| unsigned int expected_failures = 0; | ||||
| #endif | ||||
|  | ||||
| @@ -1,124 +0,0 @@ | ||||
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||||
| <html> | ||||
| 	<head> | ||||
| 		<title>Boost: checked_delete.hpp documentation</title> | ||||
| 		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | ||||
| 	</head> | ||||
| 	<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%"> | ||||
| 		<table border="0" width="100%"> | ||||
| 			<tr> | ||||
| 				<td width="277"> | ||||
| 					<img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86"> | ||||
| 				</td> | ||||
| 				<td align="middle"> | ||||
| 					<h1>checked_delete.hpp</h1> | ||||
| 				</td> | ||||
| 			</tr> | ||||
| 			<tr> | ||||
| 				<td colspan="2" height="64"> </td> | ||||
| 			</tr> | ||||
| 		</table> | ||||
| 		<p> | ||||
| 			The header <STRONG><boost/checked_delete.hpp></STRONG> defines two  | ||||
| 			function templates, <STRONG>checked_delete</STRONG> and <STRONG>checked_array_delete</STRONG>,  | ||||
| 			and two class templates, <STRONG>checked_deleter</STRONG> and <STRONG>checked_array_deleter</STRONG>. | ||||
| 		</p> | ||||
| 		<P>The C++ Standard allows, in 5.3.5/5, pointers to incomplete class types to be  | ||||
| 			deleted with a <EM>delete-expression</EM>. When the class has a non-trivial  | ||||
| 			destructor, or a class-specific operator delete, the behavior is undefined.  | ||||
| 			Some compilers issue a warning when an incomplete type is deleted, but  | ||||
| 			unfortunately, not all do, and programmers sometimes ignore or disable  | ||||
| 			warnings.</P> | ||||
| 		<P>A particularly troublesome case is when a smart pointer's destructor, such as <STRONG> | ||||
| 				boost::scoped_ptr<T>::~scoped_ptr</STRONG>, is instantiated with an  | ||||
| 			incomplete type. This can often lead to silent, hard to track failures.</P> | ||||
| 		<P>The supplied function and class templates can be used to prevent these problems,  | ||||
| 			as they require a complete type, and cause a compilation error otherwise.</P> | ||||
| 		<h3><a name="Synopsis">Synopsis</a></h3> | ||||
| 		<pre> | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| template<class T> void checked_delete(T * p); | ||||
| template<class T> void checked_array_delete(T * p); | ||||
| template<class T> struct checked_deleter; | ||||
| template<class T> struct checked_array_deleter; | ||||
|  | ||||
| } | ||||
| </pre> | ||||
| 		<h3>checked_delete</h3> | ||||
| 		<h4><a name="checked_delete">template<class T> void checked_delete(T * p);</a></h4> | ||||
| 		<blockquote> | ||||
| 			<p> | ||||
| 				<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete p</tt> | ||||
| 				must be well-formed. | ||||
| 			</p> | ||||
| 			<p> | ||||
| 				<b>Effects:</b> <tt>delete p;</tt> | ||||
| 			</p> | ||||
| 		</blockquote> | ||||
| 		<h3>checked_array_delete</h3> | ||||
| 		<h4><a name="checked_array_delete">template<class T> void checked_array_delete(T  | ||||
| 				* p);</a></h4> | ||||
| 		<blockquote> | ||||
| 			<p> | ||||
| 				<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete [] p</tt> | ||||
| 				must be well-formed. | ||||
| 			</p> | ||||
| 			<p> | ||||
| 				<b>Effects:</b> <tt>delete [] p;</tt> | ||||
| 			</p> | ||||
| 		</blockquote> | ||||
| 		<h3>checked_deleter</h3> | ||||
| 		<pre> | ||||
| template<class T> struct checked_deleter | ||||
| { | ||||
|     typedef void result_type; | ||||
|     typedef T * argument_type; | ||||
|     void operator()(T * p) const; | ||||
| }; | ||||
| </pre> | ||||
| 		<h4>void checked_deleter<T>::operator()(T * p) const;</h4> | ||||
| 		<blockquote> | ||||
| 			<p> | ||||
| 				<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete p</tt> | ||||
| 				must be well-formed. | ||||
| 			</p> | ||||
| 			<p> | ||||
| 				<b>Effects:</b> <tt>delete p;</tt> | ||||
| 			</p> | ||||
| 		</blockquote> | ||||
| 		<h3>checked_array_deleter</h3> | ||||
| 		<pre> | ||||
| template<class T> struct checked_array_deleter | ||||
| { | ||||
|     typedef void result_type; | ||||
|     typedef T * argument_type; | ||||
|     void operator()(T * p) const; | ||||
| }; | ||||
| </pre> | ||||
| 		<h4>void checked_array_deleter<T>::operator()(T * p) const;</h4> | ||||
| 		<blockquote> | ||||
| 			<p> | ||||
| 				<b>Requires:</b> <b>T</b> must be a complete type. The expression <tt>delete [] p</tt> | ||||
| 				must be well-formed. | ||||
| 			</p> | ||||
| 			<p> | ||||
| 				<b>Effects:</b> <tt>delete [] p;</tt> | ||||
| 			</p> | ||||
| 		</blockquote> | ||||
| 		<h3><a name="Acknowledgements">Acknowledgements</a></h3> | ||||
| 		<p> | ||||
| 			The function templates <STRONG>checked_delete</STRONG> and <STRONG>checked_array_delete</STRONG> | ||||
| 			were originally part of <STRONG><boost/utility.hpp></STRONG>, and the  | ||||
| 			documentation acknowledged Beman Dawes, Dave Abrahams, Vladimir Prus, Rainer  | ||||
| 			Deyke, John Maddock, and others as contributors. | ||||
| 		</p> | ||||
| 		<p> | ||||
| 			<br> | ||||
| 			<small>Copyright <20> 2002 by Peter Dimov. 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.</small></p> | ||||
| 	</body> | ||||
| </html> | ||||
| @@ -1,28 +0,0 @@ | ||||
| //  Boost checked_delete test program  ---------------------------------------// | ||||
|  | ||||
| //  Copyright Beman Dawes 2001.  Distributed under the Boost | ||||
| //  Software License, Version 1.0. (See accompanying file | ||||
| //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //  See http://www.boost.org/libs/utility for documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  21 May 01  Initial version (Beman Dawes) | ||||
|  | ||||
| #include <boost/checked_delete.hpp>  // for checked_delete | ||||
|  | ||||
| //  This program demonstrates compiler errors when trying to delete an | ||||
| //  incomplete type. | ||||
|  | ||||
| namespace | ||||
| { | ||||
|     class Incomplete; | ||||
| } | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     Incomplete * p = 0; | ||||
|     boost::checked_delete(p);          // should cause compile time error | ||||
|     boost::checked_array_delete(p);    // should cause compile time error | ||||
|     return 0; | ||||
| }   // main | ||||
| @@ -1,75 +0,0 @@ | ||||
| <html> | ||||
|    <head> | ||||
|       <title>Header </title> | ||||
|       <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"> | ||||
|       <boostcompressed_pair.hpp> | ||||
|    </head> | ||||
|    <body bgcolor="#ffffff" text="#000000" link="#0000ff" vlink="#800080"> | ||||
|       <h2><img src="../../boost.png" width="276" height="86">Header <<a href="../../boost/detail/compressed_pair.hpp">boost/compressed_pair.hpp</a>></h2> | ||||
|       <p>All of the contents of <boost/compressed_pair.hpp> are defined inside  | ||||
|          namespace boost.</p> | ||||
|       <p>The class compressed pair is very similar to std::pair, but if either of the  | ||||
|          template arguments are empty classes, then the "empty base-class 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); | ||||
|  | ||||
| 	compressed_pair& operator=(const compressed_pair&); | ||||
|  | ||||
| 	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 if either member is a POD type, then that member is not  | ||||
|          zero-initialized by the compressed_pair default constructor: it's up to you to  | ||||
|          supply an initial value for these types if you want them to have a default  | ||||
|          value.</P> | ||||
|       <p>Note that compressed_pair can not be instantiated if either of the template  | ||||
|          arguments is a union type, unless there is compiler support for  | ||||
|          boost::is_union, or if boost::is_union is specialised for the union type.</p> | ||||
|       <p>Finally, a word of caution for Visual C++ 6 users: if either argument is an  | ||||
|          empty type, then assigning to that member will produce memory corruption,  | ||||
|          unless the empty type has a "do nothing" assignment operator defined. This is  | ||||
|          due to a bug in the way VC6 generates implicit assignment operators.</p> | ||||
|       <hr> | ||||
|       <p>Revised 08 May 2001</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@johnmaddock.co.uk">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.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p> | ||||
|       <p> </p> | ||||
|    </body> | ||||
| </html> | ||||
| @@ -1,395 +0,0 @@ | ||||
| //  boost::compressed_pair test program    | ||||
|      | ||||
| //  (C) Copyright John Maddock 2000.  | ||||
| //  Use, modification and distribution are subject to the Boost Software License, | ||||
| //  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //  http://www.boost.org/LICENSE_1_0.txt). | ||||
|  | ||||
| // 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/test/test_tools.hpp> | ||||
|  | ||||
| using namespace boost; | ||||
|  | ||||
| struct empty_UDT | ||||
| { | ||||
|    ~empty_UDT(){}; | ||||
|    empty_UDT& operator=(const empty_UDT&){ return *this; } | ||||
|    bool operator==(const empty_UDT&)const | ||||
|    { return true; } | ||||
| }; | ||||
| struct empty_POD_UDT | ||||
| { | ||||
|    empty_POD_UDT& operator=(const empty_POD_UDT&){ return *this; } | ||||
|    bool operator==(const empty_POD_UDT&)const | ||||
|    { return true; } | ||||
| }; | ||||
|  | ||||
| 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; } | ||||
| }; | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
| using std::swap; | ||||
| #endif | ||||
|  | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) | ||||
| { | ||||
| #ifndef __GNUC__ | ||||
|    // gcc 2.90 can't cope with function scope using | ||||
|    // declarations, and generates an internal compiler error... | ||||
|    using std::swap; | ||||
| #endif | ||||
|    // default construct: | ||||
|    boost::compressed_pair<T1,T2> cp1; | ||||
|    // first param construct: | ||||
|    boost::compressed_pair<T1,T2> cp2(p1); | ||||
|    cp2.second() = p2; | ||||
|    BOOST_CHECK(cp2.first() == p1); | ||||
|    BOOST_CHECK(cp2.second() == p2); | ||||
|    // second param construct: | ||||
|    boost::compressed_pair<T1,T2> cp3(p2); | ||||
|    cp3.first() = p1; | ||||
|    BOOST_CHECK(cp3.second() == p2); | ||||
|    BOOST_CHECK(cp3.first() == p1); | ||||
|    // both param construct: | ||||
|    boost::compressed_pair<T1,T2> cp4(p1, p2); | ||||
|    BOOST_CHECK(cp4.first() == p1); | ||||
|    BOOST_CHECK(cp4.second() == p2); | ||||
|    boost::compressed_pair<T1,T2> cp5(p3, p4); | ||||
|    BOOST_CHECK(cp5.first() == p3); | ||||
|    BOOST_CHECK(cp5.second() == p4); | ||||
|    // check const members: | ||||
|    const boost::compressed_pair<T1,T2>& cpr1 = cp4; | ||||
|    BOOST_CHECK(cpr1.first() == p1); | ||||
|    BOOST_CHECK(cpr1.second() == p2); | ||||
|  | ||||
|    // copy construct: | ||||
|    boost::compressed_pair<T1,T2> cp6(cp4); | ||||
|    BOOST_CHECK(cp6.first() == p1); | ||||
|    BOOST_CHECK(cp6.second() == p2); | ||||
|    // assignment: | ||||
|    cp1 = cp4; | ||||
|    BOOST_CHECK(cp1.first() == p1); | ||||
|    BOOST_CHECK(cp1.second() == p2); | ||||
|    cp1 = cp5; | ||||
|    BOOST_CHECK(cp1.first() == p3); | ||||
|    BOOST_CHECK(cp1.second() == p4); | ||||
|    // swap: | ||||
|    cp4.swap(cp5); | ||||
|    BOOST_CHECK(cp4.first() == p3); | ||||
|    BOOST_CHECK(cp4.second() == p4); | ||||
|    BOOST_CHECK(cp5.first() == p1); | ||||
|    BOOST_CHECK(cp5.second() == p2); | ||||
|    swap(cp4,cp5); | ||||
|    BOOST_CHECK(cp4.first() == p1); | ||||
|    BOOST_CHECK(cp4.second() == p2); | ||||
|    BOOST_CHECK(cp5.first() == p3); | ||||
|    BOOST_CHECK(cp5.second() == p4); | ||||
| } | ||||
|  | ||||
| // | ||||
| // tests for case where one or both  | ||||
| // parameters are reference types: | ||||
| // | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_reference_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_reference_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) | ||||
| { | ||||
| #ifndef __GNUC__ | ||||
|    // gcc 2.90 can't cope with function scope using | ||||
|    // declarations, and generates an internal compiler error... | ||||
|    using std::swap; | ||||
| #endif | ||||
|    // both param construct: | ||||
|    boost::compressed_pair<T1,T2> cp4(p1, p2); | ||||
|    BOOST_CHECK(cp4.first() == p1); | ||||
|    BOOST_CHECK(cp4.second() == p2); | ||||
|    boost::compressed_pair<T1,T2> cp5(p3, p4); | ||||
|    BOOST_CHECK(cp5.first() == p3); | ||||
|    BOOST_CHECK(cp5.second() == p4); | ||||
|    // check const members: | ||||
|    const boost::compressed_pair<T1,T2>& cpr1 = cp4; | ||||
|    BOOST_CHECK(cpr1.first() == p1); | ||||
|    BOOST_CHECK(cpr1.second() == p2); | ||||
|  | ||||
|    // copy construct: | ||||
|    boost::compressed_pair<T1,T2> cp6(cp4); | ||||
|    BOOST_CHECK(cp6.first() == p1); | ||||
|    BOOST_CHECK(cp6.second() == p2); | ||||
|    // assignment: | ||||
|    // VC6 bug: | ||||
|    // When second() is an empty class, VC6 performs the | ||||
|    // assignment by doing a memcpy - even though the empty | ||||
|    // class is really a zero sized base class, the result | ||||
|    // is that the memory of first() gets trampled over. | ||||
|    // Similar arguments apply to the case that first() is  | ||||
|    // an empty base class. | ||||
|    // Strangely the problem is dependent upon the compiler | ||||
|    // settings - some generate the problem others do not. | ||||
|    cp4.first() = p3; | ||||
|    cp4.second() = p4; | ||||
|    BOOST_CHECK(cp4.first() == p3); | ||||
|    BOOST_CHECK(cp4.second() == p4); | ||||
| } | ||||
| // | ||||
| // supplimentary tests for case where first arg only is a reference type: | ||||
| // | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_reference1_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_reference1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) | ||||
| { | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|    // first param construct: | ||||
|    boost::compressed_pair<T1,T2> cp2(p1); | ||||
|    cp2.second() = p2; | ||||
|    BOOST_CHECK(cp2.first() == p1); | ||||
|    BOOST_CHECK(cp2.second() == p2); | ||||
| #endif | ||||
| } | ||||
| // | ||||
| // supplimentary tests for case where second arg only is a reference type: | ||||
| // | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_reference2_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_reference2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) | ||||
| { | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|    // second param construct: | ||||
|    boost::compressed_pair<T1,T2> cp3(p2); | ||||
|    cp3.first() = p1; | ||||
|    BOOST_CHECK(cp3.second() == p2); | ||||
|    BOOST_CHECK(cp3.first() == p1); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| // | ||||
| // tests for where one or the other parameter is an array: | ||||
| // | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_array1_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_array1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) | ||||
| { | ||||
|   // default construct: | ||||
|    boost::compressed_pair<T1,T2> cp1; | ||||
|    // second param construct: | ||||
|    boost::compressed_pair<T1,T2> cp3(p2); | ||||
|    cp3.first()[0] = p1[0]; | ||||
|    BOOST_CHECK(cp3.second() == p2); | ||||
|    BOOST_CHECK(cp3.first()[0] == p1[0]); | ||||
|    // check const members: | ||||
|    const boost::compressed_pair<T1,T2>& cpr1 = cp3; | ||||
|    BOOST_CHECK(cpr1.first()[0] == p1[0]); | ||||
|    BOOST_CHECK(cpr1.second() == p2); | ||||
|  | ||||
|    BOOST_CHECK(sizeof(T1) == sizeof(cp1.first())); | ||||
| } | ||||
|  | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_array2_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_array2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) | ||||
| { | ||||
|    // default construct: | ||||
|    boost::compressed_pair<T1,T2> cp1; | ||||
|    // first param construct: | ||||
|    boost::compressed_pair<T1,T2> cp2(p1); | ||||
|    cp2.second()[0] = p2[0]; | ||||
|    BOOST_CHECK(cp2.first() == p1); | ||||
|    BOOST_CHECK(cp2.second()[0] == p2[0]); | ||||
|    // check const members: | ||||
|    const boost::compressed_pair<T1,T2>& cpr1 = cp2; | ||||
|    BOOST_CHECK(cpr1.first() == p1); | ||||
|    BOOST_CHECK(cpr1.second()[0] == p2[0]); | ||||
|  | ||||
|    BOOST_CHECK(sizeof(T2) == sizeof(cp1.second())); | ||||
| } | ||||
|  | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_array_tester | ||||
| { | ||||
|    // define the types we need: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    // define our test proc: | ||||
|    static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) | ||||
| { | ||||
|    // default construct: | ||||
|    boost::compressed_pair<T1,T2> cp1; | ||||
|    cp1.first()[0] = p1[0]; | ||||
|    cp1.second()[0] = p2[0]; | ||||
|    BOOST_CHECK(cp1.first()[0] == p1[0]); | ||||
|    BOOST_CHECK(cp1.second()[0] == p2[0]); | ||||
|    // check const members: | ||||
|    const boost::compressed_pair<T1,T2>& cpr1 = cp1; | ||||
|    BOOST_CHECK(cpr1.first()[0] == p1[0]); | ||||
|    BOOST_CHECK(cpr1.second()[0] == p2[0]); | ||||
|  | ||||
|    BOOST_CHECK(sizeof(T1) == sizeof(cp1.first())); | ||||
|    BOOST_CHECK(sizeof(T2) == sizeof(cp1.second())); | ||||
| } | ||||
|  | ||||
| int test_main(int, char *[]) | ||||
| { | ||||
|    // declare some variables to pass to the tester: | ||||
|    non_empty1 ne1(2); | ||||
|    non_empty1 ne2(3); | ||||
|    non_empty2 ne3(4); | ||||
|    non_empty2 ne4(5); | ||||
|    empty_POD_UDT  e1; | ||||
|    empty_UDT      e2; | ||||
|  | ||||
|    // T1 != T2, both non-empty | ||||
|    compressed_pair_tester<non_empty1,non_empty2>::test(ne1, ne3, ne2, ne4); | ||||
|    // T1 != T2, T2 empty | ||||
|    compressed_pair_tester<non_empty1,empty_POD_UDT>::test(ne1, e1, ne2, e1); | ||||
|    // T1 != T2, T1 empty | ||||
|    compressed_pair_tester<empty_POD_UDT,non_empty2>::test(e1, ne3, e1, ne4); | ||||
|    // T1 != T2, both empty | ||||
|    compressed_pair_tester<empty_POD_UDT,empty_UDT>::test(e1, e2, e1, e2); | ||||
|    // T1 == T2, both non-empty | ||||
|    compressed_pair_tester<non_empty1,non_empty1>::test(ne1, ne1, ne2, ne2); | ||||
|    // T1 == T2, both empty | ||||
|    compressed_pair_tester<empty_UDT,empty_UDT>::test(e2, e2, e2, e2); | ||||
|  | ||||
|  | ||||
|    // test references: | ||||
|  | ||||
|    // T1 != T2, both non-empty | ||||
|    compressed_pair_reference_tester<non_empty1&,non_empty2>::test(ne1, ne3, ne2, ne4); | ||||
|    compressed_pair_reference_tester<non_empty1,non_empty2&>::test(ne1, ne3, ne2, ne4); | ||||
|    compressed_pair_reference1_tester<non_empty1&,non_empty2>::test(ne1, ne3, ne2, ne4); | ||||
|    compressed_pair_reference2_tester<non_empty1,non_empty2&>::test(ne1, ne3, ne2, ne4); | ||||
|    // T1 != T2, T2 empty | ||||
|    compressed_pair_reference_tester<non_empty1&,empty_POD_UDT>::test(ne1, e1, ne2, e1); | ||||
|    compressed_pair_reference1_tester<non_empty1&,empty_POD_UDT>::test(ne1, e1, ne2, e1); | ||||
|    // T1 != T2, T1 empty | ||||
|    compressed_pair_reference_tester<empty_POD_UDT,non_empty2&>::test(e1, ne3, e1, ne4); | ||||
|    compressed_pair_reference2_tester<empty_POD_UDT,non_empty2&>::test(e1, ne3, e1, ne4); | ||||
|    // T1 == T2, both non-empty | ||||
|    compressed_pair_reference_tester<non_empty1&,non_empty1&>::test(ne1, ne1, ne2, ne2); | ||||
|  | ||||
|    // tests arrays: | ||||
|    non_empty1 nea1[2]; | ||||
|    non_empty1 nea2[2]; | ||||
|    non_empty2 nea3[2]; | ||||
|    non_empty2 nea4[2]; | ||||
|    nea1[0] = non_empty1(5); | ||||
|    nea2[0] = non_empty1(6); | ||||
|    nea3[0] = non_empty2(7); | ||||
|    nea4[0] = non_empty2(8); | ||||
|     | ||||
|    // T1 != T2, both non-empty | ||||
|    compressed_pair_array1_tester<non_empty1[2],non_empty2>::test(nea1, ne3, nea2, ne4); | ||||
|    compressed_pair_array2_tester<non_empty1,non_empty2[2]>::test(ne1, nea3, ne2, nea4); | ||||
|    compressed_pair_array_tester<non_empty1[2],non_empty2[2]>::test(nea1, nea3, nea2, nea4); | ||||
|    // T1 != T2, T2 empty | ||||
|    compressed_pair_array1_tester<non_empty1[2],empty_POD_UDT>::test(nea1, e1, nea2, e1); | ||||
|    // T1 != T2, T1 empty | ||||
|    compressed_pair_array2_tester<empty_POD_UDT,non_empty2[2]>::test(e1, nea3, e1, nea4); | ||||
|    // T1 == T2, both non-empty | ||||
|    compressed_pair_array_tester<non_empty1[2],non_empty1[2]>::test(nea1, nea1, nea2, nea2); | ||||
|    return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| unsigned int expected_failures = 0; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -1,38 +0,0 @@ | ||||
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||||
| <html> | ||||
| 	<head> | ||||
| 		<title>Boost: current_function.hpp documentation</title> | ||||
| 		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | ||||
| 	</head> | ||||
| 	<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%"> | ||||
| 		<table border="0" width="100%"> | ||||
| 			<tr> | ||||
| 				<td width="277"> | ||||
| 					<img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86"> | ||||
| 				</td> | ||||
| 				<td align="middle"> | ||||
| 					<h1>current_function.hpp</h1> | ||||
| 				</td> | ||||
| 			</tr> | ||||
| 			<tr> | ||||
| 				<td colspan="2" height="64"> </td> | ||||
| 			</tr> | ||||
| 		</table> | ||||
| 		<p> | ||||
| 			The header <STRONG><boost/current_function.hpp></STRONG> defines a single  | ||||
| 			macro, <STRONG>BOOST_CURRENT_FUNCTION</STRONG>,<STRONG> </STRONG>similar to the  | ||||
| 			C99 predefined identifier <STRONG>__func__</STRONG>. | ||||
| 		</p> | ||||
| 		<P><STRONG>BOOST_CURRENT_FUNCTION</STRONG> expands to a string literal containing  | ||||
| 			the (fully qualified, if possible) name of the enclosing function. If there is  | ||||
| 			no enclosing function, the behavior is undefined.</P> | ||||
| 		<p>Some compilers do not provide a way to obtain the name of the current enclosing  | ||||
| 			function. On such compilers, the string literal has an unspecified value.</p> | ||||
| 		<p> | ||||
| 			<br> | ||||
| 			<small>Copyright <20> 2002 by Peter Dimov. 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.</small></p> | ||||
| 	</body> | ||||
| </html> | ||||
| @@ -1,40 +0,0 @@ | ||||
| #include <boost/config.hpp> | ||||
|  | ||||
| #if defined(BOOST_MSVC) | ||||
| #pragma warning(disable: 4786)  // identifier truncated in debug info | ||||
| #pragma warning(disable: 4710)  // function not inlined | ||||
| #pragma warning(disable: 4711)  // function selected for automatic inline expansion | ||||
| #pragma warning(disable: 4514)  // unreferenced inline removed | ||||
| #endif | ||||
|  | ||||
| // | ||||
| //  current_function_test.cpp - a test for boost/current_function.hpp | ||||
| // | ||||
| //  Copyright (c) 2002 Peter Dimov and Multi Media Ltd. | ||||
| // | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
|  | ||||
| #include <boost/current_function.hpp> | ||||
| #include <boost/config.hpp> | ||||
| #include <cstdio> | ||||
|  | ||||
| void message(char const * file, long line, char const * func, char const * msg) | ||||
| { | ||||
| #if !defined(BOOST_NO_STDC_NAMESPACE) | ||||
|     using std::printf; | ||||
| #endif | ||||
|  | ||||
|     printf("%s(%ld): %s in function '%s'\n", file, line, msg, func); | ||||
| } | ||||
|  | ||||
| #define MESSAGE(msg) message(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, msg) | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     MESSAGE("assertion failed"); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										388
									
								
								enable_if.html
									
									
									
									
									
								
							
							
						
						
									
										388
									
								
								enable_if.html
									
									
									
									
									
								
							| @@ -1,388 +0,0 @@ | ||||
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" | ||||
|             "http://www.w3.org/TR/REC-html40/loose.dtd"> | ||||
| <HTML> | ||||
| <HEAD><TITLE>enable_if</TITLE> | ||||
|  | ||||
| <META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> | ||||
| <META name="GENERATOR" content="Microsoft FrontPage 5.0"> | ||||
| </HEAD> | ||||
| <BODY > | ||||
| <!--HEVEA command line is: hevea -nosymb -noiso -pedantic -v enable_if_docs_for_boost.tex --> | ||||
| <!--HTMLHEAD--> | ||||
| <!--ENDHTML--> | ||||
| <!--PREFIX <ARG ></ARG>--> | ||||
| <!--CUT DEF section 1 --> | ||||
| <BR> | ||||
| <BR> | ||||
|  | ||||
|  | ||||
| <h1> | ||||
| <img border="0" src="../../boost.png" align="center" width="277" height="86">enable_if</h1> | ||||
| <BR> | ||||
| <BR> | ||||
| Copyright 2003 Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine.<BR> | ||||
| <BR> | ||||
| <!--TOC section Introduction--> | ||||
|  | ||||
| <H2><A NAME="htoc1">1</A>  Introduction</H2><!--SEC END --> | ||||
|  | ||||
| <A NAME="introduction"></A> | ||||
| The <TT>enable_if</TT> family of templates is a set of tools to allow a function template or a class template specialization  | ||||
| to include or exclude itself from a set of matching functions or specializations | ||||
| based on properties of its template arguments.  | ||||
| For example, one can define function templates that | ||||
| are only enabled for, and thus only match, an arbitrary set of types | ||||
| defined by a traits class. The <TT>enable_if</TT> templates can also be | ||||
| applied to enable class template specializations. Applications of | ||||
| <TT>enable_if</TT> are discussed in length | ||||
| in [<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>] and [<A HREF="#jarvi:03:c++typeclasses"><CITE>2</CITE></A>].<BR> | ||||
| <BR> | ||||
| <!--TOC subsection Synopsis--> | ||||
|  | ||||
| <H3><A NAME="htoc2">1.1</A>  Synopsis</H3><!--SEC END --> | ||||
|  | ||||
| <A NAME="sec:synopsis"></A> | ||||
| <PRE>namespace boost { | ||||
|   template <class Cond, class T = void> struct enable_if; | ||||
|   template <class Cond, class T = void> struct disable_if; | ||||
|   template <class Cond, class T> struct lazy_enable_if; | ||||
|   template <class Cond, class T> struct lazy_disable_if; | ||||
|  | ||||
|   template <bool B, class T = void> struct enable_if_c; | ||||
|   template <bool B, class T = void> struct disable_if_c; | ||||
|   template <bool B, class T> struct lazy_enable_if_c; | ||||
|   template <bool B, class T> struct lazy_disable_if_c; | ||||
| } | ||||
| </PRE> | ||||
| <!--TOC subsection Background--> | ||||
|  | ||||
| <H3><A NAME="htoc3">1.2</A>  Background</H3><!--SEC END --> | ||||
|  | ||||
| <A NAME="sec:background"></A> | ||||
| Sensible operation of template function overloading in C++ relies | ||||
| on the <EM>SFINAE</EM> (substitution-failure-is-not-an-error) | ||||
| principle [<A HREF="#vandevoorde2002:templates"><CITE>3</CITE></A>]: if an invalid argument | ||||
| or return type is formed during the instantiation of a function | ||||
| template, the instantiation is removed from the overload resolution | ||||
| set instead of causing a compilation error. The following example,  | ||||
| taken from [<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>], | ||||
| demonstrates why this is important: | ||||
| <PRE>int negate(int i) { return -i; } | ||||
|  | ||||
| template <class F> | ||||
| typename F::result_type negate(const F& f) { return -f(); } | ||||
|  | ||||
| </PRE> | ||||
| Suppose the compiler encounters the call <TT>negate(1)</TT>. The first | ||||
| definition is obviously a better match, but the compiler must | ||||
| nevertheless consider (and instantiate the prototypes) of both | ||||
| definitions to find this out. Instantiating the latter definition with | ||||
| <TT>F</TT> as <TT>int</TT> would result in: | ||||
| <PRE>int::result_type negate(const int&); | ||||
|  | ||||
| </PRE> | ||||
| where the return type is invalid. If this was an error, adding an unrelated function template  | ||||
| (that was never called) could break otherwise valid code. | ||||
| Due to the SFINAE principle the above example is not, however, erroneous.  | ||||
| The latter definition of <TT>negate</TT> is simply removed from the overload resolution set.<BR> | ||||
| <BR> | ||||
| The <TT>enable_if</TT> templates are tools for controlled creation of the SFINAE | ||||
| conditions.<BR> | ||||
| <BR> | ||||
| <!--TOC section The <TT>enable_if</TT> templates--> | ||||
|  | ||||
| <H2><A NAME="htoc4">2</A>  The <TT>enable_if</TT> templates</H2><!--SEC END --> | ||||
|  | ||||
| <A NAME="enable_if"></A> | ||||
| The names of the <TT>enable_if</TT> templates have three parts: an optional <TT>lazy_</TT> tag,  | ||||
| either <TT>enable_if</TT> or <TT>disable_if</TT>, and an optional <TT>_c</TT> tag. | ||||
| All eight combinations of these parts are supported. | ||||
| The meaning of the <TT>lazy_</TT> tag is described in Section <A HREF="#sec:enable_if_lazy">3.3</A>. | ||||
| The second part of the name indicates whether a true condition argument should  | ||||
| enable or disable the current overload. | ||||
| The third part of the name indicates whether the condition argument is a <TT>bool</TT> value  | ||||
| (<TT>_c</TT> suffix), or a type containing a static <TT>bool</TT> constant named <TT>value</TT> (no suffix). | ||||
| The latter version interoperates with Boost.MPL. <BR> | ||||
| <BR> | ||||
| The definitions of <TT>enable_if_c</TT> and <TT>enable_if</TT> are as follows (we use <TT>enable_if</TT> templates  | ||||
| unqualified but they are in the <TT>boost</TT> namespace). | ||||
| <PRE>template <bool B, class T = void> | ||||
| struct enable_if_c { | ||||
|   typedef T type; | ||||
| }; | ||||
|  | ||||
| template <class T> | ||||
| struct enable_if_c<false, T> {}; | ||||
|  | ||||
| template <class Cond, class T = void> | ||||
| struct enable_if : public enable_if_c<Cond::value, T> {}; | ||||
|  | ||||
| </PRE> | ||||
| An instantiation of the <TT>enable_if_c</TT> template with the parameter | ||||
| <TT>B</TT> as <TT>true</TT> contains a member type <TT>type</TT>, defined | ||||
| to be <TT>T</TT>. If <TT>B</TT> is | ||||
| <TT>false</TT>, no such member is defined. Thus  | ||||
| <TT>enable_if_c<B, T>::type</TT> is either a valid or an invalid type | ||||
| expression, depending on the value of <TT>B</TT>. | ||||
| When valid, <TT>enable_if_c<B, T>::type</TT> equals <TT>T</TT>. | ||||
| The <TT>enable_if_c</TT> template can thus be used for controlling when functions are considered for | ||||
| overload resolution and when they are not.  | ||||
| For example, the following function is defined for all arithmetic types (according to the | ||||
| classification of the <A HREF="../type_traits/index.html">Boost type_traits library</A>): | ||||
| <PRE>template <class T> | ||||
| typename enable_if_c<boost::is_arithmetic<T>::value, T>::type  | ||||
| foo(T t) { return t; } | ||||
|  | ||||
| </PRE> | ||||
| The <TT>disable_if_c</TT> template is provided as well, and has the | ||||
| same functionality as <TT>enable_if_c</TT> except for the negated condition. The following | ||||
| function is enabled for all non-arithmetic types. | ||||
| <PRE>template <class T> | ||||
| typename disable_if_c<boost::is_arithmetic<T>::value, T>::type  | ||||
| bar(T t) { return t; } | ||||
|  | ||||
| </PRE> | ||||
| For easier syntax in some cases and interoperation with Boost.MPL we provide versions of | ||||
| the <TT>enable_if</TT> templates taking any type with a <TT>bool</TT> member constant named  | ||||
| <TT>value</TT> as the condition argument. | ||||
| The MPL <TT>bool_</TT>, <TT>and_</TT>, <TT>or_</TT>, and <TT>not_</TT> templates are likely to be  | ||||
| useful for creating such types. Also, the traits classes in the Boost.Type_traits library  | ||||
| follow this convention.  | ||||
| For example, the above example function <TT>foo</TT> can be alternatively written as: | ||||
| <PRE>template <class T> | ||||
| typename enable_if<boost::is_arithmetic<T>, T>::type  | ||||
| foo(T t) { return t; } | ||||
|  | ||||
| </PRE> | ||||
| <!--TOC section Using <TT>enable_if</TT>--> | ||||
|  | ||||
| <H2><A NAME="htoc5">3</A>  Using <TT>enable_if</TT></H2><!--SEC END --> | ||||
|  | ||||
| <A NAME="sec:using_enable_if"></A> | ||||
| The <TT>enable_if</TT> templates are defined in | ||||
| <TT>boost/utility/enable_if.hpp</TT>, which is included by <TT>boost/utility.hpp</TT>.<BR> | ||||
| <BR> | ||||
| The <TT>enable_if</TT> template can be used either as the return type, or as an  | ||||
| extra argument. For example, the <TT>foo</TT> function in the previous section could also be written | ||||
| as: | ||||
| <PRE>template <class T> | ||||
| T foo(T t, typename enable_if<boost::is_arithmetic<T> >::type* dummy = 0);  | ||||
|  | ||||
| </PRE>Hence, an extra parameter of type <TT>void*</TT> is added, but it is given  | ||||
| a default value to keep the parameter hidden from client code. | ||||
| Note that the second template argument was not given to <TT>enable_if</TT>, as the default  | ||||
| <TT>void</TT> gives the desired behavior.<BR> | ||||
| <BR> | ||||
| Whether to write the enabler as an argument or within the return type is | ||||
| largely a matter of taste, but for certain functions, only one | ||||
| alternative is possible: | ||||
| <UL><LI> | ||||
| Operators have a fixed number of arguments, thus <TT>enable_if</TT> must be used in the return type. | ||||
| <LI>Constructors and destructors do not have a return type; an extra argument is the only option. | ||||
| <LI>There does not seem to be a way to specify an enabler for a conversion operator. Converting constructors, | ||||
| however, can have enablers as extra default arguments. | ||||
| </UL> | ||||
| <!--TOC subsection Enabling template class specializations--> | ||||
|  | ||||
| <H3><A NAME="htoc6">3.1</A>  Enabling template class specializations</H3><!--SEC END --> | ||||
|  | ||||
| <A NAME="sec:enable_if_classes"></A> | ||||
| Class template specializations can be enabled or disabled with <TT>enable_if</TT>. | ||||
| One extra template parameter needs to be added for the enabler expressions. | ||||
| This parameter has the default value <TT>void</TT>. | ||||
| For example: | ||||
| <PRE>template <class T, class Enable = void>  | ||||
| class A { ... }; | ||||
|  | ||||
| template <class T> | ||||
| class A<T, typename enable_if<is_integral<T> >::type> { ... }; | ||||
|  | ||||
| template <class T> | ||||
| class A<T, typename enable_if<is_float<T> >::type> { ... }; | ||||
|  | ||||
| </PRE>Instantiating <TT>A</TT> with any integral type matches the first specialization, | ||||
| whereas any floating point type matches the second one. All other types | ||||
| match the primary template. | ||||
| The condition can be any compile-time boolean expression that depends on the  | ||||
| template arguments of the class. | ||||
| Note that again, the second argument to <TT>enable_if</TT> is not needed; the default (<TT>void</TT>)  | ||||
| is the correct value.<BR> | ||||
| <BR> | ||||
| <!--TOC subsection Overlapping enabler conditions--> | ||||
|  | ||||
| <H3><A NAME="htoc7">3.2</A>  Overlapping enabler conditions</H3><!--SEC END --> | ||||
|  | ||||
| <A NAME="sec:overlapping_conditions"></A> | ||||
| Once the compiler has examined the enabling conditions and included the | ||||
| function into the overload resolution set, normal C++ overload resolution  | ||||
| rules are used to select the best matching function. | ||||
| In particular, there is no ordering between enabling conditions. | ||||
| Function templates with enabling conditions that are not mutually exclusive can  | ||||
| lead to ambiguities. For example: | ||||
| <PRE>template <class T> | ||||
| typename enable_if<boost::is_integral<T>, void>::type  | ||||
| foo(T t) {} | ||||
|  | ||||
| template <class T> | ||||
| typename enable_if<boost::is_arithmetic<T>, void>::type  | ||||
| foo(T t) {} | ||||
|  | ||||
| </PRE> | ||||
| All integral types are also arithmetic. Therefore, say, for the call <TT>foo(1)</TT>, | ||||
| both conditions are true and both functions are thus in the overload resolution set. | ||||
| They are both equally good matches and thus ambiguous. | ||||
| Of course, more than one enabling condition can be simultaneously true as long as  | ||||
| other arguments disambiguate the functions.<BR> | ||||
| <BR> | ||||
| The above discussion applies to using <TT>enable_if</TT> in class template | ||||
| partial specializations as well.<BR> | ||||
| <BR> | ||||
| <!--TOC subsection Lazy <TT>enable_if</TT>--> | ||||
|  | ||||
| <H3><A NAME="htoc8">3.3</A>  Lazy <TT>enable_if</TT></H3><!--SEC END --> | ||||
|  | ||||
| <A NAME="sec:enable_if_lazy"></A> | ||||
| In some cases it is necessary to avoid instantiating part of a | ||||
| function signature unless an enabling condition is true. For example: | ||||
| <PRE>template <class T, class U> class mult_traits; | ||||
|  | ||||
| template <class T, class U> | ||||
| typename enable_if<is_multipliable<T, U>, typename mult_traits<T, U>::type>::type | ||||
| operator*(const T& t, const U& u) { ... } | ||||
|  | ||||
| </PRE>Assume the class template <TT>mult_traits</TT> is a traits class defining  | ||||
| the resulting type of a multiplication operator. The <TT>is_multipliable</TT> traits | ||||
| class specifies for which types to enable the operator. Whenever | ||||
| <TT>is_multipliable<A, B>::value</TT> is <TT>true</TT> for some types <TT>A</TT> and <TT>B</TT>, | ||||
| then <TT>mult_traits<A, B>::type</TT> is defined.<BR> | ||||
| <BR> | ||||
| Now, trying to invoke (some other overload) of <TT>operator*</TT> with, say, operand types <TT>C</TT> and <TT>D</TT>  | ||||
| for which <TT>is_multipliable<C, D>::value</TT> is <TT>false</TT>  | ||||
| and <TT>mult_traits<C, D>::type</TT> is not defined is an error on some compilers.  | ||||
| The SFINAE principle is not applied because | ||||
| the invalid type occurs as an argument to another template. The <TT>lazy_enable_if</TT>  | ||||
| and <TT>lazy_disable_if</TT> templates (and their <TT>_c</TT> versions) can be used in such | ||||
| situations: | ||||
| <PRE>template<class T, class U> | ||||
| typename lazy_enable_if<is_multipliable<T, U>, mult_traits<T, U> >::type | ||||
| operator*(const T& t, const U& u) { ... } | ||||
|  | ||||
| </PRE>The second argument of <TT>lazy_enable_if</TT> must be a class type | ||||
| that defines a nested type named <TT>type</TT> whenever the first | ||||
| parameter (the condition) is true.<BR> | ||||
| <BR> | ||||
| <!--TOC paragraph Note--> | ||||
|  | ||||
| <H5>Note</H5><!--SEC END --> | ||||
|  | ||||
| Referring to one member type or static constant in a traits class | ||||
| causes all of the members (type and static constant) of that | ||||
| specialization to be instantiated. Therefore, if your traits classes | ||||
| can sometimes contain invalid types, you should use two distinct | ||||
| templates for describing the conditions and the type mappings. In the | ||||
| above example, <TT>is_multipliable<T, U>::value</TT> defines when | ||||
| <TT>mult_traits<T, U>::type</TT> is valid.<BR> | ||||
| <BR> | ||||
| <!--TOC subsection Compiler workarounds--> | ||||
|  | ||||
| <H3><A NAME="htoc9">3.4</A>  Compiler workarounds</H3><!--SEC END --> | ||||
|  | ||||
| <A NAME="sec:workarounds"></A> | ||||
| Some compilers flag functions as ambiguous if the only distinguishing factor is a different  | ||||
| condition in an enabler (even though the functions could never be ambiguous). For example, | ||||
| some compilers (e.g. GCC 3.2) diagnose the following two functions as ambiguous: | ||||
| <PRE>template <class T> | ||||
| typename enable_if<boost::is_arithmetic<T>, T>::type  | ||||
| foo(T t); | ||||
|  | ||||
| template <class T> | ||||
| typename disable_if<boost::is_arithmetic<T>, T>::type  | ||||
| foo(T t); | ||||
|  | ||||
| </PRE>Two workarounds can be applied: | ||||
| <UL><LI> | ||||
| Use an extra dummy parameter which disambiguates the functions. Use a default value for | ||||
| it to hide the parameter from the caller. For example: | ||||
| <PRE>template <int> struct dummy { dummy(int) {} }; | ||||
|  | ||||
| template <class T> | ||||
| typename enable_if<boost::is_arithmetic<T>, T>::type  | ||||
| foo(T t, dummy<0> = 0); | ||||
|  | ||||
| template <class T> | ||||
| typename disable_if<boost::is_arithmetic<T>, T>::type  | ||||
| foo(T t, dummy<1> = 0); | ||||
| </PRE><BR> | ||||
| <BR> | ||||
| <LI>Define the functions in different namespaces and bring them into a common | ||||
| namespace with <TT>using</TT> declarations: | ||||
| <PRE>namespace A { | ||||
|   template <class T> | ||||
|   typename enable_if<boost::is_arithmetic<T>, T>::type  | ||||
|   foo(T t); | ||||
| } | ||||
|  | ||||
| namespace B { | ||||
|   template <class T> | ||||
|   typename disable_if<boost::is_arithmetic<T>, T>::type  | ||||
|   foo(T t); | ||||
| } | ||||
|  | ||||
| using A::foo; | ||||
| using B::foo; | ||||
|  | ||||
| </PRE> | ||||
| Note that the second workaround above cannot be used for member | ||||
| templates. On the other hand, operators do not accept extra arguments, | ||||
| which makes the first workaround unusable. As the net effect, | ||||
| neither of the workarounds are of assistance for templated operators that | ||||
| need to be defined as member functions (assignment and | ||||
| subscript operators). | ||||
| </UL> | ||||
| <!--TOC section Acknowledgements--> | ||||
|  | ||||
| <H2><A NAME="htoc10">4</A>  Acknowledgements</H2><!--SEC END --> | ||||
|  | ||||
| We are grateful to Howard Hinnant, Jason Shirk, Paul Mensonides, and Richard | ||||
| Smith whose findings have influenced the library.<BR> | ||||
| <BR> | ||||
| <!--TOC section References--> | ||||
|  | ||||
| <H2>References</H2><!--SEC END --> | ||||
| <DL COMPACT=compact><DT><A NAME="jarvi:03:cuj_arbitrary_overloading"><FONT COLOR=purple>[1]</FONT></A><DD> | ||||
| Jaakko Järvi, Jeremiah Willcock, Howard Hinnant, and Andrew Lumsdaine. | ||||
| Function overloading based on arbitrary properties of types. | ||||
| <EM>C/C++ Users Journal</EM>, 21(6):25--32, June 2003.<BR> | ||||
| <BR> | ||||
| <DT><A NAME="jarvi:03:c++typeclasses"><FONT COLOR=purple>[2]</FONT></A><DD> | ||||
| Jaakko Järvi, Jeremiah Willcock, and Andrew Lumsdaine. | ||||
| Concept-controlled polymorphism. | ||||
| In Frank Pfennig and Yannis Smaragdakis, editors, <EM>Generative | ||||
|  Programming and Component Engineering</EM>, volume 2830 of <EM>LNCS</EM>, pages | ||||
|  228--244. Springer Verlag, September 2003.<BR> | ||||
| <BR> | ||||
| <DT><A NAME="vandevoorde2002:templates"><FONT COLOR=purple>[3]</FONT></A><DD> | ||||
| David Vandevoorde and Nicolai M. Josuttis. | ||||
| <EM>C++ Templates: The Complete Guide</EM>. | ||||
| Addison-Wesley, 2002.</DL> | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| <hr></hr> | ||||
|  | ||||
| <B>Contributed by:</B> <BR> | ||||
| Jaakko Järvi, Jeremiah Willcock and Andrew Lumsdaine<BR> | ||||
| <EM>{jajarvi|jewillco|lums}@osl.iu.edu</EM><BR> | ||||
| Indiana University<BR> | ||||
| Open Systems Lab | ||||
| <!--HTMLFOOT--> | ||||
| <!--ENDHTML--> | ||||
| <!--FOOTER--> | ||||
| <HR SIZE=2> | ||||
| <BLOCKQUOTE><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by | ||||
| </EM><A HREF="http://pauillac.inria.fr/~maranget/hevea/index.html"><EM>H<FONT SIZE=2><sup>E</sup></FONT>V<FONT SIZE=2><sup>E</sup></FONT>A</EM></A><EM>. | ||||
| </EM></BLOCKQUOTE> | ||||
| </BODY> | ||||
| </HTML> | ||||
| @@ -1,33 +0,0 @@ | ||||
| # Copyright David Abrahams 2003. | ||||
| # Distributed under the Boost Software License, Version 1.0.  | ||||
| # (See accompanying file LICENSE_1_0.txt or copy at  | ||||
| # http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| # For more information, see http://www.boost.org/ | ||||
|  | ||||
| subproject libs/utility/enable_if/test ; | ||||
|  | ||||
| # bring in rules for testing | ||||
| import testing ; | ||||
|  | ||||
| # Make tests run by default. | ||||
| DEPENDS all : test ; | ||||
|  | ||||
| { | ||||
|     local test_monitor = <lib>@boost/libs/test/build/boost_test_exec_monitor ; | ||||
|  | ||||
|     # look in BOOST_ROOT for sources first, just in this Jamfile | ||||
|     local SEARCH_SOURCE = $(BOOST_ROOT) $(SEARCH_SOURCE) ; | ||||
|  | ||||
|     test-suite utility/enable_if | ||||
|         : | ||||
|         [ run libs/utility/enable_if/test/constructors.cpp $(test_monitor) ] | ||||
|         [ run libs/utility/enable_if/test/dummy_arg_disambiguation.cpp $(test_monitor) ] | ||||
|         [ run libs/utility/enable_if/test/lazy.cpp $(test_monitor) ] | ||||
|         [ run libs/utility/enable_if/test/lazy_test.cpp $(test_monitor) ] | ||||
|         [ run libs/utility/enable_if/test/member_templates.cpp $(test_monitor) ] | ||||
|         [ run libs/utility/enable_if/test/namespace_disambiguation.cpp $(test_monitor) ] | ||||
|         [ run libs/utility/enable_if/test/no_disambiguation.cpp $(test_monitor) ] | ||||
|         [ run libs/utility/enable_if/test/partial_specializations.cpp $(test_monitor) ] | ||||
|     ; | ||||
| } | ||||
| @@ -1,23 +0,0 @@ | ||||
| # Copyright David Abrahams 2003. | ||||
| # Distributed under the Boost Software License, Version 1.0.  | ||||
| # (See accompanying file LICENSE_1_0.txt or copy at  | ||||
| # http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| # For more information, see http://www.boost.org/ | ||||
|  | ||||
| project | ||||
|     : requirements <library>/boost/test//boost_test_exec_monitor | ||||
|     ; | ||||
|  | ||||
| test-suite utility/enable_if | ||||
|         : | ||||
|         [ run constructors.cpp ] | ||||
|         [ run dummy_arg_disambiguation.cpp ] | ||||
|         [ run lazy.cpp ] | ||||
|         [ run lazy_test.cpp ] | ||||
|         [ run member_templates.cpp ] | ||||
|         [ run namespace_disambiguation.cpp ] | ||||
|         [ run no_disambiguation.cpp ] | ||||
|         [ run partial_specializations.cpp ] | ||||
|     ; | ||||
|  | ||||
| @@ -1,62 +0,0 @@ | ||||
| // Boost enable_if library | ||||
|  | ||||
| // Copyright 2003 <20> The Trustees of Indiana University. | ||||
|  | ||||
| // Use, modification, and distribution is subject to the Boost Software | ||||
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //    Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu) | ||||
| //             Jeremiah Willcock (jewillco at osl.iu.edu) | ||||
| //             Andrew Lumsdaine (lums at osl.iu.edu) | ||||
|  | ||||
| #include <boost/test/minimal.hpp> | ||||
|  | ||||
| #include <boost/utility/enable_if.hpp> | ||||
| #include <boost/type_traits.hpp> | ||||
|  | ||||
| using boost::enable_if; | ||||
| using boost::disable_if; | ||||
| using boost::is_arithmetic; | ||||
|  | ||||
| struct container { | ||||
|   bool my_value; | ||||
|  | ||||
|   template <class T> | ||||
|   container(const T&, const typename enable_if<is_arithmetic<T>, T>::type * = 0): | ||||
|   my_value(true) {} | ||||
|  | ||||
|   template <class T> | ||||
|   container(const T&, const typename disable_if<is_arithmetic<T>, T>::type * = 0): | ||||
|   my_value(false) {} | ||||
| }; | ||||
|  | ||||
| // example from Howard Hinnant (tests enable_if template members of a templated class) | ||||
| template <class charT> | ||||
| struct xstring | ||||
| { | ||||
|   template <class It> | ||||
|   xstring(It begin, It end, typename  | ||||
|           disable_if<is_arithmetic<It> >::type* = 0) | ||||
|     : data(end-begin) {} | ||||
|    | ||||
|   int data; | ||||
| }; | ||||
|  | ||||
|  | ||||
| int test_main(int, char*[]) | ||||
| { | ||||
|   | ||||
|   BOOST_CHECK(container(1).my_value); | ||||
|   BOOST_CHECK(container(1.0).my_value); | ||||
|  | ||||
|   BOOST_CHECK(!container("1").my_value);   | ||||
|   BOOST_CHECK(!container(static_cast<void*>(0)).my_value);   | ||||
|  | ||||
|   char sa[] = "123456"; | ||||
|   BOOST_CHECK(xstring<char>(sa, sa+6).data == 6); | ||||
|  | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| @@ -1,46 +0,0 @@ | ||||
| // Boost enable_if library | ||||
|  | ||||
| // Copyright 2003 <20> The Trustees of Indiana University. | ||||
|  | ||||
| // Use, modification, and distribution is subject to the Boost Software | ||||
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //    Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu) | ||||
| //             Jeremiah Willcock (jewillco at osl.iu.edu) | ||||
| //             Andrew Lumsdaine (lums at osl.iu.edu) | ||||
|  | ||||
| #include <boost/test/minimal.hpp> | ||||
|  | ||||
| #include <boost/utility/enable_if.hpp> | ||||
| #include <boost/type_traits/is_arithmetic.hpp> | ||||
|  | ||||
| using boost::enable_if; | ||||
| using boost::disable_if; | ||||
| using boost::is_arithmetic; | ||||
|  | ||||
| template <int N> struct dummy { | ||||
|   dummy(int) {}; | ||||
| }; | ||||
|  | ||||
| template<class T> | ||||
| typename enable_if<is_arithmetic<T>, bool>::type | ||||
| arithmetic_object(T t, dummy<0> = 0) { return true; } | ||||
|  | ||||
| template<class T> | ||||
| typename disable_if<is_arithmetic<T>, bool>::type | ||||
| arithmetic_object(T t, dummy<1> = 0) { return false; } | ||||
|  | ||||
|  | ||||
| int test_main(int, char*[]) | ||||
| { | ||||
|   | ||||
|   BOOST_CHECK(arithmetic_object(1)); | ||||
|   BOOST_CHECK(arithmetic_object(1.0)); | ||||
|  | ||||
|   BOOST_CHECK(!arithmetic_object("1"));   | ||||
|   BOOST_CHECK(!arithmetic_object(static_cast<void*>(0)));   | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| @@ -1,82 +0,0 @@ | ||||
| // Boost enable_if library | ||||
|  | ||||
| // Copyright 2003 <20> The Trustees of Indiana University. | ||||
|  | ||||
| // Use, modification, and distribution is subject to the Boost Software | ||||
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //    Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu) | ||||
| //             Jeremiah Willcock (jewillco at osl.iu.edu) | ||||
| //             Andrew Lumsdaine (lums at osl.iu.edu) | ||||
|  | ||||
| #include <boost/test/minimal.hpp> | ||||
|  | ||||
| #include <boost/utility/enable_if.hpp> | ||||
| #include <boost/type_traits/is_same.hpp> | ||||
|  | ||||
| using boost::enable_if_c; | ||||
| using boost::lazy_enable_if_c; | ||||
|  | ||||
| // This class provides a reduced example of a traits class for | ||||
| // computing the result of multiplying two types.  The member typedef | ||||
| // 'type' in this traits class defines the return type of this | ||||
| // operator.  The return type member is invalid unless both arguments | ||||
| // for mult_traits are values that mult_traits expects (ints in this | ||||
| // case).  This kind of situation may arise if a traits class only | ||||
| // makes sense for some set of types, not all C++ types. | ||||
|  | ||||
| template <class T> struct is_int { | ||||
|   BOOST_STATIC_CONSTANT(bool, value = (boost::is_same<T, int>::value)); | ||||
| }; | ||||
|  | ||||
| template <class T, class U> | ||||
| struct mult_traits { | ||||
|   typedef typename T::does_not_exist type; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct mult_traits<int, int> { | ||||
|   typedef int type; | ||||
| }; | ||||
|  | ||||
|  | ||||
| // Next, a forwarding function mult() is defined.  It is enabled only | ||||
| // when both arguments are of type int.  The first version, using | ||||
| // non-lazy enable_if_c does not work. | ||||
|  | ||||
| #if 0 | ||||
| template <class T, class U> | ||||
| typename enable_if_c< | ||||
|   is_int<T>::value && is_int<U>::value, | ||||
|   typename mult_traits<T, U>::type | ||||
| >::type | ||||
| mult(const T& x, const U& y) {return x * y;} | ||||
| #endif | ||||
|  | ||||
| // A correct version uses lazy_enable_if_c. | ||||
| // This template removes compiler errors from invalid code used as an | ||||
| // argument to enable_if_c. | ||||
|  | ||||
| #if 1 | ||||
| template <class T, class U> | ||||
| typename lazy_enable_if_c< | ||||
|   is_int<T>::value && is_int<U>::value, | ||||
|   mult_traits<T, U>  | ||||
| >::type | ||||
| mult(const T& x, const U& y) {return x * y;} | ||||
| #endif | ||||
|  | ||||
| double mult(int i, double d) { return (double)i * d; } | ||||
|  | ||||
| int test_main(int, char*[]) | ||||
| { | ||||
|  | ||||
|  | ||||
|   BOOST_CHECK(mult(1, 2) == 2); | ||||
|  | ||||
|   BOOST_CHECK(mult(1, 3.0) == 3.0); | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| @@ -1,100 +0,0 @@ | ||||
| // Boost enable_if library | ||||
|  | ||||
| // Copyright 2003 <20> The Trustees of Indiana University. | ||||
|  | ||||
| // Use, modification, and distribution is subject to the Boost Software | ||||
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //    Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu) | ||||
| //             Jeremiah Willcock (jewillco at osl.iu.edu) | ||||
| //             Andrew Lumsdaine (lums at osl.iu.edu) | ||||
|  | ||||
| // Testing all variations of lazy_enable_if. | ||||
|  | ||||
| #include <boost/test/minimal.hpp> | ||||
| #include <boost/mpl/not.hpp> | ||||
|  | ||||
| #include <boost/utility/enable_if.hpp> | ||||
| #include <boost/type_traits/is_same.hpp> | ||||
|  | ||||
| using boost::lazy_enable_if; | ||||
| using boost::lazy_disable_if; | ||||
|  | ||||
| using boost::lazy_enable_if_c; | ||||
| using boost::lazy_disable_if_c; | ||||
|  | ||||
|  | ||||
| template <class T> | ||||
| struct is_int_or_double { | ||||
|   BOOST_STATIC_CONSTANT(bool,  | ||||
|     value = (boost::is_same<T, int>::value ||  | ||||
|              boost::is_same<T, double>::value)); | ||||
| }; | ||||
|  | ||||
| template <class T> | ||||
| struct some_traits { | ||||
|   typedef typename T::does_not_exist type; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct some_traits<int> { | ||||
|   typedef bool type; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct some_traits<double> { | ||||
|   typedef bool type; | ||||
| }; | ||||
|  | ||||
| template <class T> | ||||
| struct make_bool { | ||||
|   typedef bool type; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct make_bool<int> {}; | ||||
|  | ||||
| template <> | ||||
| struct make_bool<double> {}; | ||||
|  | ||||
| namespace A { | ||||
|  | ||||
|   template<class T> | ||||
|   typename lazy_enable_if<is_int_or_double<T>, some_traits<T> >::type | ||||
|   foo(T t) { return true; } | ||||
|  | ||||
|   template<class T> | ||||
|   typename lazy_enable_if_c<is_int_or_double<T>::value, some_traits<T> >::type | ||||
|   foo2(T t) { return true; } | ||||
| } | ||||
|  | ||||
| namespace B { | ||||
|   template<class T> | ||||
|   typename lazy_disable_if<is_int_or_double<T>, make_bool<T> >::type | ||||
|   foo(T t) { return false; } | ||||
|  | ||||
|   template<class T> | ||||
|   typename lazy_disable_if_c<is_int_or_double<T>::value, make_bool<T> >::type | ||||
|   foo2(T t) { return false; } | ||||
| } | ||||
|  | ||||
| int test_main(int, char*[]) | ||||
| { | ||||
|   using namespace A; | ||||
|   using namespace B; | ||||
|   BOOST_CHECK(foo(1)); | ||||
|   BOOST_CHECK(foo(1.0)); | ||||
|  | ||||
|   BOOST_CHECK(!foo("1"));   | ||||
|   BOOST_CHECK(!foo(static_cast<void*>(0)));   | ||||
|  | ||||
|   BOOST_CHECK(foo2(1)); | ||||
|   BOOST_CHECK(foo2(1.0)); | ||||
|  | ||||
|   BOOST_CHECK(!foo2("1"));   | ||||
|   BOOST_CHECK(!foo2(static_cast<void*>(0)));   | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| @@ -1,43 +0,0 @@ | ||||
| // Boost enable_if library | ||||
|  | ||||
| // Copyright 2003 <20> The Trustees of Indiana University. | ||||
|  | ||||
| // Use, modification, and distribution is subject to the Boost Software | ||||
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //    Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu) | ||||
| //             Jeremiah Willcock (jewillco at osl.iu.edu) | ||||
| //             Andrew Lumsdaine (lums at osl.iu.edu) | ||||
|  | ||||
| #include <boost/test/minimal.hpp> | ||||
|  | ||||
| #include <boost/utility/enable_if.hpp> | ||||
| #include <boost/type_traits/is_arithmetic.hpp> | ||||
|  | ||||
| using boost::enable_if; | ||||
| using boost::disable_if; | ||||
| using boost::is_arithmetic; | ||||
|  | ||||
| struct container { | ||||
|   template <class T> | ||||
|   typename enable_if<is_arithmetic<T>, bool>::type | ||||
|   arithmetic_object(const T&, const int* /* disambiguate */ = 0) {return true;} | ||||
|  | ||||
|   template <class T> | ||||
|   typename disable_if<is_arithmetic<T>, bool>::type | ||||
|   arithmetic_object(const T&) {return false;} | ||||
| }; | ||||
|  | ||||
| int test_main(int, char*[]) | ||||
| { | ||||
|   | ||||
|   BOOST_CHECK(container().arithmetic_object(1)); | ||||
|   BOOST_CHECK(container().arithmetic_object(1.0)); | ||||
|  | ||||
|   BOOST_CHECK(!container().arithmetic_object("1"));   | ||||
|   BOOST_CHECK(!container().arithmetic_object(static_cast<void*>(0)));   | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| @@ -1,47 +0,0 @@ | ||||
| // Boost enable_if library | ||||
|  | ||||
| // Copyright 2003 <20> The Trustees of Indiana University. | ||||
|  | ||||
| // Use, modification, and distribution is subject to the Boost Software | ||||
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //    Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu) | ||||
| //             Jeremiah Willcock (jewillco at osl.iu.edu) | ||||
| //             Andrew Lumsdaine (lums at osl.iu.edu) | ||||
|  | ||||
| #include <boost/test/minimal.hpp> | ||||
| #include <boost/mpl/not.hpp> | ||||
|  | ||||
| #include <boost/utility/enable_if.hpp> | ||||
| #include <boost/type_traits/is_arithmetic.hpp> | ||||
|  | ||||
| using boost::enable_if; | ||||
| using boost::mpl::not_; | ||||
| using boost::is_arithmetic; | ||||
|  | ||||
| namespace A { | ||||
|   template<class T> | ||||
|   typename enable_if<is_arithmetic<T>, bool>::type | ||||
|   arithmetic_object(T t) { return true; } | ||||
| } | ||||
|  | ||||
| namespace B { | ||||
|   template<class T> | ||||
|   typename enable_if<not_<is_arithmetic<T> >, bool>::type | ||||
|   arithmetic_object(T t) { return false; } | ||||
| } | ||||
|  | ||||
| int test_main(int, char*[]) | ||||
| { | ||||
|   using namespace A; | ||||
|   using namespace B; | ||||
|   BOOST_CHECK(arithmetic_object(1)); | ||||
|   BOOST_CHECK(arithmetic_object(1.0)); | ||||
|  | ||||
|   BOOST_CHECK(!arithmetic_object("1"));   | ||||
|   BOOST_CHECK(!arithmetic_object(static_cast<void*>(0)));   | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| @@ -1,43 +0,0 @@ | ||||
| // Boost enable_if library | ||||
|  | ||||
| // Copyright 2003 <20> The Trustees of Indiana University. | ||||
|  | ||||
| // Use, modification, and distribution is subject to the Boost Software | ||||
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //    Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu) | ||||
| //             Jeremiah Willcock (jewillco at osl.iu.edu) | ||||
| //             Andrew Lumsdaine (lums at osl.iu.edu) | ||||
|  | ||||
| #include <boost/test/minimal.hpp> | ||||
| #include <boost/mpl/not.hpp> | ||||
|  | ||||
| #include <boost/utility/enable_if.hpp> | ||||
| #include <boost/type_traits/is_arithmetic.hpp> | ||||
|  | ||||
| using boost::mpl::not_; | ||||
| using boost::enable_if; | ||||
| using boost::is_arithmetic; | ||||
|  | ||||
| template<class T> | ||||
| typename enable_if<is_arithmetic<T>, bool>::type | ||||
| arithmetic_object(T t) { return true; } | ||||
|  | ||||
| template<class T> | ||||
| typename enable_if<not_<is_arithmetic<T> >, bool>::type | ||||
| arithmetic_object(T t) { return false; } | ||||
|  | ||||
|  | ||||
| int test_main(int, char*[]) | ||||
| { | ||||
|   | ||||
|   BOOST_CHECK(arithmetic_object(1)); | ||||
|   BOOST_CHECK(arithmetic_object(1.0)); | ||||
|  | ||||
|   BOOST_CHECK(!arithmetic_object("1"));   | ||||
|   BOOST_CHECK(!arithmetic_object(static_cast<void*>(0)));   | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| @@ -1,67 +0,0 @@ | ||||
| // Boost enable_if library | ||||
|  | ||||
| // Copyright 2003 <20> The Trustees of Indiana University. | ||||
|  | ||||
| // Use, modification, and distribution is subject to the Boost Software | ||||
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //    Authors: Jaakko J<>rvi (jajarvi at osl.iu.edu) | ||||
| //             Jeremiah Willcock (jewillco at osl.iu.edu) | ||||
| //             Andrew Lumsdaine (lums at osl.iu.edu) | ||||
|  | ||||
| #include <boost/test/minimal.hpp> | ||||
|  | ||||
| #include <boost/utility/enable_if.hpp> | ||||
| #include <boost/type_traits/is_arithmetic.hpp> | ||||
|  | ||||
| using boost::enable_if_c; | ||||
| using boost::disable_if_c; | ||||
| using boost::enable_if; | ||||
| using boost::disable_if; | ||||
| using boost::is_arithmetic; | ||||
|  | ||||
| template <class T, class Enable = void> | ||||
| struct tester; | ||||
|  | ||||
| template <class T> | ||||
| struct tester<T, typename enable_if_c<is_arithmetic<T>::value>::type> { | ||||
|   BOOST_STATIC_CONSTANT(bool, value = true); | ||||
| }; | ||||
|  | ||||
| template <class T> | ||||
| struct tester<T, typename disable_if_c<is_arithmetic<T>::value>::type> { | ||||
|   BOOST_STATIC_CONSTANT(bool, value = false); | ||||
| }; | ||||
|  | ||||
| template <class T, class Enable = void> | ||||
| struct tester2; | ||||
|  | ||||
| template <class T> | ||||
| struct tester2<T, typename enable_if<is_arithmetic<T> >::type> { | ||||
|   BOOST_STATIC_CONSTANT(bool, value = true); | ||||
| }; | ||||
|  | ||||
| template <class T> | ||||
| struct tester2<T, typename disable_if<is_arithmetic<T> >::type> { | ||||
|   BOOST_STATIC_CONSTANT(bool, value = false); | ||||
| }; | ||||
|  | ||||
| int test_main(int, char*[]) | ||||
| { | ||||
|   | ||||
|   BOOST_CHECK(tester<int>::value); | ||||
|   BOOST_CHECK(tester<double>::value); | ||||
|  | ||||
|   BOOST_CHECK(!tester<char*>::value); | ||||
|   BOOST_CHECK(!tester<void*>::value); | ||||
|  | ||||
|   BOOST_CHECK(tester2<int>::value); | ||||
|   BOOST_CHECK(tester2<double>::value); | ||||
|  | ||||
|   BOOST_CHECK(!tester2<char*>::value); | ||||
|   BOOST_CHECK(!tester2<void*>::value); | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| @@ -1,150 +0,0 @@ | ||||
| <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN"> | ||||
|  | ||||
| <html> | ||||
| <head> | ||||
| <title>Generator Iterator Adaptor Documentation</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000"> | ||||
|          | ||||
| <img src="../../boost.png" alt="boost.png (6897 bytes)" align="center" width="277" height="86">  | ||||
|  | ||||
| <h1>Generator Iterator Adaptor</h1> | ||||
| Defined in header <a href="../../boost/generator_iterator.hpp">boost/generator_iterator.hpp</a>  | ||||
| <p> | ||||
| The generator iterator adaptor makes it easier to create custom input | ||||
| iterators from 0-ary functions and function objects.  The adaptor | ||||
| takes a | ||||
| <a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a> | ||||
| and creates a model of | ||||
| <a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>. | ||||
| Each increment retrieves an item from the generator and makes it | ||||
| available to be retrieved by dereferencing.  The motivation for this | ||||
| iterator is that some concepts can be more naturally expressed as a | ||||
| generator, while most STL algorithms expect an iterator.  An example | ||||
| is the <a href="../random/index.html">Random Number</a> library. | ||||
|  | ||||
| <h2>Synopsis</h2> | ||||
|  | ||||
| <blockquote> | ||||
| <pre> | ||||
| namespace boost { | ||||
|   template <class Generator> | ||||
|   class generator_iterator_policies; | ||||
|  | ||||
|   template <class Generator> | ||||
|   class generator_iterator_generator; | ||||
|  | ||||
|   template <class Generator> | ||||
|   typename generator_iterator_generator<Generator>::type | ||||
|   make_generator_iterator(Generator & gen); | ||||
| } | ||||
| </pre> | ||||
| </blockquote> | ||||
|  | ||||
| <hr> | ||||
|  | ||||
| <h2>The Generator Iterator Generator Class</h2> | ||||
|  | ||||
| The class generator_iterator_generator is a helper class whose purpose | ||||
| is to construct a generator iterator type. The template parameter for | ||||
| this class is the Generator function object type that is being | ||||
| wrapped.  The generator iterator adaptor only holds a reference (or | ||||
| pointer) to the function object, therefore the function object must | ||||
| outlive the generator iterator adaptor constructed from it. | ||||
|  | ||||
| <pre> | ||||
| template <class Generator> | ||||
| class generator_iterator_generator | ||||
| { | ||||
| public: | ||||
|   typedef <i>unspecified</i> type; // the resulting generator iterator type  | ||||
| } | ||||
| </pre> | ||||
|  | ||||
|  | ||||
| <h3>Template Parameters</h3> | ||||
|  | ||||
| <table border> | ||||
| <tr> | ||||
| <th>Parameter</th> | ||||
| <th>Description</th> | ||||
| </tr> | ||||
|  | ||||
| <tr> | ||||
| <td><tt><a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a></tt>  | ||||
| <td>The generator (0-ary function object) type being | ||||
| wrapped.  The return type of the function must be defined as | ||||
| <tt>Generator::result_type</tt>.  The function object must be a model | ||||
| of | ||||
| <a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>. | ||||
| </td> | ||||
| </table> | ||||
|  | ||||
| <h3>Concept Model</h3> | ||||
| The generator iterator class is a model of | ||||
| <a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>. | ||||
|  | ||||
| <h3>Members</h3> | ||||
| The generator iterator implements the member functions | ||||
| and operators required of the | ||||
| <a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a> | ||||
| concept. | ||||
|  | ||||
| <br> | ||||
|  | ||||
| <hr> | ||||
| <h2><a name="make_generator_iterator">The Generator Iterator Object Generator</a></h2> | ||||
|  | ||||
| The <tt>make_generator_iterator()</tt> function provides a | ||||
| convenient way to create generator iterator objects. The function | ||||
| saves the user the trouble of explicitly writing out the iterator | ||||
| types. | ||||
|  | ||||
| <blockquote> | ||||
| <pre> | ||||
| template <class Generator> | ||||
| typename generator_iterator_generator<Generator>::type | ||||
| make_generator_iterator(Generator & gen); | ||||
| </pre> | ||||
| </blockquote> | ||||
|  | ||||
| <hr> | ||||
|  | ||||
|  | ||||
| <h3>Example</h3> | ||||
|  | ||||
| The following program shows how <code>generator_iterator</code> | ||||
| transforms a generator into an input iterator. | ||||
|  | ||||
| <blockquote> | ||||
| <pre> | ||||
| #include <iostream> | ||||
| #include <boost/generator_iterator.hpp> | ||||
|  | ||||
| class my_generator | ||||
| { | ||||
| public: | ||||
|   typedef int result_type; | ||||
|   my_generator() : state(0) { } | ||||
|   int operator()() { return ++state; } | ||||
| private: | ||||
|   int state; | ||||
| }; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|   my_generator gen; | ||||
|   boost::generator_iterator_generator<my_generator>::type it = boost::make_generator_iterator(gen); | ||||
|   for(int i = 0; i < 10; ++i, ++it) | ||||
|     std::cout << *it << std::endl; | ||||
| } | ||||
| </pre> | ||||
| </blockquote> | ||||
|  | ||||
| <hr> | ||||
|  | ||||
| Written by Jens Maurer. | ||||
|  | ||||
| </body> | ||||
| </html> | ||||
| @@ -1,297 +0,0 @@ | ||||
| <!DOCTYPE HTML PUBLIC "-//SoftQuad Software//DTD HoTMetaL PRO 5.0::19981217::extensions to HTML 4.0//EN" "hmpro5.dtd"> | ||||
|  | ||||
| <HTML> | ||||
|  | ||||
| <HEAD> | ||||
| <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> | ||||
| <LINK REL="stylesheet" TYPE="text/css" HREF="../../boost.css"> | ||||
| <TITLE>Header </TITLE> | ||||
| </HEAD> | ||||
|  | ||||
| <BODY BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080"> | ||||
| <H2 align="left"><IMG SRC="../../boost.png" WIDTH="276" HEIGHT="86"></H2> | ||||
|  | ||||
| <blockquote> | ||||
|   <blockquote> | ||||
|     <blockquote> | ||||
|       <blockquote> | ||||
|         <blockquote> | ||||
|           <blockquote> | ||||
| <H2 align="left">Header <<A | ||||
| HREF="../../boost/utility/in_place_factory.hpp">boost/utility/in_place_factory.hpp</A>> </H2> | ||||
|  | ||||
| <H2 align="left">Header <<A | ||||
| HREF="../../boost/utility/typed_in_place_factory.hpp">boost/utility/typed_in_place_factory.hpp</A>> </H2> | ||||
|  | ||||
|           </blockquote> | ||||
|         </blockquote> | ||||
|       </blockquote> | ||||
|     </blockquote> | ||||
|   </blockquote> | ||||
| </blockquote> | ||||
| <p> </p> | ||||
|  | ||||
| <H2>Contents</H2> | ||||
| <DL CLASS="page-index"> | ||||
|   <DT><A HREF="#mot">Motivation</A></DT> | ||||
|   <DT><A HREF="#framework">Framework</A></DT> | ||||
|   <DT><A HREF="#specification">Specification</A></DT> | ||||
|   <DT><A HREF="#container-usage">Container-side Usage</A></DT> | ||||
|   <DT><A HREF="#user-usage">User-side Usage</A></DT> | ||||
| </DL> | ||||
|  | ||||
| <HR> | ||||
|  | ||||
| <H2><A NAME="mot"></A>Motivation</H2> | ||||
|  | ||||
| <p>Suppose we have a class</p> | ||||
| <pre>struct X | ||||
| { | ||||
|   X ( int, std:::string ) ; | ||||
| } ;</pre> | ||||
| <p>And a container for it which supports an empty state (that is, which can contain zero objects):</p> | ||||
| <pre>struct C | ||||
| { | ||||
|    C() : contained_(0) {} | ||||
|   ~C() { delete contained_ ; } | ||||
|   X* contained_ ; | ||||
| } ;</pre> | ||||
| <p>A container designed to support an empty state typically doesn't require the contained type to be DefaultConstructible, | ||||
| but it typically requires it to be CopyConstructible as a mechanism to | ||||
| initialize the object to store:</p> | ||||
| <pre>struct C | ||||
| { | ||||
|    C() : contained_(0) {} | ||||
|    C ( X const& v ) : contained_ ( new X(v) ) {} | ||||
|   ~C() { delete contained_ ; } | ||||
|   X* contained_ ; | ||||
| } ;</pre> | ||||
| <p>There is a subtle problem with this: since the mechanism used to initialize the stored object is copy construction, | ||||
| there must exist a previously constructed source object to copy from. This | ||||
| object is likely to be temporary and serve no purpose besides being the source</p> | ||||
| <pre>void foo() | ||||
| { | ||||
|   // Temporary object created. | ||||
|   C c( X(123,"hello") ) ; | ||||
| } | ||||
| </pre> | ||||
| <p>A solution to this problem is to support direct construction of the contained | ||||
| object right in the container's storage.<br> | ||||
| In this shceme, the user supplies the arguments for the X constructor | ||||
| directly to the container:</p> | ||||
| <pre>struct C | ||||
| { | ||||
|    C() : contained_(0) {} | ||||
|    C ( X const& v ) : contained_ ( new X(v) ) {} | ||||
|    C ( int a0, std::string a1 ) : contained_ ( new X(a0,a1) ) {} | ||||
|   ~C() { delete contained_ ; } | ||||
|   X* contained_ ; | ||||
| } ;</pre> | ||||
| <pre>void foo() | ||||
| { | ||||
|   // Wrapped object constructed in-place | ||||
|   // No temporary created. | ||||
|   C c(123,"hello") ; | ||||
| } | ||||
| </pre> | ||||
| <p>Clearly, this solution doesn't scale well since the container must duplicate all the constructor overloads from the contained type | ||||
| (at least all those which are to be supported directly in the container).</p> | ||||
|  | ||||
| <H2><A NAME="framework"></A>Framework</H2> | ||||
| <p> | ||||
| This library proposes a framework to allow some containers to directly contruct contained objects in-place without requiring | ||||
| the entire set of constructor overloads ftom the contained type. It also allows the container to remove the CopyConstuctible | ||||
| requirement from the contained type since objects can be directly constructed in-place without need of a copy.<br> | ||||
| The only requirement on the container is that it must provide proper storage (that is, correctly aligned and sized). | ||||
| Naturally, the container will typically support uninitialized storage to avoid the in-place construction to override | ||||
| a fully-constructed object (as this would defeat the purpose of in-place construction) | ||||
| </p> | ||||
| <p>For this purpose, the framework provides two families of classes collectively called: InPlaceFactories and TypedInPlaceFactories.<br> | ||||
| Essentially, these classes hold a sequence of actual parameters and a method to contruct an object in place using these parameters. | ||||
| Each member of the family differs only in the number (and type) of the parameter list. The first family | ||||
| takes the type of the object to construct directly in method provided for that | ||||
| purpose, whereas the second family incorporates that type in the factory class | ||||
| itself..</p> | ||||
| <p>From the container POV, using the framework amounts to calling the factory's method to contruct the object in place. | ||||
| From the user POV, it amounts to creating the right factory object to hold the parameters and pass it to the container.<br> | ||||
| The following simplified example shows the basic idea. A complete example follows the formal specification of the framework:</p> | ||||
| <pre>struct C | ||||
| { | ||||
|    template<class InPlaceFactory> | ||||
|    C ( InPlaceFactory const& aFactoty ) | ||||
|     : | ||||
|     contained_ ( uninitialized_storage() ) | ||||
|    { | ||||
|      aFactory.template apply<X>(contained_); | ||||
|    } | ||||
|  | ||||
|   ~C()  | ||||
|   {  | ||||
|     contained_ -> X::~X(); | ||||
|     delete[] contained_ ;  | ||||
|   } | ||||
|  | ||||
|   char* uninitialized_storage() { return new char[sizeof(X)] ; } | ||||
|  | ||||
|   char* contained_ ; | ||||
| } ; | ||||
|  | ||||
| void foo() | ||||
| { | ||||
|   C c( in_place(123,"hello" ) ; | ||||
| } | ||||
| </pre> | ||||
|  | ||||
| <HR> | ||||
|  | ||||
| <H2><A NAME="specification">Specification</A></H2> | ||||
|  | ||||
| <p>The following is the first member of the family of 'in_place_factory' classes, along with its corresponding helper template function. | ||||
| The rest of the family varies only in the number and type of template (and constructor) parameters.</p> | ||||
| <PRE>namespace boost { | ||||
|  | ||||
| struct in_place_factory_base {} ; | ||||
|  | ||||
| template<class A0> | ||||
| class in_place_factory : public in_place_factory_base | ||||
| { | ||||
|   public:</PRE> | ||||
|  | ||||
| <PRE>    in_place_factory ( A0 const& a0 ) : m_a0(a0) {} | ||||
|  | ||||
|     template< class T > | ||||
|     void apply ( void* address ) const | ||||
|     { | ||||
|       new (address) T(m_a0); | ||||
|     } | ||||
|  | ||||
|   private:</PRE> | ||||
|  | ||||
| <PRE>    A0 const& m_a0 ; | ||||
| } ; | ||||
|  | ||||
| template<class A0> | ||||
| in_place_factory<A0> in_place ( A0 const& a0 ) | ||||
| { | ||||
|   return in_place_factory<A0>(a0); | ||||
| } | ||||
| </PRE> | ||||
|  | ||||
| <p>Similarly, the following is the first member of the family of 'typed_in_place_factory' classes, along with its corresponding | ||||
| helper template function. The rest of the family varies only in the number and type of template (and constructor) parameters.</p> | ||||
| <PRE>namespace boost { | ||||
|  | ||||
| struct typed_in_place_factory_base {} ; | ||||
|  | ||||
| template<class T, class A0> | ||||
| class typed_in_place_factory : public typed_in_place_factory_base | ||||
| { | ||||
|   public:</PRE> | ||||
|  | ||||
| <PRE>    typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {} | ||||
|  | ||||
|     void apply ( void* address ) const | ||||
|     { | ||||
|       new (address) T(m_a0); | ||||
|     } | ||||
|  | ||||
|   private:</PRE> | ||||
|  | ||||
| <PRE>    A0 const& m_a0 ; | ||||
| } ; | ||||
|  | ||||
| template<class T, class A0> | ||||
| typed_in_place_factory<A0> in_place ( A0 const& a0 ) | ||||
| { | ||||
|   return typed_in_place_factory<T,A0>(a0); | ||||
| }</PRE> | ||||
|  | ||||
| <PRE>} | ||||
| </PRE> | ||||
|  | ||||
| <p>As you can see, the 'in_place_factory' and 'typed_in_place_factory' template classes varies only in the way they specify | ||||
| the target type: in the first family, the type is given as a template argument to the apply member function while in the | ||||
| second it is given directly as part of the factory class.<br> | ||||
| When the container holds a unique non-polymorphic type (such as the case of Boost.Optional), it knows the exact dynamic-type | ||||
| of the contained object and can pass it to the apply() method of a (non-typed) factory. | ||||
| In this case, end users can use an 'in_place_factory' instance which can be constructed without the type of the object to construct.<br> | ||||
| However, if the container holds heterogeneous or polymorphic objects (such as the case of Boost.Variant), the dynamic-type | ||||
| of the object to be constructed must be known by the factory itslef. In this case, end users must use a 'typed_in_place_factory' | ||||
| instead.</p> | ||||
|  | ||||
| <HR> | ||||
|  | ||||
| <h2><A NAME="container-usage">Container-side Usage</a></h2> | ||||
|  | ||||
| <p>As shown in the introductory simplified example, the container class must | ||||
| contain methods that accept an instance of | ||||
| these factories and pass the object's storage to the factory's apply method.<br> | ||||
| However, the type of the factory class cannot be completly specified in the container class because that would | ||||
| defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list | ||||
| for the constructor of its contained object.<br> | ||||
| The correct function overload must be based on the only distinctive and common | ||||
| characteristic of all the classes in each family, the base class.<br> | ||||
| Depending on the container class, you can use 'enable_if' to generate the right overload, or use the following | ||||
| dispatch technique (used in the Boost.Optional class): | ||||
| </p> | ||||
| <pre>struct C | ||||
| { | ||||
|    C() : contained_(0) {} | ||||
|    C ( X const& v ) : contained_ ( new X(v) ) {} | ||||
|  | ||||
|    template<class Expr> | ||||
|    C ( Expr const& expr ) | ||||
|     : | ||||
|     contained_ ( uninitialized_storage() ) | ||||
|    { | ||||
|     construct(expr,&expr) | ||||
|    } | ||||
|  | ||||
|   ~C() { delete contained_ ; } | ||||
|  | ||||
|   template<class InPlaceFactory> | ||||
|   void construct ( InPlaceFactory const& aFactory, boost::in_place_factory_base* ) | ||||
|   { | ||||
|     aFactory.template apply<X>(contained_); | ||||
|   } | ||||
|  | ||||
|   template<class TypedInPlaceFactory> | ||||
|   void construct ( TypedInPlaceFactory const& aFactory, boost::typed_in_place_factory_base* ) | ||||
|   { | ||||
|     aFactory.apply(contained_); | ||||
|   } | ||||
|  | ||||
|   X* uninitialized_storage() { return static_cast<X*>(new char[sizeof(X)]) ; } | ||||
|  | ||||
|   X* contained_ ; | ||||
| } ; | ||||
| </pre> | ||||
|  | ||||
| <hr> | ||||
|  | ||||
| <h2><A NAME="user-usage">User-side Usage</a></h2> | ||||
|  | ||||
| <p>End users pass to the container an instance of a factory object holding the actual parameters needed to construct the | ||||
| contained object directly within the container. For this, the helper template function 'in_place' is used.<br> | ||||
| The call 'in_place(a0,a1,a2,...,an)' constructs a (non-typed) 'in_place_factory' instance with the given argument list.<br> | ||||
| The call 'in_place<T>(a0,a1,a2,...,an)' constructs a 'typed_in_place_factory' instance with the given argument list for the | ||||
| type 'T'.</p> | ||||
| <pre>void foo() | ||||
| { | ||||
|   C a( in_place(123,"hello") ) ;    // in_place_factory passed | ||||
|   C b( in_place<X>(456,"world") ) ; // typed_in_place_factory passed | ||||
| } | ||||
| </pre> | ||||
|  | ||||
| <P>Revised September 17, 2004</P> | ||||
| <p><EFBFBD> Copyright Fernando Luis Cacciola Carballal, 2004</p> | ||||
| <p> Use, modification, and distribution are subject to the Boost Software | ||||
| License, Version 1.0. (See accompanying file <a href="../../LICENSE_1_0.txt"> | ||||
| LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt"> | ||||
| www.boost.org/LICENSE_1_0.txt</a>)</p> | ||||
| <P>Developed by <A HREF="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</A>, | ||||
| the latest version of this file can be found at <A | ||||
| HREF="http://www.boost.org">www.boost.org</A>, and the boost | ||||
| <A HREF="http://www.boost.org/more/mailing_lists.htm#main">discussion lists</A></P> | ||||
| </BODY> | ||||
| </HTML> | ||||
							
								
								
									
										34
									
								
								index.html
									
									
									
									
									
								
							
							
						
						
									
										34
									
								
								index.html
									
									
									
									
									
								
							| @@ -1,34 +0,0 @@ | ||||
| <html> | ||||
| 	<head> | ||||
| 		<meta http-equiv="Content-Language" content="en-us"> | ||||
| 		<meta name="GENERATOR" content="Microsoft FrontPage 5.0"> | ||||
| 		<meta name="ProgId" content="FrontPage.Editor.Document"> | ||||
| 		<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | ||||
| 		<title>Boost Utility Library</title> | ||||
| 	</head> | ||||
| 	<body bgcolor="#FFFFFF"> | ||||
| 		<h1><IMG SRC="../../boost.png" WIDTH="276" HEIGHT="86" align="center">Boost  | ||||
| 			Utility Library</h1> | ||||
| 		<p>The Boost Utility Library isn't really a single library at all. It is just a  | ||||
| 			collection for components too small to be called libraries in their own right.</p> | ||||
| 		<p>But that doesn't mean there isn't useful stuff here. Take a look:</p> | ||||
| 		<blockquote> | ||||
| 			<p> | ||||
| 				<a href="assert.html">assert</a><br> | ||||
| 				<a href="base_from_member.html">base_from_member</a><br> | ||||
| 				<a href="call_traits.htm">call_traits</a><br> | ||||
| 				<a href="checked_delete.html">checked_delete</a><br> | ||||
| 				<a href="compressed_pair.htm">compressed_pair</a><br> | ||||
| 				<a href="enable_if.html">enable_if</a><br> | ||||
|                 <a href="iterator_adaptors.htm">iterator_adaptors</a><br> | ||||
| 				<a href="operators.htm">operators</a><br> | ||||
| 				<a href="throw_exception.html">throw_exception</a><br> | ||||
| 				<a href="utility.htm">utility</a><br> | ||||
|                 <a href="value_init.htm">value_init</a></p> | ||||
| 		</blockquote> | ||||
| 		<hr> | ||||
| 		<p>Revised  | ||||
| 			<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 September, 2003<!--webbot bot="Timestamp" endspan i-checksum="38582" --></p> | ||||
| 		<p> </p> | ||||
| 	</body> | ||||
| </html> | ||||
| @@ -1,11 +0,0 @@ | ||||
| <!-- Copyright David Abrahams 2004. Distributed under the Boost --> | ||||
| <!-- Software License, Version 1.0. (See accompanying --> | ||||
| <!-- file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) --> | ||||
| <html> | ||||
| <head> | ||||
| <meta http-equiv="refresh" content="0; URL=../iterator/doc/index.html"> | ||||
| </head> | ||||
| <body> | ||||
| This documentation moved to <a href="../iterator/doc/index.html">../iterator/doc/index.html</a>. | ||||
| </body> | ||||
| </html> | ||||
| @@ -1,324 +0,0 @@ | ||||
| //  Demonstrate and test boost/operators.hpp on std::iterators  --------------// | ||||
|  | ||||
| //  (C) Copyright Jeremy Siek 1999. | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  29 May 01 Factored implementation, added comparison tests, use Test Tools | ||||
| //            library (Daryle Walker) | ||||
| //  12 Dec 99 Initial version with iterator operators (Jeremy Siek) | ||||
|  | ||||
| #define  BOOST_INCLUDE_MAIN | ||||
| #include <boost/test/test_tools.hpp>  // for main | ||||
|  | ||||
| #include <boost/config.hpp>     // for BOOST_STATIC_CONSTANT | ||||
| #include <boost/cstdlib.hpp>    // for boost::exit_success | ||||
| #include <boost/operators.hpp>  // for boost::random_access_iterator_helper | ||||
|  | ||||
| #include <cstddef>    // for std::ptrdiff_t, std::size_t | ||||
| #include <cstring>    // for std::strcmp | ||||
| #include <iostream>   // for std::cout (std::endl, ends, and flush indirectly) | ||||
| #include <string>     // for std::string | ||||
| #include <sstream>    // for std::stringstream | ||||
|  | ||||
| # ifdef BOOST_NO_STDC_NAMESPACE | ||||
|     namespace std { using ::strcmp; } | ||||
| # endif | ||||
|  | ||||
|  | ||||
| // Iterator test class | ||||
| template <class T, class R, class P> | ||||
| struct test_iter | ||||
|   : public boost::random_access_iterator_helper< | ||||
|      test_iter<T,R,P>, T, std::ptrdiff_t, P, R> | ||||
| { | ||||
|   typedef test_iter self; | ||||
|   typedef R Reference; | ||||
|   typedef std::ptrdiff_t Distance; | ||||
|  | ||||
| public: | ||||
|   explicit test_iter(T* i =0) : _i(i) { } | ||||
|   test_iter(const self& x) : _i(x._i) { } | ||||
|   self& operator=(const self& x) { _i = x._i; return *this; } | ||||
|   Reference operator*() const { return *_i; } | ||||
|   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: | ||||
|   P _i; | ||||
| }; | ||||
|  | ||||
| // Iterator operator testing classes | ||||
| class test_opr_base | ||||
| { | ||||
| protected: | ||||
|     // Test data and types | ||||
|     BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u ); | ||||
|  | ||||
|     typedef std::string  fruit_array_type[ fruit_length ]; | ||||
|  | ||||
|     static  fruit_array_type    fruit; | ||||
|  | ||||
| };  // test_opr_base | ||||
|  | ||||
| #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | ||||
| //  A definition is required even for integral static constants | ||||
| const std::size_t test_opr_base::fruit_length; | ||||
| #endif | ||||
|  | ||||
| template <typename T, typename R = T&, typename P = T*> | ||||
| class test_opr | ||||
|     : public test_opr_base | ||||
| { | ||||
|     typedef test_opr<T, R, P>  self_type; | ||||
|  | ||||
| public: | ||||
|     // Types | ||||
|     typedef T  value_type; | ||||
|     typedef R  reference; | ||||
|     typedef P  pointer; | ||||
|  | ||||
|     typedef test_iter<T, R, P>  iter_type; | ||||
|  | ||||
|     // Test controller | ||||
|     static  void  master_test( char const name[] ); | ||||
|  | ||||
| private: | ||||
|     // Test data | ||||
|     static iter_type const  fruit_begin; | ||||
|     static iter_type const  fruit_end; | ||||
|  | ||||
|     // Test parts | ||||
|     static  void  post_increment_test(); | ||||
|     static  void  post_decrement_test(); | ||||
|     static  void  indirect_referral_test(); | ||||
|     static  void  offset_addition_test(); | ||||
|     static  void  reverse_offset_addition_test(); | ||||
|     static  void  offset_subtraction_test(); | ||||
|     static  void  comparison_test(); | ||||
|     static  void  indexing_test(); | ||||
|  | ||||
| };  // test_opr | ||||
|  | ||||
|  | ||||
| // Class-static data definitions | ||||
| test_opr_base::fruit_array_type | ||||
|  test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" }; | ||||
|  | ||||
| template <typename T, typename R, typename P> | ||||
|   typename test_opr<T, R, P>::iter_type const | ||||
|  test_opr<T, R, P>::fruit_begin = test_iter<T,R,P>( fruit ); | ||||
|  | ||||
| template <typename T, typename R, typename P> | ||||
| typename test_opr<T, R, P>::iter_type const | ||||
|  test_opr<T, R, P>::fruit_end = test_iter<T,R,P>( fruit + fruit_length ); | ||||
|  | ||||
|  | ||||
| // Main testing function | ||||
| int | ||||
| test_main( int , char * [] ) | ||||
| { | ||||
|     using std::string; | ||||
|  | ||||
|     typedef test_opr<string, string &, string *>              test1_type; | ||||
|     typedef test_opr<string, string const &, string const *>  test2_type; | ||||
|  | ||||
|     test1_type::master_test( "non-const string" ); | ||||
|     test2_type::master_test( "const string" ); | ||||
|  | ||||
|     return boost::exit_success; | ||||
| } | ||||
|  | ||||
| // Tests for all of the operators added by random_access_iterator_helper | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::master_test | ||||
| ( | ||||
|     char const  name[] | ||||
| ) | ||||
| { | ||||
|     std::cout << "Doing test run for " << name << '.' << std::endl; | ||||
|  | ||||
|     post_increment_test(); | ||||
|     post_decrement_test(); | ||||
|     indirect_referral_test(); | ||||
|     offset_addition_test(); | ||||
|     reverse_offset_addition_test(); | ||||
|     offset_subtraction_test(); | ||||
|     comparison_test(); | ||||
|     indexing_test(); | ||||
| } | ||||
|  | ||||
| // Test post-increment | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::post_increment_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing post-increment test." << std::endl; | ||||
|  | ||||
|     std::stringstream oss; | ||||
|     for ( iter_type i = fruit_begin ; i != fruit_end ; ) | ||||
|     { | ||||
|         oss << *i++ << ' '; | ||||
|     } | ||||
|  | ||||
|     BOOST_CHECK( oss.str() == "apple orange pear peach grape plum "); | ||||
| } | ||||
|  | ||||
| // Test post-decrement | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::post_decrement_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing post-decrement test." << std::endl; | ||||
|  | ||||
|     std::stringstream oss; | ||||
|     for ( iter_type i = fruit_end ; i != fruit_begin ; ) | ||||
|     { | ||||
|         i--; | ||||
|         oss << *i << ' '; | ||||
|     } | ||||
|  | ||||
|     BOOST_CHECK( oss.str() == "plum grape peach pear orange apple "); | ||||
| } | ||||
|  | ||||
| // Test indirect structure referral | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::indirect_referral_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing indirect reference test." << std::endl; | ||||
|  | ||||
|     std::stringstream oss; | ||||
|     for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) | ||||
|     { | ||||
|         oss << i->size() << ' '; | ||||
|     } | ||||
|  | ||||
|     BOOST_CHECK( oss.str() == "5 6 4 5 5 4 "); | ||||
| } | ||||
|  | ||||
| // Test offset addition | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::offset_addition_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing offset addition test." << std::endl; | ||||
|  | ||||
|     std::ptrdiff_t const  two = 2; | ||||
|     std::stringstream oss; | ||||
|     for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two ) | ||||
|     { | ||||
|         oss << *i << ' '; | ||||
|     } | ||||
|  | ||||
|     BOOST_CHECK( oss.str() == "apple pear grape "); | ||||
| } | ||||
|  | ||||
| // Test offset addition, in reverse order | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::reverse_offset_addition_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing reverse offset addition test." << std::endl; | ||||
|  | ||||
|     std::ptrdiff_t const  two = 2; | ||||
|     std::stringstream oss; | ||||
|     for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i ) | ||||
|     { | ||||
|         oss << *i << ' '; | ||||
|     } | ||||
|  | ||||
|     BOOST_CHECK( oss.str() == "apple pear grape "); | ||||
| } | ||||
|  | ||||
| // Test offset subtraction | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::offset_subtraction_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing offset subtraction test." << std::endl; | ||||
|  | ||||
|     std::ptrdiff_t const  two = 2; | ||||
|     std::stringstream oss; | ||||
|     for ( iter_type i = fruit_end ; fruit_begin < i ; ) | ||||
|     { | ||||
|         i = i - two; | ||||
|         if ( (fruit_begin < i) || (fruit_begin == i) ) | ||||
|         { | ||||
|             oss << *i << ' '; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     BOOST_CHECK( oss.str() == "grape pear apple "); | ||||
| } | ||||
|  | ||||
| // Test comparisons | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::comparison_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     using std::cout; | ||||
|     using std::ptrdiff_t; | ||||
|  | ||||
|     cout << "\tDoing comparison tests.\n\t\tPass:"; | ||||
|  | ||||
|     for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) | ||||
|     { | ||||
|         ptrdiff_t const  i_offset = i - fruit_begin; | ||||
|  | ||||
|         cout << ' ' << *i << std::flush; | ||||
|         for ( iter_type j = fruit_begin ; j != fruit_end ; ++j ) | ||||
|         { | ||||
|             ptrdiff_t const  j_offset = j - fruit_begin; | ||||
|  | ||||
|             BOOST_CHECK( (i != j) == (i_offset != j_offset) ); | ||||
|             BOOST_CHECK( (i > j) == (i_offset > j_offset) ); | ||||
|             BOOST_CHECK( (i <= j) == (i_offset <= j_offset) ); | ||||
|             BOOST_CHECK( (i >= j) == (i_offset >= j_offset) ); | ||||
|         } | ||||
|     } | ||||
|     cout << std::endl; | ||||
| } | ||||
|  | ||||
| // Test indexing | ||||
| template <typename T, typename R, typename P> | ||||
| void | ||||
| test_opr<T, R, P>::indexing_test | ||||
| ( | ||||
| ) | ||||
| { | ||||
|     std::cout << "\tDoing indexing test." << std::endl; | ||||
|  | ||||
|     std::stringstream oss; | ||||
|     for ( std::size_t k = 0u ; k < fruit_length ; ++k ) | ||||
|     { | ||||
|         oss << fruit_begin[ k ] << ' '; | ||||
|     } | ||||
|  | ||||
|     BOOST_CHECK( oss.str() == "apple orange pear peach grape plum "); | ||||
| } | ||||
| @@ -1,36 +0,0 @@ | ||||
| //  boost class noncopyable test program  ------------------------------------// | ||||
|  | ||||
| //  (C) Copyright Beman Dawes 1999. Distributed under the Boost | ||||
| //  Software License, Version 1.0. (See accompanying file | ||||
| //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //  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/noncopyable.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 : private 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,386 +0,0 @@ | ||||
| //  (C) Copyright David Abrahams 2001. | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  1  Apr 2001 Fixes for ICL; use BOOST_STATIC_CONSTANT | ||||
| //  11 Feb 2001 Fixes for Borland (David Abrahams) | ||||
| //  23 Jan 2001 Added test for wchar_t (David Abrahams) | ||||
| //  23 Jan 2001 Now statically selecting a test for signed numbers to avoid | ||||
| //              warnings with fancy compilers. Added commentary and | ||||
| //              additional dumping of traits data for tested types (David | ||||
| //              Abrahams). | ||||
| //  21 Jan 2001 Initial version (David Abrahams) | ||||
|  | ||||
| #include <boost/detail/numeric_traits.hpp> | ||||
| #include <cassert> | ||||
| #include <boost/type_traits.hpp> | ||||
| #include <boost/static_assert.hpp> | ||||
| #include <boost/cstdint.hpp> | ||||
| #include <boost/utility.hpp> | ||||
| #include <boost/lexical_cast.hpp> | ||||
| #include <climits> | ||||
| #include <typeinfo> | ||||
| #include <iostream> | ||||
| #include <string> | ||||
| #ifndef BOOST_NO_LIMITS | ||||
| # include <limits> | ||||
| #endif | ||||
|  | ||||
| // ================================================================================= | ||||
| // template class complement_traits<Number> -- | ||||
| // | ||||
| //    statically computes the max and min for 1s and 2s-complement binary | ||||
| //    numbers. This helps on platforms without <limits> support. It also shows | ||||
| //    an example of a recursive template that works with MSVC! | ||||
| // | ||||
|  | ||||
| template <unsigned size> struct complement; // forward | ||||
|  | ||||
| // The template complement, below, does all the real work, using "poor man's | ||||
| // partial specialization". We need complement_traits_aux<> so that MSVC doesn't | ||||
| // complain about undefined min/max as we're trying to recursively define them.  | ||||
| template <class Number, unsigned size> | ||||
| struct complement_traits_aux | ||||
| { | ||||
|     BOOST_STATIC_CONSTANT(Number, max = complement<size>::template traits<Number>::max); | ||||
|     BOOST_STATIC_CONSTANT(Number, min = complement<size>::template traits<Number>::min); | ||||
| }; | ||||
|  | ||||
| template <unsigned size> | ||||
| struct complement | ||||
| { | ||||
|     template <class Number> | ||||
|     struct traits | ||||
|     { | ||||
|      private: | ||||
|         // indirection through complement_traits_aux necessary to keep MSVC happy | ||||
|         typedef complement_traits_aux<Number, size - 1> prev; | ||||
|      public: | ||||
|         BOOST_STATIC_CONSTANT(Number, max = | ||||
|                             Number(Number(prev::max) << CHAR_BIT) | ||||
|                             + Number(UCHAR_MAX)); | ||||
|          | ||||
|         BOOST_STATIC_CONSTANT(Number, min = Number(Number(prev::min) << CHAR_BIT)); | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| // Template class complement_base<> -- defines values for min and max for | ||||
| // complement<1>, at the deepest level of recursion. Uses "poor man's partial | ||||
| // specialization" again. | ||||
| template <bool is_signed> struct complement_base; | ||||
|  | ||||
| template <> struct complement_base<false> | ||||
| { | ||||
|     template <class Number> | ||||
|     struct values | ||||
|     { | ||||
|         BOOST_STATIC_CONSTANT(Number, min = 0); | ||||
|         BOOST_STATIC_CONSTANT(Number, max = UCHAR_MAX); | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| template <> struct complement_base<true> | ||||
| { | ||||
|     template <class Number> | ||||
|     struct values | ||||
|     { | ||||
|         BOOST_STATIC_CONSTANT(Number, min = SCHAR_MIN); | ||||
|         BOOST_STATIC_CONSTANT(Number, max = SCHAR_MAX); | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| // Base specialization of complement, puts an end to the recursion. | ||||
| template <> | ||||
| struct complement<1> | ||||
| { | ||||
|     template <class Number> | ||||
|     struct traits | ||||
|     { | ||||
|         BOOST_STATIC_CONSTANT(bool, is_signed = boost::detail::is_signed<Number>::value); | ||||
|         BOOST_STATIC_CONSTANT(Number, min = | ||||
|                             complement_base<is_signed>::template values<Number>::min); | ||||
|         BOOST_STATIC_CONSTANT(Number, max = | ||||
|                             complement_base<is_signed>::template values<Number>::max); | ||||
|     }; | ||||
| }; | ||||
|  | ||||
| // Now here's the "pretty" template you're intended to actually use. | ||||
| //   complement_traits<Number>::min, complement_traits<Number>::max are the | ||||
| //   minimum and maximum values of Number if Number is a built-in integer type. | ||||
| template <class Number> | ||||
| struct complement_traits | ||||
| { | ||||
|     BOOST_STATIC_CONSTANT(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max)); | ||||
|     BOOST_STATIC_CONSTANT(Number, min = (complement_traits_aux<Number, sizeof(Number)>::min)); | ||||
| }; | ||||
|  | ||||
| // ================================================================================= | ||||
|  | ||||
| // Support for streaming various numeric types in exactly the format I want. I | ||||
| // needed this in addition to all the assertions so that I could see exactly | ||||
| // what was going on. | ||||
| // | ||||
| // Numbers go through a 2-stage conversion process (by default, though, no real | ||||
| // conversion). | ||||
| // | ||||
| template <class T> struct stream_as { | ||||
|     typedef T t1; | ||||
|     typedef T t2; | ||||
| }; | ||||
|  | ||||
| // char types first get converted to unsigned char, then to unsigned. | ||||
| template <> struct stream_as<char> { | ||||
|     typedef unsigned char t1; | ||||
|     typedef unsigned t2; | ||||
| }; | ||||
| template <> struct stream_as<unsigned char> { | ||||
|     typedef unsigned char t1; typedef unsigned t2; | ||||
| }; | ||||
| template <> struct stream_as<signed char>  { | ||||
|     typedef unsigned char t1; typedef unsigned t2; | ||||
| }; | ||||
|  | ||||
| #if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in | ||||
|  | ||||
| // With this library implementation, __int64 and __uint64 get streamed as strings | ||||
| template <> struct stream_as<boost::uintmax_t> { | ||||
|     typedef std::string t1; | ||||
|     typedef std::string t2; | ||||
| }; | ||||
|  | ||||
| template <> struct stream_as<boost::intmax_t>  { | ||||
|     typedef std::string t1; | ||||
|     typedef std::string t2; | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| // Standard promotion process for streaming | ||||
| template <class T> struct promote | ||||
| { | ||||
|     static typename stream_as<T>::t1 from(T x) { | ||||
|         typedef typename stream_as<T>::t1 t1; | ||||
|         return t1(x); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| #if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in | ||||
|  | ||||
| // On this platform, stream them as long/unsigned long if they fit. | ||||
| // Otherwise, write a string. | ||||
| template <> struct promote<boost::uintmax_t> { | ||||
|     std::string static from(const boost::uintmax_t x) { | ||||
|         if (x > ULONG_MAX) | ||||
|             return std::string("large unsigned value"); | ||||
|         else | ||||
|             return boost::lexical_cast<std::string>((unsigned long)x); | ||||
|     } | ||||
| }; | ||||
| template <> struct promote<boost::intmax_t> { | ||||
|     std::string static from(const boost::intmax_t x) { | ||||
|         if (x > boost::intmax_t(ULONG_MAX)) | ||||
|             return std::string("large positive signed value"); | ||||
|         else if (x >= 0) | ||||
|             return boost::lexical_cast<std::string>((unsigned long)x); | ||||
|          | ||||
|         if (x < boost::intmax_t(LONG_MIN)) | ||||
|             return std::string("large negative signed value"); | ||||
|         else | ||||
|             return boost::lexical_cast<std::string>((long)x); | ||||
|     } | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| // This is the function which converts types to the form I want to stream them in. | ||||
| template <class T> | ||||
| typename stream_as<T>::t2 stream_number(T x) | ||||
| { | ||||
|     return promote<T>::from(x); | ||||
| } | ||||
| // ================================================================================= | ||||
|  | ||||
| // | ||||
| // Tests for built-in signed and unsigned types | ||||
| // | ||||
|  | ||||
| // Tag types for selecting tests | ||||
| struct unsigned_tag {}; | ||||
| struct signed_tag {}; | ||||
|  | ||||
| // Tests for unsigned numbers. The extra default Number parameter works around | ||||
| // an MSVC bug. | ||||
| template <class Number> | ||||
| void test_aux(unsigned_tag, Number*) | ||||
| { | ||||
|     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*) | ||||
| { | ||||
|     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*) | ||||
| { | ||||
|     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*) | ||||
| { | ||||
|     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(), 0); | ||||
| } | ||||
|  | ||||
|  | ||||
| // 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< | ||||
| #if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 | ||||
|         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(), 0); | ||||
|     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(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_INTEGRAL_INT64_T) | ||||
|     test< ::boost::long_long_type>(); | ||||
|     test< ::boost::ulong_long_type>(); | ||||
| #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; | ||||
| } | ||||
							
								
								
									
										2133
									
								
								operators.htm
									
									
									
									
									
								
							
							
						
						
									
										2133
									
								
								operators.htm
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,897 +0,0 @@ | ||||
| //  Demonstrate and test boost/operators.hpp  -------------------------------// | ||||
|  | ||||
| //  Copyright Beman Dawes 1999.  Distributed under the Boost | ||||
| //  Software License, Version 1.0. (See accompanying file | ||||
| //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //  See http://www.boost.org/libs/utility for documentation. | ||||
|  | ||||
| //  Revision History | ||||
| //  01 Oct 01 Added tests for "left" operators | ||||
| //            and new grouped operators. (Helmut Zeisel) | ||||
| //  20 May 01 Output progress messages.  Added tests for new operator | ||||
| //            templates.  Updated random number generator.  Changed tests to | ||||
| //            use Boost Test Tools library.  (Daryle Walker) | ||||
| //  04 Jun 00 Added regression test for a bug I found (David Abrahams) | ||||
| //  17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy) | ||||
| //  ?? ??? 00 Major update to randomly test all one- and two- argument forms by | ||||
| //            wrapping integral types and comparing the results of operations | ||||
| //            to the results for the raw types (David Abrahams) | ||||
| //  12 Dec 99 Minor update, output confirmation message. | ||||
| //  15 Nov 99 Initial version | ||||
|  | ||||
| #define BOOST_INCLUDE_MAIN | ||||
|  | ||||
| #include <boost/config.hpp>                      // for BOOST_MSVC | ||||
| #include <boost/cstdlib.hpp>                     // for boost::exit_success | ||||
| #include <boost/operators.hpp>                   // for the tested items | ||||
| #include <boost/random/linear_congruential.hpp>  // for boost::minstd_rand | ||||
| #include <boost/test/test_tools.hpp>             // for main | ||||
|  | ||||
| #include <iostream>  // for std::cout (std::endl indirectly) | ||||
|  | ||||
|  | ||||
| namespace | ||||
| { | ||||
|     // 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; } | ||||
|     short true_value(short x) { return x; } | ||||
|     unsigned int true_value(unsigned int x) { return x; } | ||||
|     unsigned long true_value(unsigned long x) { return x; } | ||||
|     unsigned char true_value(unsigned char x) { return x; } | ||||
|     unsigned short true_value(unsigned short x) { return x; } | ||||
|  | ||||
|     // The use of operators<> here tended to obscure | ||||
|     // interactions with certain compiler bugs | ||||
|     template <class T> | ||||
|     class Wrapped1 | ||||
|         : boost::operators<Wrapped1<T> > | ||||
|         , boost::shiftable<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<<=(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> | ||||
|         , boost::shiftable1<Wrapped2<T, U> | ||||
|         , boost::shiftable2<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<<=(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; } | ||||
|         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(); } | ||||
|      | ||||
|     template <class T> | ||||
|     class Wrapped3 | ||||
|         : boost::equivalent<Wrapped3<T> > | ||||
|         , boost::partially_ordered<Wrapped3<T> > | ||||
|         , boost::equality_comparable<Wrapped3<T> > | ||||
|     { | ||||
|     public: | ||||
|         explicit Wrapped3( T v = T() ) : _value(v) {} | ||||
|         T value() const { return _value; } | ||||
|  | ||||
|         bool operator<(const Wrapped3& x) const { return _value < x._value; } | ||||
|          | ||||
|     private: | ||||
|         T _value; | ||||
|     }; | ||||
|     template <class T> | ||||
|     T true_value(Wrapped3<T> x) { return x.value(); }     | ||||
|  | ||||
|     template <class T, class U> | ||||
|     class Wrapped4 | ||||
|         : boost::equality_comparable1<Wrapped4<T, U> | ||||
|         , boost::equivalent1<Wrapped4<T, U> | ||||
|         , boost::partially_ordered1<Wrapped4<T, U> > > > | ||||
|         , boost::partially_ordered2<Wrapped4<T, U>, U | ||||
|         , boost::equivalent2<Wrapped4<T, U>, U | ||||
|         , boost::equality_comparable2<Wrapped4<T, U>, U> > > | ||||
|     { | ||||
|     public: | ||||
|         explicit Wrapped4( T v = T() ) : _value(v) {} | ||||
|         T value() const { return _value; } | ||||
|  | ||||
|         bool operator<(const Wrapped4& x) const { return _value < x._value; } | ||||
|           | ||||
|         bool operator<(U u) const { return _value < u; } | ||||
|         bool operator>(U u) const { return _value > u; } | ||||
|  | ||||
|     private: | ||||
|         T _value; | ||||
|     }; | ||||
|     template <class T, class U> | ||||
|     T true_value(Wrapped4<T,U> x) { return x.value(); } | ||||
|      | ||||
|     // U must be convertible to T | ||||
|     template <class T, class U> | ||||
|     class Wrapped5 | ||||
|         : boost::ordered_field_operators2<Wrapped5<T, U>, U> | ||||
|         , boost::ordered_field_operators1<Wrapped5<T, U> > | ||||
|     { | ||||
|     public: | ||||
|         explicit Wrapped5( T v = T() ) : _value(v) {} | ||||
|  | ||||
|         // Conversion from U to Wrapped5<T,U> | ||||
|         Wrapped5(U u) : _value(u) {} | ||||
|  | ||||
|         T value() const { return _value; } | ||||
|         bool operator<(const Wrapped5& x) const { return _value < x._value; } | ||||
|         bool operator<(U u) const { return _value < u; } | ||||
|         bool operator>(U u) const { return _value > u; } | ||||
|         bool operator==(const Wrapped5& u) const { return _value == u._value; } | ||||
|         bool operator==(U u) const { return _value == u; } | ||||
|         Wrapped5& operator/=(const Wrapped5& u) { _value /= u._value; return *this;} | ||||
|         Wrapped5& operator/=(U u) { _value /= u; return *this;} | ||||
|         Wrapped5& operator*=(const Wrapped5& u) { _value *= u._value; return *this;} | ||||
|         Wrapped5& operator*=(U u) { _value *= u; return *this;} | ||||
|         Wrapped5& operator-=(const Wrapped5& u) { _value -= u._value; return *this;} | ||||
|         Wrapped5& operator-=(U u) { _value -= u; return *this;} | ||||
|         Wrapped5& operator+=(const Wrapped5& u) { _value += u._value; return *this;} | ||||
|         Wrapped5& operator+=(U u) { _value += u; return *this;} | ||||
|  | ||||
|     private: | ||||
|         T _value; | ||||
|     }; | ||||
|     template <class T, class U> | ||||
|     T true_value(Wrapped5<T,U> x) { return x.value(); } | ||||
|      | ||||
|     // U must be convertible to T | ||||
|     template <class T, class U> | ||||
|     class Wrapped6 | ||||
|         : boost::ordered_euclidian_ring_operators2<Wrapped6<T, U>, U> | ||||
|         , boost::ordered_euclidian_ring_operators1<Wrapped6<T, U> > | ||||
|     { | ||||
|     public: | ||||
|         explicit Wrapped6( T v = T() ) : _value(v) {} | ||||
|  | ||||
|         // Conversion from U to Wrapped6<T,U> | ||||
|         Wrapped6(U u) : _value(u) {} | ||||
|  | ||||
|         T value() const { return _value; } | ||||
|         bool operator<(const Wrapped6& x) const { return _value < x._value; } | ||||
|         bool operator<(U u) const { return _value < u; } | ||||
|         bool operator>(U u) const { return _value > u; } | ||||
|         bool operator==(const Wrapped6& u) const { return _value == u._value; } | ||||
|         bool operator==(U u) const { return _value == u; } | ||||
|         Wrapped6& operator%=(const Wrapped6& u) { _value %= u._value; return *this;} | ||||
|         Wrapped6& operator%=(U u) { _value %= u; return *this;} | ||||
|         Wrapped6& operator/=(const Wrapped6& u) { _value /= u._value; return *this;} | ||||
|         Wrapped6& operator/=(U u) { _value /= u; return *this;} | ||||
|         Wrapped6& operator*=(const Wrapped6& u) { _value *= u._value; return *this;} | ||||
|         Wrapped6& operator*=(U u) { _value *= u; return *this;} | ||||
|         Wrapped6& operator-=(const Wrapped6& u) { _value -= u._value; return *this;} | ||||
|         Wrapped6& operator-=(U u) { _value -= u; return *this;} | ||||
|         Wrapped6& operator+=(const Wrapped6& u) { _value += u._value; return *this;} | ||||
|         Wrapped6& operator+=(U u) { _value += u; return *this;} | ||||
|  | ||||
|     private: | ||||
|         T _value; | ||||
|     }; | ||||
|     template <class T, class U> | ||||
|     T true_value(Wrapped6<T,U> x) { return x.value(); } | ||||
|      | ||||
|     //  MyInt uses only the single template-argument form of all_operators<> | ||||
|     typedef Wrapped1<int> MyInt; | ||||
|  | ||||
|     typedef Wrapped2<long, long> MyLong; | ||||
|  | ||||
|     typedef Wrapped3<signed char> MyChar; | ||||
|  | ||||
|     typedef Wrapped4<short, short> MyShort; | ||||
|  | ||||
|     typedef Wrapped5<double, int> MyDoubleInt; | ||||
|  | ||||
|     typedef Wrapped6<long, int> MyLongInt; | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         BOOST_CHECK( true_value(y1) == true_value(y2) ); | ||||
|         BOOST_CHECK( 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) | ||||
|     { | ||||
|         BOOST_CHECK( (x1 < y1) == (x2 < y2) ); | ||||
|         BOOST_CHECK( (x1 <= y1) == (x2 <= y2) ); | ||||
|         BOOST_CHECK( (x1 >= y1) == (x2 >= y2) ); | ||||
|         BOOST_CHECK( (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) | ||||
|     { | ||||
|         BOOST_CHECK( (x1 == y1) == (x2 == y2) ); | ||||
|         BOOST_CHECK( (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) | ||||
|     { | ||||
|         BOOST_CHECK( (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 A, class B> | ||||
|   void test_value_equality(A a, B b) | ||||
|   { | ||||
|       BOOST_CHECK(a.value() == b); | ||||
|   } | ||||
|    | ||||
| #define TEST_OP_R(op) test_value_equality(x1 op y1, x2 op y2) | ||||
| #define TEST_OP_L(op) test_value_equality(y1 op x1, y2 op x2) | ||||
|    | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         TEST_OP_R(+); | ||||
|     } | ||||
|      | ||||
|     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 ); | ||||
|         TEST_OP_R(-); | ||||
|     } | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_subtractable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         TEST_OP_L(-); | ||||
|     } | ||||
|  | ||||
|     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 ) | ||||
|             TEST_OP_R(/); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_dividable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         if ( x2 != 0 ) | ||||
|             TEST_OP_L(/); | ||||
|     } | ||||
|  | ||||
|     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 ) | ||||
|             TEST_OP_R(%); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_modable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         if ( x2 != 0 ) | ||||
|             TEST_OP_L(%); | ||||
|     } | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         TEST_OP_R(^); | ||||
|     } | ||||
|      | ||||
|     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) | ||||
|     { | ||||
|         TEST_OP_R(&); | ||||
|     } | ||||
|      | ||||
|     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) | ||||
|     { | ||||
|         TEST_OP_R(|); | ||||
|     } | ||||
|      | ||||
|     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 Y1, class X2, class Y2> | ||||
|     void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         TEST_OP_R(<<); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check( x1, y1, x2, y2 ); | ||||
|         TEST_OP_R(>>); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class X2> | ||||
|     void test_incrementable(X1 x1, X2 x2) | ||||
|     { | ||||
|         sanity_check( x1, x1, x2, x2 ); | ||||
|         BOOST_CHECK( (x1++).value() == x2++ ); | ||||
|         BOOST_CHECK( x1.value() == x2 ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class X2> | ||||
|     void test_decrementable(X1 x1, X2 x2) | ||||
|     { | ||||
|         sanity_check( x1, x1, x2, x2 ); | ||||
|         BOOST_CHECK( (x1--).value() == x2-- ); | ||||
|         BOOST_CHECK( 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_left_shiftable( x1, y1, x2, y2 ); | ||||
|         test_right_shiftable( x1, y1, x2, y2 ); | ||||
|         test_incrementable( x1, x2 ); | ||||
|         test_decrementable( x1, x2 ); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_left(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         test_subtractable_left( x1, y1, x2, y2 ); | ||||
|         test_dividable_left( x1, y1, x2, y2 ); | ||||
|         test_modable_left( x1, y1, x2, y2 ); | ||||
|      } | ||||
|  | ||||
|     template <class Big, class Small> | ||||
|     struct tester | ||||
|     { | ||||
|         void operator()(boost::minstd_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 ); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     template <class Big, class Small> | ||||
|     struct tester_left | ||||
|     { | ||||
|         void operator()(boost::minstd_rand& randomizer) const | ||||
|         { | ||||
|             Big    b1 = Big( randomizer() ); | ||||
|             Small  s = Small( randomizer() ); | ||||
|              | ||||
|             test_left( Wrapped6<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 < 1300) | ||||
| 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>; | ||||
|  | ||||
| template Wrapped6<long, int>; | ||||
| template Wrapped6<long, signed char>; | ||||
| template Wrapped6<int, signed char>; | ||||
| template Wrapped6<unsigned long, unsigned int>; | ||||
| template Wrapped6<unsigned long, unsigned char>; | ||||
| template Wrapped6<unsigned int, unsigned char>; | ||||
| #endif | ||||
|  | ||||
| #define PRIVATE_EXPR_TEST(e, t)  BOOST_CHECK( ((e), (t)) ) | ||||
|  | ||||
| int | ||||
| test_main( int , char * [] ) | ||||
| { | ||||
|     using std::cout; | ||||
|     using std::endl; | ||||
|  | ||||
|     // Regression test. | ||||
|     Point x; | ||||
|     x = x + Point(3, 4); | ||||
|     x = x - Point(3, 4); | ||||
|      | ||||
|     cout << "Created point, and operated on it." << endl; | ||||
|      | ||||
|     for (int n = 0; n < 1000; ++n)  // was 10,000 but took too long (Beman) | ||||
|     { | ||||
|         boost::minstd_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); | ||||
|  | ||||
|         tester_left<long, int>()(r); | ||||
|         tester_left<long, signed char>()(r); | ||||
|         tester_left<int, signed char>()(r); | ||||
|  | ||||
|         tester_left<unsigned long, unsigned int>()(r); | ||||
|         tester_left<unsigned long, unsigned char>()(r); | ||||
|         tester_left<unsigned int, unsigned char>()(r); | ||||
|     } | ||||
|      | ||||
|     cout << "Did random tester loop." << endl; | ||||
|  | ||||
|     MyInt i1(1); | ||||
|     MyInt i2(2); | ||||
|     MyInt i; | ||||
|  | ||||
|     BOOST_CHECK( i1.value() == 1 ); | ||||
|     BOOST_CHECK( i2.value() == 2 ); | ||||
|     BOOST_CHECK( i.value() == 0 ); | ||||
|  | ||||
|     cout << "Created MyInt objects.\n"; | ||||
|  | ||||
|     PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) ); | ||||
|  | ||||
|     BOOST_CHECK( i2 == i ); | ||||
|     BOOST_CHECK( i1 != i2 ); | ||||
|     BOOST_CHECK( i1 <  i2 ); | ||||
|     BOOST_CHECK( i1 <= i2 ); | ||||
|     BOOST_CHECK( i <= i2 ); | ||||
|     BOOST_CHECK( i2 >  i1 ); | ||||
|     BOOST_CHECK( i2 >= i1 ); | ||||
|     BOOST_CHECK( i2 >= i ); | ||||
|  | ||||
|     PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) ); | ||||
|     PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) ); | ||||
|  | ||||
|     PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) ); | ||||
|     PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) ); | ||||
|  | ||||
|     cout << "Performed tests on MyInt objects.\n"; | ||||
|  | ||||
|     MyLong j1(1); | ||||
|     MyLong j2(2); | ||||
|     MyLong j; | ||||
|  | ||||
|     BOOST_CHECK( j1.value() == 1 ); | ||||
|     BOOST_CHECK( j2.value() == 2 ); | ||||
|     BOOST_CHECK( j.value() == 0 ); | ||||
|  | ||||
|     cout << "Created MyLong objects.\n"; | ||||
|  | ||||
|     PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) ); | ||||
|      | ||||
|     BOOST_CHECK( j2 == j ); | ||||
|     BOOST_CHECK( 2 == j ); | ||||
|     BOOST_CHECK( j2 == 2 );     | ||||
|     BOOST_CHECK( j == j2 ); | ||||
|     BOOST_CHECK( j1 != j2 ); | ||||
|     BOOST_CHECK( j1 != 2 ); | ||||
|     BOOST_CHECK( 1 != j2 ); | ||||
|     BOOST_CHECK( j1 <  j2 ); | ||||
|     BOOST_CHECK( 1 <  j2 ); | ||||
|     BOOST_CHECK( j1 <  2 ); | ||||
|     BOOST_CHECK( j1 <= j2 ); | ||||
|     BOOST_CHECK( 1 <= j2 ); | ||||
|     BOOST_CHECK( j1 <= j ); | ||||
|     BOOST_CHECK( j <= j2 ); | ||||
|     BOOST_CHECK( 2 <= j2 ); | ||||
|     BOOST_CHECK( j <= 2 ); | ||||
|     BOOST_CHECK( j2 >  j1 ); | ||||
|     BOOST_CHECK( 2 >  j1 ); | ||||
|     BOOST_CHECK( j2 >  1 ); | ||||
|     BOOST_CHECK( j2 >= j1 ); | ||||
|     BOOST_CHECK( 2 >= j1 ); | ||||
|     BOOST_CHECK( j2 >= 1 ); | ||||
|     BOOST_CHECK( j2 >= j ); | ||||
|     BOOST_CHECK( 2 >= j ); | ||||
|     BOOST_CHECK( j2 >= 2 ); | ||||
|  | ||||
|     BOOST_CHECK( (j1 + 2) == 3 ); | ||||
|     BOOST_CHECK( (1 + j2) == 3 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) ); | ||||
|      | ||||
|     BOOST_CHECK( (j + 2) == 5 ); | ||||
|     BOOST_CHECK( (3 + j2) == 5 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) ); | ||||
|      | ||||
|     BOOST_CHECK( (j - 1) == 4 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) ); | ||||
|      | ||||
|     BOOST_CHECK( (j * 2) == 8 ); | ||||
|     BOOST_CHECK( (4 * j2) == 8 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) ); | ||||
|      | ||||
|     BOOST_CHECK( (j / 2) == 4 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) ); | ||||
|      | ||||
|     BOOST_CHECK( (j % 3) == 1 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) ); | ||||
|      | ||||
|     PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) ); | ||||
|      | ||||
|     BOOST_CHECK( (1 | j2 | j) == 7 ); | ||||
|     BOOST_CHECK( (j1 | 2 | j) == 7 ); | ||||
|     BOOST_CHECK( (j1 | j2 | 4) == 7 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) ); | ||||
|      | ||||
|     BOOST_CHECK( (7 & j2) == 2 ); | ||||
|     BOOST_CHECK( (j & 2) == 2 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) ); | ||||
|      | ||||
|     PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) ); | ||||
|      | ||||
|     BOOST_CHECK( (3 ^ j1) == 2 ); | ||||
|     BOOST_CHECK( (j ^ 1) == 2 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) ); | ||||
|      | ||||
|     PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) ); | ||||
|  | ||||
|     BOOST_CHECK( (j1 << 2) == 4 ); | ||||
|     BOOST_CHECK( (j2 << 1) == 4 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) ); | ||||
|  | ||||
|     BOOST_CHECK( (j >> 2) == 1 ); | ||||
|     BOOST_CHECK( (j2 >> 1) == 1 ); | ||||
|     PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) ); | ||||
|      | ||||
|     cout << "Performed tests on MyLong objects.\n"; | ||||
|  | ||||
|     MyChar k1(1); | ||||
|     MyChar k2(2); | ||||
|     MyChar k; | ||||
|  | ||||
|     BOOST_CHECK( k1.value() == 1 ); | ||||
|     BOOST_CHECK( k2.value() == 2 ); | ||||
|     BOOST_CHECK( k.value() == 0 ); | ||||
|  | ||||
|     cout << "Created MyChar objects.\n"; | ||||
|  | ||||
|     PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) ); | ||||
|  | ||||
|     BOOST_CHECK( k2 == k ); | ||||
|     BOOST_CHECK( k1 != k2 ); | ||||
|     BOOST_CHECK( k1 <  k2 ); | ||||
|     BOOST_CHECK( k1 <= k2 ); | ||||
|     BOOST_CHECK( k <= k2 ); | ||||
|     BOOST_CHECK( k2 >  k1 ); | ||||
|     BOOST_CHECK( k2 >= k1 ); | ||||
|     BOOST_CHECK( k2 >= k ); | ||||
|      | ||||
|     cout << "Performed tests on MyChar objects.\n"; | ||||
|  | ||||
|     MyShort l1(1); | ||||
|     MyShort l2(2); | ||||
|     MyShort l; | ||||
|  | ||||
|     BOOST_CHECK( l1.value() == 1 ); | ||||
|     BOOST_CHECK( l2.value() == 2 ); | ||||
|     BOOST_CHECK( l.value() == 0 ); | ||||
|  | ||||
|     cout << "Created MyShort objects.\n"; | ||||
|  | ||||
|     PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) ); | ||||
|      | ||||
|     BOOST_CHECK( l2 == l ); | ||||
|     BOOST_CHECK( 2 == l ); | ||||
|     BOOST_CHECK( l2 == 2 );     | ||||
|     BOOST_CHECK( l == l2 ); | ||||
|     BOOST_CHECK( l1 != l2 ); | ||||
|     BOOST_CHECK( l1 != 2 ); | ||||
|     BOOST_CHECK( 1 != l2 ); | ||||
|     BOOST_CHECK( l1 <  l2 ); | ||||
|     BOOST_CHECK( 1 <  l2 ); | ||||
|     BOOST_CHECK( l1 <  2 ); | ||||
|     BOOST_CHECK( l1 <= l2 ); | ||||
|     BOOST_CHECK( 1 <= l2 ); | ||||
|     BOOST_CHECK( l1 <= l ); | ||||
|     BOOST_CHECK( l <= l2 ); | ||||
|     BOOST_CHECK( 2 <= l2 ); | ||||
|     BOOST_CHECK( l <= 2 ); | ||||
|     BOOST_CHECK( l2 >  l1 ); | ||||
|     BOOST_CHECK( 2 >  l1 ); | ||||
|     BOOST_CHECK( l2 >  1 ); | ||||
|     BOOST_CHECK( l2 >= l1 ); | ||||
|     BOOST_CHECK( 2 >= l1 ); | ||||
|     BOOST_CHECK( l2 >= 1 ); | ||||
|     BOOST_CHECK( l2 >= l ); | ||||
|     BOOST_CHECK( 2 >= l ); | ||||
|     BOOST_CHECK( l2 >= 2 ); | ||||
|      | ||||
|     cout << "Performed tests on MyShort objects.\n"; | ||||
|      | ||||
|     MyDoubleInt di1(1); | ||||
|     MyDoubleInt di2(2.); | ||||
|     MyDoubleInt half(0.5); | ||||
|     MyDoubleInt di; | ||||
|     MyDoubleInt tmp; | ||||
|  | ||||
|     BOOST_CHECK( di1.value() == 1 ); | ||||
|     BOOST_CHECK( di2.value() == 2 ); | ||||
|     BOOST_CHECK( di2.value() == 2 ); | ||||
|     BOOST_CHECK( di.value() == 0 ); | ||||
|  | ||||
|     cout << "Created MyDoubleInt objects.\n"; | ||||
|  | ||||
|     PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) ); | ||||
|      | ||||
|     BOOST_CHECK( di2 == di ); | ||||
|     BOOST_CHECK( 2 == di ); | ||||
|     BOOST_CHECK( di == 2 ); | ||||
|     BOOST_CHECK( di1 < di2 ); | ||||
|     BOOST_CHECK( 1 < di2 ); | ||||
|     BOOST_CHECK( di1 <= di2 ); | ||||
|     BOOST_CHECK( 1 <= di2 ); | ||||
|     BOOST_CHECK( di2 > di1 ); | ||||
|     BOOST_CHECK( di2 > 1 ); | ||||
|     BOOST_CHECK( di2 >= di1 ); | ||||
|     BOOST_CHECK( di2 >= 1 ); | ||||
|     BOOST_CHECK( di1 / di2 == half ); | ||||
|     BOOST_CHECK( di1 / 2 == half ); | ||||
|     BOOST_CHECK( 1 / di2 == half ); | ||||
|     PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=2) == half) ); | ||||
|     PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=di2) == half) ); | ||||
|     BOOST_CHECK( di1 * di2 == di2 ); | ||||
|     BOOST_CHECK( di1 * 2 == di2 ); | ||||
|     BOOST_CHECK( 1 * di2 == di2 ); | ||||
|     PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=2) == di2) ); | ||||
|     PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=di2) == di2) ); | ||||
|     BOOST_CHECK( di2 - di1 == di1 ); | ||||
|     BOOST_CHECK( di2 - 1 == di1 ); | ||||
|     BOOST_CHECK( 2 - di1 == di1 ); | ||||
|     PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=1) == di1) ); | ||||
|     PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=di1) == di1) ); | ||||
|     BOOST_CHECK( di1 + di1 == di2 ); | ||||
|     BOOST_CHECK( di1 + 1 == di2 ); | ||||
|     BOOST_CHECK( 1 + di1 == di2 ); | ||||
|     PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=1) == di2) ); | ||||
|     PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=di1) == di2) ); | ||||
|  | ||||
|     cout << "Performed tests on MyDoubleInt objects.\n"; | ||||
|  | ||||
|     MyLongInt li1(1); | ||||
|     MyLongInt li2(2); | ||||
|     MyLongInt li; | ||||
|     MyLongInt tmp2; | ||||
|  | ||||
|     BOOST_CHECK( li1.value() == 1 ); | ||||
|     BOOST_CHECK( li2.value() == 2 ); | ||||
|     BOOST_CHECK( li.value() == 0 ); | ||||
|  | ||||
|     cout << "Created MyLongInt objects.\n"; | ||||
|  | ||||
|     PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) ); | ||||
|      | ||||
|     BOOST_CHECK( li2 == li ); | ||||
|     BOOST_CHECK( 2 == li ); | ||||
|     BOOST_CHECK( li == 2 ); | ||||
|     BOOST_CHECK( li1 < li2 ); | ||||
|     BOOST_CHECK( 1 < li2 ); | ||||
|     BOOST_CHECK( li1 <= li2 ); | ||||
|     BOOST_CHECK( 1 <= li2 ); | ||||
|     BOOST_CHECK( li2 > li1 ); | ||||
|     BOOST_CHECK( li2 > 1 ); | ||||
|     BOOST_CHECK( li2 >= li1 ); | ||||
|     BOOST_CHECK( li2 >= 1 ); | ||||
|     BOOST_CHECK( li1 % li2 == li1 ); | ||||
|     BOOST_CHECK( li1 % 2 == li1 ); | ||||
|     BOOST_CHECK( 1 % li2 == li1 ); | ||||
|     PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=2) == li1) ); | ||||
|     PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=li2) == li1) ); | ||||
|     BOOST_CHECK( li1 / li2 == 0 ); | ||||
|     BOOST_CHECK( li1 / 2 == 0 ); | ||||
|     BOOST_CHECK( 1 / li2 == 0 ); | ||||
|     PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=2) == 0) ); | ||||
|     PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=li2) == 0) ); | ||||
|     BOOST_CHECK( li1 * li2 == li2 ); | ||||
|     BOOST_CHECK( li1 * 2 == li2 ); | ||||
|     BOOST_CHECK( 1 * li2 == li2 ); | ||||
|     PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=2) == li2) ); | ||||
|     PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=li2) == li2) ); | ||||
|     BOOST_CHECK( li2 - li1 == li1 ); | ||||
|     BOOST_CHECK( li2 - 1 == li1 ); | ||||
|     BOOST_CHECK( 2 - li1 == li1 ); | ||||
|     PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=1) == li1) ); | ||||
|     PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=li1) == li1) ); | ||||
|     BOOST_CHECK( li1 + li1 == li2 ); | ||||
|     BOOST_CHECK( li1 + 1 == li2 ); | ||||
|     BOOST_CHECK( 1 + li1 == li2 ); | ||||
|     PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=1) == li2) ); | ||||
|     PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=li1) == li2) ); | ||||
|  | ||||
|     cout << "Performed tests on MyLongInt objects.\n"; | ||||
|  | ||||
|     return boost::exit_success; | ||||
| } | ||||
							
								
								
									
										134
									
								
								ref_ct_test.cpp
									
									
									
									
									
								
							
							
						
						
									
										134
									
								
								ref_ct_test.cpp
									
									
									
									
									
								
							| @@ -1,134 +0,0 @@ | ||||
| // Copyright David Abrahams and Aleksey Gurtovoy | ||||
| // 2002-2004. Distributed under the Boost Software License, Version | ||||
| // 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| // compile-time test for "boost/ref.hpp" header content | ||||
| // see 'ref_test.cpp' for run-time part | ||||
|  | ||||
| #include <boost/ref.hpp> | ||||
| #include <boost/type_traits/is_same.hpp> | ||||
| #include <boost/type_traits/remove_const.hpp> | ||||
| #include <boost/static_assert.hpp> | ||||
| #include <boost/detail/workaround.hpp> | ||||
|  | ||||
| #include <boost/mpl/assert.hpp> | ||||
|  | ||||
| namespace { | ||||
|  | ||||
| template< typename T, typename U > | ||||
| void ref_test(boost::reference_wrapper<U>) | ||||
| { | ||||
|     typedef typename boost::reference_wrapper<U>::type type; | ||||
|     BOOST_STATIC_ASSERT((boost::is_same<U,type>::value)); | ||||
|     BOOST_STATIC_ASSERT((boost::is_same<T,type>::value)); | ||||
| } | ||||
|  | ||||
| template< typename T > | ||||
| void assignable_test(T x) | ||||
| { | ||||
|     x = x; | ||||
| } | ||||
|  | ||||
| template< bool R, typename T > | ||||
| void is_reference_wrapper_test(T) | ||||
| { | ||||
|     BOOST_STATIC_ASSERT(boost::is_reference_wrapper<T>::value == R); | ||||
| } | ||||
|  | ||||
| template< typename R, typename Ref > | ||||
| void cxx_reference_test(Ref) | ||||
| { | ||||
| #if BOOST_WORKAROUND(__BORLANDC__, < 0x600) | ||||
|     typedef typename boost::remove_const<Ref>::type ref; | ||||
|     BOOST_STATIC_ASSERT((boost::is_same<R,ref>::value)); | ||||
| #else | ||||
|     BOOST_STATIC_ASSERT((boost::is_same<R,Ref>::value)); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| template< typename R, typename Ref > | ||||
| void unwrap_reference_test(Ref) | ||||
| { | ||||
| #if BOOST_WORKAROUND(__BORLANDC__, < 0x600) | ||||
|     typedef typename boost::remove_const<Ref>::type ref; | ||||
|     typedef typename boost::unwrap_reference<ref>::type type; | ||||
| #else | ||||
|     typedef typename boost::unwrap_reference<Ref>::type type; | ||||
| #endif | ||||
|     BOOST_STATIC_ASSERT((boost::is_same<R,type>::value)); | ||||
| } | ||||
|  | ||||
| } // namespace | ||||
|  | ||||
| int main() | ||||
| { | ||||
|     int i = 0; | ||||
|     int& ri = i; | ||||
|  | ||||
|     int const ci = 0; | ||||
|     int const& rci = ci; | ||||
|  | ||||
|     // 'ref/cref' functions test | ||||
|     ref_test<int>(boost::ref(i)); | ||||
|     ref_test<int>(boost::ref(ri)); | ||||
|     ref_test<int const>(boost::ref(ci)); | ||||
|     ref_test<int const>(boost::ref(rci)); | ||||
|  | ||||
|     ref_test<int const>(boost::cref(i)); | ||||
|     ref_test<int const>(boost::cref(ri)); | ||||
|     ref_test<int const>(boost::cref(ci)); | ||||
|     ref_test<int const>(boost::cref(rci)); | ||||
|  | ||||
|     // test 'assignable' requirement | ||||
|     assignable_test(boost::ref(i)); | ||||
|     assignable_test(boost::ref(ri)); | ||||
|     assignable_test(boost::cref(i)); | ||||
|     assignable_test(boost::cref(ci)); | ||||
|     assignable_test(boost::cref(rci)); | ||||
|  | ||||
|     // 'is_reference_wrapper' test | ||||
|     is_reference_wrapper_test<true>(boost::ref(i)); | ||||
|     is_reference_wrapper_test<true>(boost::ref(ri)); | ||||
|     is_reference_wrapper_test<true>(boost::cref(i)); | ||||
|     is_reference_wrapper_test<true>(boost::cref(ci)); | ||||
|     is_reference_wrapper_test<true>(boost::cref(rci)); | ||||
|  | ||||
|     is_reference_wrapper_test<false>(i); | ||||
|     is_reference_wrapper_test<false, int&>(ri); | ||||
|     is_reference_wrapper_test<false>(ci); | ||||
|     is_reference_wrapper_test<false, int const&>(rci); | ||||
|  | ||||
|     // ordinary references/function template arguments deduction test | ||||
|     cxx_reference_test<int>(i); | ||||
|     cxx_reference_test<int>(ri); | ||||
|     cxx_reference_test<int>(ci); | ||||
|     cxx_reference_test<int>(rci); | ||||
|  | ||||
|     cxx_reference_test<int&, int&>(i); | ||||
|     cxx_reference_test<int&, int&>(ri); | ||||
|     cxx_reference_test<int const&, int const&>(i); | ||||
|     cxx_reference_test<int const&, int const&>(ri); | ||||
|     cxx_reference_test<int const&, int const&>(ci); | ||||
|     cxx_reference_test<int const&, int const&>(rci); | ||||
|  | ||||
|     // 'unwrap_reference' test | ||||
|     unwrap_reference_test<int>(boost::ref(i)); | ||||
|     unwrap_reference_test<int>(boost::ref(ri)); | ||||
|     unwrap_reference_test<int const>(boost::cref(i)); | ||||
|     unwrap_reference_test<int const>(boost::cref(ci)); | ||||
|     unwrap_reference_test<int const>(boost::cref(rci)); | ||||
|  | ||||
|     unwrap_reference_test<int>(i); | ||||
|     unwrap_reference_test<int>(ri); | ||||
|     unwrap_reference_test<int>(ci); | ||||
|     unwrap_reference_test<int>(rci); | ||||
|     unwrap_reference_test<int&, int&>(i); | ||||
|     unwrap_reference_test<int&, int&>(ri); | ||||
|     unwrap_reference_test<int const&, int const&>(i); | ||||
|     unwrap_reference_test<int const&, int const&>(ri); | ||||
|     unwrap_reference_test<int const&, int const&>(ci); | ||||
|     unwrap_reference_test<int const&, int const&>(rci); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										78
									
								
								ref_test.cpp
									
									
									
									
									
								
							
							
						
						
									
										78
									
								
								ref_test.cpp
									
									
									
									
									
								
							| @@ -1,78 +0,0 @@ | ||||
| // Copyright David Abrahams and Aleksey Gurtovoy | ||||
| // 2002-2004. Distributed under the Boost Software License, Version | ||||
| // 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| // run-time test for "boost/ref.hpp" header content | ||||
| // see 'ref_ct_test.cpp' for compile-time part | ||||
|  | ||||
| #if defined(_MSC_VER) && !defined(__ICL) | ||||
| # pragma warning(disable: 4786)  // identifier truncated in debug info | ||||
| # pragma warning(disable: 4710)  // function not inlined | ||||
| # pragma warning(disable: 4711)  // function selected for automatic inline expansion | ||||
| # pragma warning(disable: 4514)  // unreferenced inline removed | ||||
| #endif | ||||
|  | ||||
| #include <boost/ref.hpp> | ||||
|  | ||||
| #if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) | ||||
| # pragma warning(push, 3) | ||||
| #endif | ||||
|  | ||||
| #include <iostream> | ||||
|  | ||||
| #if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) | ||||
| # pragma warning(pop) | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #define BOOST_INCLUDE_MAIN | ||||
| #include <boost/test/test_tools.hpp> | ||||
|  | ||||
| namespace { | ||||
| using namespace boost; | ||||
|  | ||||
| template <class T> | ||||
| struct ref_wrapper | ||||
| { | ||||
|     // Used to verify implicit conversion | ||||
|     static T* get_pointer(T& x) | ||||
|     { | ||||
|         return &x; | ||||
|     } | ||||
|  | ||||
|     static T const* get_const_pointer(T const& x) | ||||
|     { | ||||
|         return &x; | ||||
|     } | ||||
|  | ||||
|     template <class Arg> | ||||
|     static T* passthru(Arg x) | ||||
|     { | ||||
|         return get_pointer(x); | ||||
|     } | ||||
|  | ||||
|     template <class Arg> | ||||
|     static T const* cref_passthru(Arg x) | ||||
|     { | ||||
|         return get_const_pointer(x); | ||||
|     } | ||||
|  | ||||
|     static void test(T x) | ||||
|     { | ||||
|         BOOST_CHECK(passthru(ref(x)) == &x); | ||||
|         BOOST_CHECK(&ref(x).get() == &x); | ||||
|  | ||||
|         BOOST_CHECK(cref_passthru(cref(x)) == &x); | ||||
|         BOOST_CHECK(&cref(x).get() == &x); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| } // namespace unnamed | ||||
|  | ||||
| int test_main(int, char * []) | ||||
| { | ||||
|     ref_wrapper<int>::test(1); | ||||
|     ref_wrapper<int const>::test(1); | ||||
|     return 0; | ||||
| } | ||||
| @@ -1,322 +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>Shared Container Iterator Documentation</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000"> | ||||
|  | ||||
| <img src="../../boost.png" alt="boost.png (6897 bytes)" | ||||
| align="center" width="277" height="86"> | ||||
|  | ||||
| <h1>Shared Container Iterator</h1> | ||||
|  | ||||
| Defined in header | ||||
| <a href="../../boost/shared_container_iterator.hpp">boost/shared_container_iterator.hpp</a> | ||||
|  | ||||
| <p> | ||||
| The purpose of the shared container iterator is to attach the lifetime | ||||
| of a container to the lifetime of its iterators. In other words, the | ||||
| container will not be deleted until after all its iterators are | ||||
| destroyed.  The shared container iterator is typically used to | ||||
| implement functions that return iterators over a range of objects that | ||||
| only need to exist for the lifetime of the iterators.  By returning a | ||||
| pair of shared iterators from a function, the callee can return a | ||||
| heap-allocated range of objects whose lifetime is automatically managed. | ||||
| <p> | ||||
| The shared container iterator augments an iterator over a shared | ||||
| container.  It maintains a reference count on the shared  | ||||
| container. If only shared container iterators hold references to | ||||
| the container, the container's lifetime will end when the last shared | ||||
| container iterator over it is destroyed.  In any case, the shared | ||||
| container is guaranteed to persist beyond the lifetime of all | ||||
| the iterators. In all other ways, the | ||||
| shared container iterator behaves the same as its base iterator. | ||||
|  | ||||
|  | ||||
| <h2>Synopsis</h2> | ||||
|  | ||||
| <pre> | ||||
| namespace boost { | ||||
|   template <typename <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>> | ||||
|   class shared_container_iterator; | ||||
|  | ||||
|   template <typename <a href="http://www.sgi.com/tech/stl/Container.html">Container</a>> | ||||
|   shared_container_iterator<Container> | ||||
|   make_shared_container_iterator(typename Container::iterator base,  | ||||
|     boost::shared_ptr<Container> const& container); | ||||
|  | ||||
|   std::pair< | ||||
|     typename shared_container_iterator<Container>, | ||||
|     typename shared_container_iterator<Container> | ||||
|   > | ||||
|   make_shared_container_range(boost::shared_ptr<Container> const& container); | ||||
| } | ||||
| </pre> | ||||
|  | ||||
| <hr> | ||||
|  | ||||
| <h2><a name="generator">The Shared Container Iterator Type</a></h2> | ||||
|  | ||||
| <pre> | ||||
| template <typename Container> class shared_container_iterator; | ||||
| </pre> | ||||
|  | ||||
| The class template <tt>shared_container_iterator</tt>  | ||||
| is the shared container iterator type.  The <tt>Container</tt> template | ||||
| type argument must model the | ||||
| <a href="http://www.sgi.com/tech/stl/Container.html">Container</a> | ||||
| concept. | ||||
|  | ||||
| <h3>Example</h3> | ||||
|  | ||||
| <p> | ||||
| The following example illustrates how to create an iterator that  | ||||
| regulates the lifetime of a reference counted <tt>std::vector</tt>. | ||||
| Though the original shared pointer <tt>ints</tt> ceases to exist | ||||
| after <tt>set_range()</tt> returns, the | ||||
| <tt>shared_counter_iterator</tt> objects maintain references to the | ||||
|       underlying vector and thereby extend the container's lifetime. | ||||
| <p> | ||||
| <a href="./shared_iterator_example1.cpp">shared_iterator_example1.cpp</a>: | ||||
| <PRE> | ||||
| <font color="#008040">#include "shared_container_iterator.hpp"</font> | ||||
| <font color="#008040">#include "boost/shared_ptr.hpp"</font> | ||||
| <font color="#008040">#include <algorithm></font> | ||||
| <font color="#008040">#include <iostream></font> | ||||
| <font color="#008040">#include <vector></font> | ||||
|  | ||||
| <B>typedef</B> boost::shared_container_iterator< std::vector<<B>int</B>> > iterator; | ||||
|  | ||||
|  | ||||
| <B>void</B> set_range(iterator& i, iterator& end)  { | ||||
|  | ||||
|   boost::shared_ptr< std::vector<<B>int</B>> > ints(<B>new</B> std::vector<<B>int</B>>()); | ||||
|    | ||||
|   ints->push_back(<font color="#0000A0">0</font>); | ||||
|   ints->push_back(<font color="#0000A0">1</font>); | ||||
|   ints->push_back(<font color="#0000A0">2</font>); | ||||
|   ints->push_back(<font color="#0000A0">3</font>); | ||||
|   ints->push_back(<font color="#0000A0">4</font>); | ||||
|   ints->push_back(<font color="#0000A0">5</font>); | ||||
|    | ||||
|   i = iterator(ints->begin(),ints); | ||||
|   end = iterator(ints->end(),ints); | ||||
| } | ||||
|  | ||||
|  | ||||
| <B>int</B> main() { | ||||
|  | ||||
|   iterator i,end; | ||||
|  | ||||
|   set_range(i,end); | ||||
|  | ||||
|   std::copy(i,end,std::ostream_iterator<<B>int</B>>(std::cout,<font color="#0000FF">","</font>)); | ||||
|   std::cout.put(<font color="#0000FF">'\n'</font>); | ||||
|  | ||||
|   <B>return</B> <font color="#0000A0">0</font>; | ||||
| } | ||||
| </PRE> | ||||
|  | ||||
| The output from this part is: | ||||
| <pre> | ||||
| 0,1,2,3,4,5, | ||||
| </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/Container.html"><tt>Container</tt></a></TD> | ||||
| <TD>The type of the container that we wish to iterate over. It must be  | ||||
| a model of the  | ||||
| <a href="http://www.sgi.com/tech/stl/Container.html"><tt>Container</tt></a> | ||||
| concept. | ||||
| </TD> | ||||
| </TR> | ||||
| </Table> | ||||
|  | ||||
| <h3>Model of</h3> | ||||
|  | ||||
| The <tt>shared_container_iterator<Container></tt> type models the | ||||
| same iterator concept as the base iterator | ||||
|     (<tt>Container::iterator</tt>). | ||||
|  | ||||
| <h3>Members</h3> | ||||
|  | ||||
| The shared container 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, though only operations defined for the base iterator will be valid. | ||||
| In addition it has the following constructor: | ||||
|  | ||||
| <pre> | ||||
| shared_container_iterator(Container::iterator const& it, | ||||
|                           boost::shared_ptr<Container> const& container) | ||||
| </pre> | ||||
|  | ||||
| <p> | ||||
| <hr> | ||||
| <p> | ||||
|  | ||||
|  | ||||
| <h2><a name="make_iterator">The Shared Container Iterator Object Generator</a></h2> | ||||
|  | ||||
| <pre> | ||||
| template <typename Container> | ||||
| shared_container_iterator<Container> | ||||
| make_shared_container_iterator(Container::iterator base, | ||||
|                                boost::shared_ptr<Container> const& container) | ||||
| </pre> | ||||
|  | ||||
| This function provides an alternative to directly constructing a | ||||
| shared container iterator.  Using the object generator, a shared | ||||
| container iterator can be created and passed to a function without | ||||
| explicitly specifying its type. | ||||
|  | ||||
| <h3>Example</h3> | ||||
|  | ||||
| This example, similar to the previous, uses  | ||||
| <tt>make_shared_container_iterator()</tt> to create the iterators. | ||||
|  | ||||
| <p> | ||||
| <a href="./shared_iterator_example2.cpp">shared_iterator_example2.cpp</a>: | ||||
|  | ||||
| <PRE> | ||||
| <font color="#008040">#include "shared_container_iterator.hpp"</font> | ||||
| <font color="#008040">#include "boost/shared_ptr.hpp"</font> | ||||
| <font color="#008040">#include <algorithm></font> | ||||
| <font color="#008040">#include <iterator></font> | ||||
| <font color="#008040">#include <iostream></font> | ||||
| <font color="#008040">#include <vector></font> | ||||
|  | ||||
|  | ||||
| <B>template</B> <<B>typename</B> Iterator> | ||||
| <B>void</B> print_range_nl (Iterator begin, Iterator end) { | ||||
|   <B>typedef</B> <B>typename</B> std::iterator_traits<Iterator>::value_type val; | ||||
|   std::copy(begin,end,std::ostream_iterator<val>(std::cout,<font color="#0000FF">","</font>)); | ||||
|   std::cout.put(<font color="#0000FF">'\n'</font>); | ||||
| } | ||||
|  | ||||
|  | ||||
| <B>int</B> main() { | ||||
|  | ||||
|   <B>typedef</B> boost::shared_ptr< std::vector<<B>int</B>> > ints_t; | ||||
|   { | ||||
|     ints_t ints(<B>new</B> std::vector<<B>int</B>>()); | ||||
|  | ||||
|     ints->push_back(<font color="#0000A0">0</font>); | ||||
|     ints->push_back(<font color="#0000A0">1</font>); | ||||
|     ints->push_back(<font color="#0000A0">2</font>); | ||||
|     ints->push_back(<font color="#0000A0">3</font>); | ||||
|     ints->push_back(<font color="#0000A0">4</font>); | ||||
|     ints->push_back(<font color="#0000A0">5</font>); | ||||
|  | ||||
|     print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints), | ||||
| 		   boost::make_shared_container_iterator(ints->end(),ints)); | ||||
|   } | ||||
|    | ||||
|  | ||||
|  | ||||
|   <B>return</B> <font color="#0000A0">0</font>; | ||||
| } | ||||
| </PRE> | ||||
|  | ||||
| Observe that the <tt>shared_container_iterator</tt> type is never | ||||
| explicitly named. The output from this example is the same as the previous. | ||||
|  | ||||
| <h2><a name="make_range">The Shared Container Iterator Range Generator</a></h2> | ||||
|  | ||||
| <pre> | ||||
| template <typename Container> | ||||
| std::pair< | ||||
|   shared_container_iterator<Container>, | ||||
|   shared_container_iterator<Container> | ||||
| > | ||||
| make_shared_container_range(boost::shared_ptr<Container> const& container); | ||||
| </pre> | ||||
|  | ||||
| Class <tt>shared_container_iterator</tt> is meant primarily to return, | ||||
| using iterators, a range of values that we can guarantee will be alive as  | ||||
| long as the iterators are. This is a convenience | ||||
| function to do just that. It is equivalent to | ||||
|  | ||||
| <pre> | ||||
| std::make_pair(make_shared_container_iterator(container->begin(),container), | ||||
|                make_shared_container_iterator(container->end(),container)); | ||||
| </pre> | ||||
|  | ||||
| <h3>Example</h3> | ||||
|  | ||||
| In the following example, a range of values is returned as a pair of | ||||
| <tt>shared_container_iterator</tt> objects.   | ||||
|  | ||||
|  | ||||
| <p> | ||||
| <a href="./shared_iterator_example3.cpp">shared_iterator_example3.cpp</a>: | ||||
|  | ||||
| <PRE> | ||||
| <font color="#008040">#include "shared_container_iterator.hpp"</font> | ||||
| <font color="#008040">#include "boost/shared_ptr.hpp"</font> | ||||
| <font color="#008040">#include "boost/tuple/tuple.hpp" // for boost::tie</font> | ||||
| <font color="#008040">#include <algorithm>              // for std::copy</font> | ||||
| <font color="#008040">#include <iostream>              </font> | ||||
| <font color="#008040">#include <vector></font> | ||||
|  | ||||
|  | ||||
| <B>typedef</B> boost::shared_container_iterator< std::vector<<B>int</B>> > iterator;  | ||||
|  | ||||
| std::pair<iterator,iterator> | ||||
| return_range() { | ||||
|   boost::shared_ptr< std::vector<<B>int</B>> > range(<B>new</B> std::vector<<B>int</B>>()); | ||||
|   range->push_back(<font color="#0000A0">0</font>); | ||||
|   range->push_back(<font color="#0000A0">1</font>); | ||||
|   range->push_back(<font color="#0000A0">2</font>); | ||||
|   range->push_back(<font color="#0000A0">3</font>); | ||||
|   range->push_back(<font color="#0000A0">4</font>); | ||||
|   range->push_back(<font color="#0000A0">5</font>); | ||||
|   <B>return</B> boost::make_shared_container_range(range); | ||||
| } | ||||
|  | ||||
|  | ||||
| <B>int</B> main() { | ||||
|  | ||||
|  | ||||
|   iterator i,end; | ||||
|    | ||||
|   boost::tie(i,end) = return_range(); | ||||
|  | ||||
|   std::copy(i,end,std::ostream_iterator<<B>int</B>>(std::cout,<font color="#0000FF">","</font>)); | ||||
|   std::cout.put(<font color="#0000FF">'\n'</font>); | ||||
|  | ||||
|   <B>return</B> <font color="#0000A0">0</font>; | ||||
| } | ||||
| </PRE> | ||||
|  | ||||
| Though the <tt>range</tt> object only lives for the duration of the | ||||
| <tt>return_range</tt> call, the reference counted | ||||
| <tt>std::vector</tt> will live until <tt>i</tt> and <tt>end</tt> | ||||
| are both destroyed.  The output from this example is the same as | ||||
| the previous two. | ||||
|  | ||||
|  | ||||
| <hr> | ||||
| <!-- hhmts start --> | ||||
| Last modified: Mon Aug 11 11:27:03 EST 2003 | ||||
| <!-- hhmts end --> | ||||
| <p><EFBFBD> Copyright 2003 The Trustees of Indiana University. | ||||
|  Use, modification and distribution is subject to the Boost Software  | ||||
|  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
|  http:www.boost.org/LICENSE_1_0.txt)</p> | ||||
|  | ||||
| </body> | ||||
|  | ||||
| </html> | ||||
| @@ -1,42 +0,0 @@ | ||||
| // Copyright 2003 The Trustees of Indiana University. | ||||
|  | ||||
| // Use, modification and distribution is subject to the Boost Software  | ||||
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #include "boost/shared_container_iterator.hpp" | ||||
| #include "boost/shared_ptr.hpp" | ||||
| #include <algorithm> | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
|  | ||||
| typedef boost::shared_container_iterator< std::vector<int> > iterator; | ||||
|  | ||||
|  | ||||
| void set_range(iterator& i, iterator& end)  { | ||||
|  | ||||
|   boost::shared_ptr< std::vector<int> > ints(new std::vector<int>()); | ||||
|    | ||||
|   ints->push_back(0); | ||||
|   ints->push_back(1); | ||||
|   ints->push_back(2); | ||||
|   ints->push_back(3); | ||||
|   ints->push_back(4); | ||||
|   ints->push_back(5); | ||||
|    | ||||
|   i = iterator(ints->begin(),ints); | ||||
|   end = iterator(ints->end(),ints); | ||||
| } | ||||
|  | ||||
|  | ||||
| int main() { | ||||
|  | ||||
|   iterator i,end; | ||||
|  | ||||
|   set_range(i,end); | ||||
|  | ||||
|   std::copy(i,end,std::ostream_iterator<int>(std::cout,",")); | ||||
|   std::cout.put('\n'); | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
| @@ -1,43 +0,0 @@ | ||||
| // Copyright 2003 The Trustees of Indiana University. | ||||
|  | ||||
| // Use, modification and distribution is subject to the Boost Software  | ||||
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #include "boost/shared_container_iterator.hpp" | ||||
| #include "boost/shared_ptr.hpp" | ||||
| #include <algorithm> | ||||
| #include <iterator> | ||||
| #include <iostream> | ||||
| #include <vector> | ||||
|  | ||||
|  | ||||
| template <typename Iterator> | ||||
| void print_range_nl (Iterator begin, Iterator end) { | ||||
|   typedef typename std::iterator_traits<Iterator>::value_type val; | ||||
|   std::copy(begin,end,std::ostream_iterator<val>(std::cout,",")); | ||||
|   std::cout.put('\n'); | ||||
| } | ||||
|  | ||||
|  | ||||
| int main() { | ||||
|  | ||||
|   typedef boost::shared_ptr< std::vector<int> > ints_t; | ||||
|   { | ||||
|     ints_t ints(new std::vector<int>()); | ||||
|  | ||||
|     ints->push_back(0); | ||||
|     ints->push_back(1); | ||||
|     ints->push_back(2); | ||||
|     ints->push_back(3); | ||||
|     ints->push_back(4); | ||||
|     ints->push_back(5); | ||||
|  | ||||
|     print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints), | ||||
|                    boost::make_shared_container_iterator(ints->end(),ints)); | ||||
|   } | ||||
|    | ||||
|  | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
| @@ -1,41 +0,0 @@ | ||||
| // Copyright 2003 The Trustees of Indiana University. | ||||
|  | ||||
| // Use, modification and distribution is subject to the Boost Software  | ||||
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| #include "boost/shared_container_iterator.hpp" | ||||
| #include "boost/shared_ptr.hpp" | ||||
| #include "boost/tuple/tuple.hpp" // for boost::tie | ||||
| #include <algorithm>              // for std::copy | ||||
| #include <iostream>               | ||||
| #include <vector> | ||||
|  | ||||
|  | ||||
| typedef boost::shared_container_iterator< std::vector<int> > iterator; | ||||
|  | ||||
| std::pair<iterator,iterator> | ||||
| return_range() { | ||||
|   boost::shared_ptr< std::vector<int> > range(new std::vector<int>()); | ||||
|   range->push_back(0); | ||||
|   range->push_back(1); | ||||
|   range->push_back(2); | ||||
|   range->push_back(3); | ||||
|   range->push_back(4); | ||||
|   range->push_back(5); | ||||
|   return boost::make_shared_container_range(range); | ||||
| } | ||||
|  | ||||
|  | ||||
| int main() { | ||||
|  | ||||
|  | ||||
|   iterator i,end; | ||||
|    | ||||
|   boost::tie(i,end) = return_range(); | ||||
|  | ||||
|   std::copy(i,end,std::ostream_iterator<int>(std::cout,",")); | ||||
|   std::cout.put('\n'); | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
| @@ -1,64 +0,0 @@ | ||||
| // Copyright 2003 The Trustees of Indiana University. | ||||
|  | ||||
| // Use, modification and distribution is subject to the Boost Software  | ||||
| // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| //  Shared container iterator adaptor  | ||||
| //  Author: Ronald Garcia | ||||
| //  See http://boost.org/libs/utility/shared_container_iterator.html  | ||||
| //  for documentation.  | ||||
|  | ||||
| // | ||||
| // shared_iterator_test.cpp - Regression tests for shared_container_iterator. | ||||
| // | ||||
|  | ||||
|  | ||||
| #include "boost/shared_container_iterator.hpp" | ||||
| #include "boost/shared_ptr.hpp" | ||||
| #include <vector> | ||||
| #include <cassert> | ||||
|  | ||||
| struct resource { | ||||
|   static int count; | ||||
|   resource() { ++count; } | ||||
|   resource(resource const&) { ++count; } | ||||
|   ~resource() { --count; } | ||||
| }; | ||||
| int resource::count = 0; | ||||
|  | ||||
| typedef std::vector<resource> resources_t; | ||||
|  | ||||
| typedef boost::shared_container_iterator< resources_t > iterator; | ||||
|  | ||||
|  | ||||
| void set_range(iterator& i, iterator& end)  { | ||||
|  | ||||
|   boost::shared_ptr< resources_t > objs(new resources_t()); | ||||
|  | ||||
|   for (int j = 0; j != 6; ++j) | ||||
|     objs->push_back(resource()); | ||||
|    | ||||
|   i = iterator(objs->begin(),objs); | ||||
|   end = iterator(objs->end(),objs); | ||||
|   assert(resource::count == 6); | ||||
| } | ||||
|  | ||||
|  | ||||
| int main() { | ||||
|  | ||||
|   assert(resource::count == 0); | ||||
|    | ||||
|   { | ||||
|     iterator i; | ||||
|     { | ||||
|       iterator end; | ||||
|       set_range(i,end); | ||||
|       assert(resource::count == 6); | ||||
|     } | ||||
|     assert(resource::count == 6); | ||||
|   } | ||||
|   assert(resource::count == 0); | ||||
|    | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										43
									
								
								test/Jamfile
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								test/Jamfile
									
									
									
									
									
								
							| @@ -1,43 +0,0 @@ | ||||
| # Copyright David Abrahams 2003. 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. | ||||
|  | ||||
| # For more information, see http://www.boost.org/ | ||||
|  | ||||
| subproject libs/utility/test ; | ||||
|  | ||||
| # bring in rules for testing | ||||
| import testing ; | ||||
|  | ||||
| # Make tests run by default. | ||||
| DEPENDS all : test ; | ||||
|  | ||||
| local test_monitor = <lib>@boost/libs/test/build/boost_test_exec_monitor ; | ||||
|  | ||||
| # Please keep the tests ordered by filename | ||||
| test-suite utility | ||||
|     : | ||||
|         [ run ../addressof_test.cpp ] | ||||
|         [ run ../assert_test.cpp ] | ||||
|         [ run ../base_from_member_test.cpp ] | ||||
|         [ run ../binary_search_test.cpp ] | ||||
|         [ run ../call_traits_test.cpp : -u ] | ||||
|         [ compile-fail ../checked_delete_test.cpp ] | ||||
|         [ run ../compressed_pair_test.cpp $(test_monitor) : -u ] | ||||
|         [ run ../current_function_test.cpp : : : <test-info>always_show_run_output ] | ||||
|         [ run ../iterators_test.cpp $(test_monitor) ] | ||||
|         [ run next_prior_test.cpp $(test_monitor) ] | ||||
|         [ compile-fail ../noncopyable_test.cpp ] | ||||
|         [ run ../numeric_traits_test.cpp ] | ||||
|         [ run ../operators_test.cpp $(test_monitor) ] | ||||
|         [ compile ../ref_ct_test.cpp  ] | ||||
|         [ run ../ref_test.cpp $(test_monitor) ] | ||||
|         [ compile result_of_test.cpp ] | ||||
|         [ run ../shared_iterator_test.cpp ] | ||||
|         [ run ../value_init_test.cpp ] | ||||
|         [ compile-fail ../value_init_test_fail1.cpp ] | ||||
|         [ compile-fail ../value_init_test_fail2.cpp ] | ||||
|         [ compile-fail ../value_init_test_fail3.cpp ] | ||||
|     ; | ||||
| @@ -1,36 +0,0 @@ | ||||
| # Copyright David Abrahams 2003. 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. | ||||
|  | ||||
| # For more information, see http://www.boost.org/ | ||||
|  | ||||
| # bring in rules for testing | ||||
| import testing ; | ||||
|  | ||||
| # Please keep the tests ordered by filename | ||||
| test-suite utility | ||||
|     : | ||||
|         [ run ../addressof_test.cpp ] | ||||
|         [ run ../assert_test.cpp ] | ||||
|         [ run ../base_from_member_test.cpp ] | ||||
|         [ run ../binary_search_test.cpp ] | ||||
|         [ run ../call_traits_test.cpp : -u ] | ||||
|         [ compile-fail ../checked_delete_test.cpp ] | ||||
|         [ run ../compressed_pair_test.cpp ../../test/build//boost_test_exec_monitor : -u ] | ||||
|         [ run ../current_function_test.cpp : : : <test-info>always_show_run_output ] | ||||
|         [ run ../iterators_test.cpp ../../test/build//boost_test_exec_monitor ] | ||||
|         [ run next_prior_test.cpp ../../test/build//boost_test_exec_monitor ] | ||||
|         [ compile-fail ../noncopyable_test.cpp ] | ||||
|         [ run ../numeric_traits_test.cpp ] | ||||
|         [ run ../operators_test.cpp ../../test/build//boost_test_exec_monitor ] | ||||
|         [ compile ../ref_ct_test.cpp  ] | ||||
|         [ run ../ref_test.cpp ../../test/build//boost_test_exec_monitor ] | ||||
|         [ compile result_of_test.cpp ] | ||||
|         [ run ../shared_iterator_test.cpp ] | ||||
|         [ run ../value_init_test.cpp ] | ||||
|         [ compile-fail ../value_init_test_fail1.cpp ] | ||||
|         [ compile-fail ../value_init_test_fail2.cpp ] | ||||
|         [ compile-fail ../value_init_test_fail3.cpp ] | ||||
|     ; | ||||
| @@ -1,79 +0,0 @@ | ||||
| // Boost test program for next() and prior() utilities. | ||||
|  | ||||
| // Copyright 2003 Daniel Walker.  Use, modification, and distribution | ||||
| // are subject to the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or a copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt.) | ||||
|  | ||||
| // See http://www.boost.org/libs/utility for documentation. | ||||
|  | ||||
| // Revision History 13 Dec 2003 Initial Version (Daniel Walker) | ||||
|  | ||||
| // next() and prior() are replacements for operator+ and operator- for | ||||
| // non-random-access iterators. The semantics of these operators are | ||||
| // such that after executing j = i + n, std::distance(i, j) equals | ||||
| // n. Tests are provided to ensure next() has the same | ||||
| // result. Parallel tests are provided for prior(). The tests call | ||||
| // next() and prior() several times. next() and prior() are very | ||||
| // simple functions, though, and it would be very strange if these | ||||
| // tests were to fail. | ||||
|  | ||||
| #define BOOST_INCLUDE_MAIN | ||||
| #include <boost/test/test_tools.hpp> | ||||
|  | ||||
| #include <list> | ||||
| #include <vector> | ||||
|  | ||||
| #include <boost/next_prior.hpp> | ||||
|  | ||||
| template<class RandomAccessIterator, class ForwardIterator> | ||||
| bool plus_one_test(RandomAccessIterator first, RandomAccessIterator last, ForwardIterator first2) | ||||
| { | ||||
|     RandomAccessIterator i = first; | ||||
|     ForwardIterator j = first2; | ||||
|     while(i != last) | ||||
|         i = i + 1, j = boost::next(j); | ||||
|     return std::distance(first, i) == std::distance(first2, j); | ||||
| } | ||||
|  | ||||
| template<class RandomAccessIterator, class ForwardIterator> | ||||
| bool plus_n_test(RandomAccessIterator first, RandomAccessIterator last, ForwardIterator first2) | ||||
| { | ||||
|     RandomAccessIterator i = first; | ||||
|     ForwardIterator j = first2; | ||||
|     for(int n = 0; i != last; ++n) | ||||
|         i = first + n, j = boost::next(first2, n); | ||||
|     return std::distance(first, i) == std::distance(first2, j); | ||||
| } | ||||
|  | ||||
| template<class RandomAccessIterator, class BidirectionalIterator> | ||||
| bool minus_one_test(RandomAccessIterator first, RandomAccessIterator last, BidirectionalIterator last2) | ||||
| { | ||||
|     RandomAccessIterator i = last; | ||||
|     BidirectionalIterator j = last2; | ||||
|     while(i != first) | ||||
|         i = i - 1, j = boost::prior(j); | ||||
|     return std::distance(i, last) == std::distance(j, last2); | ||||
| } | ||||
|  | ||||
| template<class RandomAccessIterator, class BidirectionalIterator> | ||||
| bool minus_n_test(RandomAccessIterator first, RandomAccessIterator last, BidirectionalIterator last2) | ||||
| { | ||||
|     RandomAccessIterator i = last; | ||||
|     BidirectionalIterator j = last2; | ||||
|     for(int n = 0; i != first; ++n) | ||||
|         i = last - n, j = boost::prior(last2, n); | ||||
|     return std::distance(i, last) == std::distance(j, last2); | ||||
| } | ||||
|  | ||||
| int test_main(int, char*[]) | ||||
| { | ||||
|     std::vector<int> x(8); | ||||
|     std::list<int> y(x.begin(), x.end()); | ||||
|  | ||||
|     BOOST_REQUIRE(plus_one_test(x.begin(), x.end(), y.begin())); | ||||
|     BOOST_REQUIRE(plus_n_test(x.begin(), x.end(), y.begin())); | ||||
|     BOOST_REQUIRE(minus_one_test(x.begin(), x.end(), y.end())); | ||||
|     BOOST_REQUIRE(minus_n_test(x.begin(), x.end(), y.end())); | ||||
|     return 0; | ||||
| } | ||||
| @@ -1,53 +0,0 @@ | ||||
| // Boost result_of library | ||||
|  | ||||
| //  Copyright Douglas Gregor 2003-2004. Use, modification and | ||||
| //  distribution is subject to the Boost Software License, Version | ||||
| //  1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||||
| //  http://www.boost.org/LICENSE_1_0.txt) | ||||
|  | ||||
| // For more information, see http://www.boost.org/libs/utility | ||||
| #include <boost/utility/result_of.hpp> | ||||
| #include <utility> | ||||
| #include <boost/static_assert.hpp> | ||||
| #include <boost/type_traits/is_same.hpp> | ||||
|  | ||||
| struct int_result_type { typedef int result_type; }; | ||||
|  | ||||
| struct int_result_of | ||||
| { | ||||
|   template<typename F> struct result { typedef int type; }; | ||||
| }; | ||||
|  | ||||
| struct int_result_type_and_float_result_of | ||||
| { | ||||
|   typedef int result_type; | ||||
|   template<typename F> struct result { typedef float type; }; | ||||
| }; | ||||
|  | ||||
| struct X {}; | ||||
|  | ||||
| int main() | ||||
| { | ||||
|   using namespace boost; | ||||
|  | ||||
|   typedef int (*func_ptr)(float, double); | ||||
|   typedef int (&func_ref)(float, double); | ||||
|   typedef int (X::*mem_func_ptr)(float); | ||||
|   typedef int (X::*mem_func_ptr_c)(float) const; | ||||
|   typedef int (X::*mem_func_ptr_v)(float) volatile; | ||||
|   typedef int (X::*mem_func_ptr_cv)(float) const volatile; | ||||
|  | ||||
|   BOOST_STATIC_ASSERT((is_same<result_of<int_result_type(float)>::type, int>::value)); | ||||
|   BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(double)>::type, int>::value)); | ||||
|   BOOST_STATIC_ASSERT((is_same<result_of<int_result_of(void)>::type, void>::value)); | ||||
|   BOOST_STATIC_ASSERT((is_same<result_of<const int_result_of(double)>::type, int>::value)); | ||||
|   BOOST_STATIC_ASSERT((is_same<result_of<volatile int_result_of(void)>::type, void>::value)); | ||||
|   BOOST_STATIC_ASSERT((is_same<result_of<int_result_type_and_float_result_of(char)>::type, int>::value)); | ||||
|   BOOST_STATIC_ASSERT((is_same<result_of<func_ptr(char, float)>::type, int>::value)); | ||||
|   BOOST_STATIC_ASSERT((is_same<result_of<func_ref(char, float)>::type, int>::value)); | ||||
|   BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr(X,char)>::type, int>::value)); | ||||
|   BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_c(X,char)>::type, int>::value)); | ||||
|   BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_v(X,char)>::type, int>::value)); | ||||
|   BOOST_STATIC_ASSERT((is_same<result_of<mem_func_ptr_cv(X,char)>::type, int>::value)); | ||||
|   return 0; | ||||
| } | ||||
| @@ -1,60 +0,0 @@ | ||||
| <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> | ||||
| <html> | ||||
| 	<head> | ||||
| 		<title>Boost: throw_exception.hpp documentation</title> | ||||
| 		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | ||||
| 	</head> | ||||
| 	<body bgcolor="white" style="MARGIN-LEFT: 5%; MARGIN-RIGHT: 5%"> | ||||
| 		<table border="0" width="100%"> | ||||
| 			<tr> | ||||
| 				<td width="277"> | ||||
| 					<img src="../../boost.png" alt="boost.png (6897 bytes)" width="277" height="86"> | ||||
| 				</td> | ||||
| 				<td align="middle"> | ||||
| 					<h1>throw_exception.hpp</h1> | ||||
| 				</td> | ||||
| 			</tr> | ||||
| 			<tr> | ||||
| 				<td colspan="2" height="64"> </td> | ||||
| 			</tr> | ||||
| 		</table> | ||||
| 		<p> | ||||
| 			The header <STRONG><boost/throw_exception.hpp></STRONG> defines the  | ||||
| 			helper function <STRONG>boost::throw_exception</STRONG>. It is intended to be  | ||||
| 			used in Boost libraries that need to throw exceptions, but support  | ||||
| 			configurations and platforms where exceptions aren't available, as indicated by  | ||||
| 			the presence of the <STRONG>BOOST_NO_EXCEPTIONS</STRONG> <A href="../config/config.htm#macro_ref"> | ||||
| 				configuration macro</A>. | ||||
| 		</p> | ||||
| 		<P>When <STRONG>BOOST_NO_EXCEPTIONS</STRONG> is not defined, <tt>boost::throw_exception(e)</tt> | ||||
| 			is equivalent to <tt>throw e</tt>. Otherwise, the function is left undefined,  | ||||
| 			and the user is expected to supply an appropriate definition. Callers of <tt>throw_exception</tt> | ||||
| 			are allowed to assume that the function never returns; therefore, if the  | ||||
| 			user-defined <tt>throw_exception</tt> returns, the behavior is undefined.</P> | ||||
| 		<h3><a name="Synopsis">Synopsis</a></h3> | ||||
| 		<pre> | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| #ifdef BOOST_NO_EXCEPTIONS | ||||
|  | ||||
| void throw_exception(std::exception const & e); // user defined | ||||
|  | ||||
| #else | ||||
|  | ||||
| template<class E> void throw_exception(E const & e) | ||||
| { | ||||
|     throw e; | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| } | ||||
| </pre> | ||||
| 		<p><br> | ||||
| 			<small>Copyright <20> 2002 by Peter Dimov. 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.</small></p> | ||||
| 	</body> | ||||
| </html> | ||||
							
								
								
									
										193
									
								
								utility.htm
									
									
									
									
									
								
							
							
						
						
									
										193
									
								
								utility.htm
									
									
									
									
									
								
							| @@ -1,193 +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="../../boost.png" alt="boost.png (6897 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> | ||||
| 				Class templates supporting the <a href="base_from_member.html">base-from-member  | ||||
| 					idiom</a></li> | ||||
| 			<li> | ||||
| 				Function templates <a href="#checked_delete">checked_delete() and  | ||||
| 					checked_array_delete()</a></li> | ||||
| 			<li> | ||||
| 				Function templates <a href="#functions_next_prior">next() and prior()</a></li> | ||||
| 			<li> | ||||
| 				Class <a href="#Class_noncopyable">noncopyable</a></li> | ||||
| 			<li> | ||||
| 				Function template <a href="#addressof">addressof()</a></li> | ||||
|                         <li>Class template <a href="#result_of">result_of</a></li> | ||||
| 		</ul> | ||||
| 		<h2> | ||||
| 			Function templates <a name="checked_delete">checked_delete</a>() and  | ||||
| 			checked_array_delete()</h2> | ||||
| 		<p>See <a href="checked_delete.html">separate documentation</a>.</p> | ||||
| 		<h2> | ||||
| 			<a name="functions_next_prior">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 T, class Distance> | ||||
| T next(T x, Distance n) | ||||
| { | ||||
|     std::advance(x, n); | ||||
|     return x; | ||||
| } | ||||
|  | ||||
| template <class T> | ||||
| T prior(T x) { return --x; } | ||||
|  | ||||
| template <class T, class Distance> | ||||
| T prior(T x, Distance n) | ||||
| { | ||||
|     std::advance(x, -n); | ||||
|     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); | ||||
| const std::list<T>::iterator next = boost::next(prev, 2);</pre> | ||||
| 		</blockquote> | ||||
|                 <p>The distance from the given iterator should be supplied as an absolute value. For | ||||
| 			example, the iterator four iterators prior to the given iterator <code>p</code> | ||||
| 			may be obtained by <code>prior(p, 4)</code>.</p> | ||||
| 		<p>Contributed by <a href="../../people/dave_abrahams.htm">Dave Abrahams</a>.  Two-argument versions by Daniel Walker.</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> | ||||
| 		<h2><a name="addressof">Function template addressof()</a></h2> | ||||
| 		<p>Function <strong>addressof()</strong> returns the address of an object.</p> | ||||
| 		<blockquote> | ||||
| 			<pre>template <typename T> inline T*                addressof(T& v); | ||||
| template <typename T> inline const T*          addressof(const T& v); | ||||
| template <typename T> inline volatile T*       addressof(volatile T& v); | ||||
| template <typename T> inline const volatile T* addressof(const volatile T& v); | ||||
| </pre> | ||||
| 		</blockquote> | ||||
| 		<p>C++ allows programmers to replace the unary <strong>operator&()</strong> class  | ||||
| 			member used to get the address of an object. Getting the real address of an  | ||||
| 			object requires ugly casting tricks to avoid invoking the overloaded <strong>operator&()</strong>.  | ||||
| 			Function <strong>addressof()</strong> provides a wrapper around the necessary  | ||||
| 			code to make it easy to get an object's real address. | ||||
| 		</p> | ||||
| 		<p>The program <a href="addressof_test.cpp">addressof_test.cpp</a> can be used to  | ||||
| 			verify that <b>addressof()</b> works as expected.</p> | ||||
| 		<p>Contributed by Brad King based on ideas from discussion with Doug Gregor.</p> | ||||
| 		<h3>Example</h3> | ||||
| 		<blockquote> | ||||
| 			<pre>#include <boost/utility.hpp> | ||||
|  | ||||
| struct useless_type {}; | ||||
| class nonaddressable { | ||||
|   useless_type operator&() const; | ||||
| }; | ||||
|  | ||||
| void f() { | ||||
|   nonaddressable x; | ||||
|   nonaddressable* xp = boost::addressof(x); | ||||
|   // nonaddressable* xpe = &x; /* error */ | ||||
| }</pre> | ||||
| 		</blockquote> | ||||
|                 <h2><a name="result_of">Class template | ||||
|                 result_of</a></h2> <p>The class template | ||||
|                 <code>result_of</code> helps determine the type of a | ||||
|                 call expression. Given an lvalue <code>f</code> of | ||||
|                 type <code>F</code> and lvalues <code>t1</code>, | ||||
|                 <code>t2</code>, ..., <code>t<em>N</em></code> of | ||||
|                 types <code>T1</code>, <code>T2</code>, ..., | ||||
|                 <code>T<em>N</em></code>, respectively, the type | ||||
|                 <code>result_of<F(T1, T2, ..., | ||||
|                 T<em>N</em>)>::type</code> defines the result type | ||||
|                 of the expression <code>f(t1, t2, | ||||
|                 ...,t<em>N</em>)</code>. The implementation permits | ||||
|                 the type <code>F</code> to be a function pointer, | ||||
|                 function reference, member function pointer, or class | ||||
|                 type. When <code>F</code> is a class type with a | ||||
|                 member type <code>result_type</code>, | ||||
|                 <code>result_of<F(T1, T2, ..., | ||||
|                 T<em>N</em>)></code> is | ||||
|                 <code>F::result_type</code>. Otherwise, | ||||
|                 <code>result_of<F(T1, T2, ..., | ||||
|                 T<em>N</em>)></code> is <code>F::result<F(T1, | ||||
|                 T2, ..., T<em>N</em>)>::type</code> when | ||||
|                 <code><em>N</em> > 0</code> or <code>void</code> | ||||
|                 when <code><em>N</em> = 0</code>. For additional | ||||
|                 information about <code>result_of</code>, see the | ||||
|                 current draft of the C++ Library TR, <a | ||||
|                 href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2004/n1647.pdf">N1647</a>, | ||||
|                 or the <code>result_of</code> <a | ||||
|                 href="http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2003/n1454.html">proposal</a>.</p> | ||||
|  | ||||
|                 <p>Class template <code>result_of</code> resides in | ||||
|                 the header <code><<a | ||||
|                 href="../../boost/utility/result_of.hpp">boost/utility/result_of.hpp</a>></code>. By | ||||
|                 default, <em>N</em> may be any value between 0 and | ||||
|                 10. To change the upper limit, define the macro | ||||
|                 <code>BOOST_RESULT_OF_NUM_ARGS</code> to the maximum | ||||
|                 value for <em>N</em>.</p> | ||||
|  | ||||
|                 <a name="BOOST_NO_RESULT_OF"></a> | ||||
|                 <p>This implementation of <code>result_of</code> requires class template partial specialization, the ability to parse function types properly, and support for SFINAE. If <code>result_of</code> is not supported by your compiler, including the header <code>boost/utility/result_of.hpp</code> will define the macro <code>BOOST_NO_RESULT_OF</code>. Contributed by Doug Gregor.</p> | ||||
|  | ||||
| 		<h2>Class templates for the Base-from-Member Idiom</h2> | ||||
| 		<p>See <a href="base_from_member.html">separate documentation</a>.</p> | ||||
| 		<hr> | ||||
| 		<p>Revised  <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan | ||||
| -->02 May, 2004<!--webbot bot="Timestamp" endspan i-checksum="38582" | ||||
| --> | ||||
| 		</p> | ||||
| 		<p>© Copyright boost.org 1999-2003. 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> | ||||
							
								
								
									
										219
									
								
								value_init.htm
									
									
									
									
									
								
							
							
						
						
									
										219
									
								
								value_init.htm
									
									
									
									
									
								
							| @@ -1,219 +0,0 @@ | ||||
| <html> | ||||
| <head> | ||||
|               | ||||
|   <meta http-equiv="Content-Type" | ||||
|  content="text/html; charset=iso-8859-1"> | ||||
|   <title>value_initialized</title> | ||||
|      | ||||
| </head> | ||||
|   <body vlink="#800080" link="#0000ff" text="#000000" bgcolor="#ffffff"> | ||||
|                     | ||||
| <h2><img src="../../boost.png" width="276" height="86"> | ||||
|          Header <<a href="../../boost/utility/value_init.hpp">boost/utility/value_init.hpp</a>> | ||||
|      </h2> | ||||
|                     | ||||
| <h2>Contents</h2> | ||||
|                     | ||||
| <dl> | ||||
|   <dt><a href="#rationale">Rationale</a></dt> | ||||
|   <dt><a href="#intro">Introduction</a></dt> | ||||
| </dl> | ||||
|                     | ||||
| <ul> | ||||
|           <li><a href="#valueinit">value-initialization</a></li> | ||||
|           <li><a href="#valueinitsyn">value-initialization syntax</a></li> | ||||
|                     | ||||
| </ul> | ||||
|                     | ||||
| <dl class="page-index"> | ||||
|   <dt><a href="#types">Types</a></dt> | ||||
| </dl> | ||||
|                     | ||||
| <ul> | ||||
|           <li><a href="#val_init"><code>value_initialized<></code></a></li> | ||||
|                     | ||||
| </ul> | ||||
|               <a href="#acknowledgements">Acknowledgements</a><br> | ||||
|      <br> | ||||
|           | ||||
| <hr>           | ||||
| <h2><a name="rationale"></a>Rationale</h2> | ||||
|                    | ||||
| <p>Constructing and initializing objects in a generic way is difficult in | ||||
|     C++. The problem is that there are several different rules that apply | ||||
| for    initialization. Depending on the type, the value of a newly constructed | ||||
|   object  can be zero-initialized (logically 0), default-constructed (using | ||||
|   the default constructor), or indeterminate. When writing generic code, | ||||
| this   problem must be addressed. <code>value_initialized</code> provides | ||||
| a solution   with consistent syntax for value   initialization of scalar, | ||||
| union and class   types. <br> | ||||
|   </p> | ||||
|          | ||||
| <h2><a name="intro"></a>Introduction</h2> | ||||
|       | ||||
| <p>The C++ standard [<a href="#references">1</a>] contains the definitions  | ||||
|     of <code>zero-initialization</code> and <code>default-initialization</code>. | ||||
|      Informally, zero-initialization means that the object is given the initial | ||||
|      value 0 (converted to the type) and default-initialization means that | ||||
|  POD   [<a href="#references">2</a>] types are zero-initialized, while class | ||||
|  types   are initialized with their corresponding default constructors. A | ||||
| <i>declaration</i>   can contain an <i>initializer</i>, which specifies the | ||||
| object's initial value.  The initializer can be just '()', which states that | ||||
| the object shall be default-initialized  (but see below). However, if a <i>declaration</i>  | ||||
|   has no <i>initializer</i>  and it is of a non-<code>const</code>, non-<code>static</code>  | ||||
|    POD type, the initial value is indeterminate:<cite>(see §8.5 for the | ||||
|    accurate definitions).</cite></p> | ||||
|                     | ||||
| <pre>int x ; // no initializer. x value is indeterminate.<br>std::string s ; // no initializer, s is default-constructed.<br><br>int y = int() ; <br>// y is initialized using copy-initialization<br>// but the temporary uses an empty set of parentheses as the initializer,<br>// so it is default-constructed.<br>// A default constructed POD type is zero-initialized,<br>// therefore, y == 0.<br><br>void foo ( std::string ) ;<br>foo ( std::string() ) ; <br>// the temporary string is default constructed <br>// as indicated by the initializer ()  </pre> | ||||
|                      | ||||
| <h3><a name="valueinit">value-initialization</a></h3> | ||||
|                     | ||||
| <p>The first <a | ||||
|  href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html">Technical  | ||||
|   Corrigendum for the C++ Standard</a> (TC1), whose draft   was released to | ||||
|   the public in November 2001, introduced <a | ||||
|  href="http://anubis.dkuug.dk/JTC1/SC22/WG21/docs/cwg_defects.html#178">Core  | ||||
|   Issue 178</a> (among   many other issues, of course).</p> | ||||
|                     | ||||
| <p> That issue introduced the new concept of <code>value-initialization</code> | ||||
|      (it also fixed the wording for zero-initialization). Informally, value-initialization  | ||||
|     is similar to default-initialization with the exception that in some cases | ||||
|     non-static data members and base class sub-objects are also value-initialized.  | ||||
|     The difference is that an object that is value-initialized won't have  | ||||
| (or    at least is less likely to have) indeterminate values for data members  | ||||
|  and   base class sub-objects; unlike the case of an object default constructed.  | ||||
|     (see Core Issue 178 for a normative description).</p> | ||||
|                     | ||||
| <p>In order to specify value-initialization of an object we need to use the | ||||
|      empty-set initializer: (). </p> | ||||
|                     | ||||
| <p><i>(but recall that the current C++ Standard states that '()' invokes default-initialization, | ||||
| not value-initialization)</i></p> | ||||
|                     | ||||
| <p>As before, a declaration with no intializer specifies default-initialization,  | ||||
|     and a declaration with a non-empty initializer specifies copy (=xxx) or | ||||
|   direct  (xxx) initialization. </p> | ||||
|                     | ||||
| <pre>template<class T> void eat(T);<br>int x ; // indeterminate initial value.<br>std::string s; // default-initialized.<br>eat ( int() ) ; // value-initialized<br>eat ( std::string() ) ; // value-initialied</pre> | ||||
|                      | ||||
| <h4><a name="valueinitsyn">value-initialization</a> syntax</h4> | ||||
|                     | ||||
| <p>Value initialization is specified using (). However, the empty set of | ||||
| parentheses is not permitted by the syntax of initializers because it is | ||||
| parsed as the declaration of a function taking no arguments: </p> | ||||
|                     | ||||
| <pre>int x() ; // declares function int(*)()<br>int y ( int() ) ; // decalares function int(*)( int(*)() )</pre> | ||||
|                      | ||||
| <p>Thus, the empty () must be put in some other initialization context.</p> | ||||
|                     | ||||
| <p>One alternative is to use copy-initialization syntax:</p> | ||||
|                     | ||||
| <pre>int x = int() ;</pre> | ||||
|                      | ||||
| <p>This works perfectly fine for POD types. But for non-POD class types, | ||||
| copy-initialization searches for a suitable constructor, which could be, | ||||
| for instance, the copy-constructor (it also searches for a suitable conversion | ||||
| sequence but this doesn't apply in this context). For an arbitrary unknown | ||||
| type, using this syntax may not have the value-initialization effect intended | ||||
| because we don't know if a copy from a default constructed object is exactly | ||||
| the same as a default constructed object, and the compiler is allowed (in | ||||
| some cases), but never required to, optimize the copy away.</p> | ||||
|                     | ||||
| <p>One possible generic solution is to use value-initialization of a non static | ||||
| data member:</p> | ||||
|                     | ||||
| <pre>template<class T> <br>struct W <br>{<br>  // value-initialization of 'data' here.<br>  W() : data() {}<br>  T data ;<br>} ;<br>W<int> w ;<br>// w.data is value-initialized for any type. </pre> | ||||
|                      | ||||
| <p><code>This is the solution supplied by the value_initialized<> template | ||||
|      class.</code></p> | ||||
|                     | ||||
| <h2><a name="types"></a>Types</h2> | ||||
|                     | ||||
| <h2><a name="val_init"><code>template class value_initialized<T></code></a></h2> | ||||
|                     | ||||
| <pre>namespace boost {<br><br>template<class T><br>class value_initialized<br>{<br>  public :<br>    value_initialized() : x() {}<br>    operator T&() const { return x ; }<br>    T& data() const { return x ; }<br><br>  private :<br>    <i>unspecified</i> x ;<br>} ;<br><br>template<class T><br>T const& get ( value_initialized<T> const& x )<br>{<br>  return x.data() ;<br>}<br><br>template<class T><br>T& get ( value_initialized<T>& x )<br>{<br>  return x.data() ;<br>}<br><br>} // namespace boost<br></pre> | ||||
|                      | ||||
| <p>An object of this template class is a <code>T</code>-wrapper convertible  | ||||
|     to <code>'T&'</code> whose wrapped object (data member of type <code>T</code>)  | ||||
|     is <a href="#valueinit">value-initialized</a> upon default-initialization  | ||||
|     of this wrapper class: </p> | ||||
|                     | ||||
| <pre>int zero = 0 ;<br>value_initialized<int> x ;<br>assert ( x == zero ) ;<br><br>std::string def ;<br>value_initialized< std::string > y ;<br>assert ( y == def ) ;<br></pre> | ||||
|                      | ||||
| <p>The purpose of this wrapper is to provide a consistent syntax for value | ||||
|      initialization of scalar, union and class types (POD and non-POD) since | ||||
|    the  correct syntax for value initialization varies (see <a | ||||
|  href="#valueinitsyn">value-initialization syntax</a>)</p> | ||||
|                     | ||||
| <p>The wrapped object can be accessed either through the conversion operator | ||||
|      <code>T&</code>, the member function <code>data()</code>, or the | ||||
| non-member    function <code>get()</code>:  </p> | ||||
|                     | ||||
| <pre>void watch(int);<br>value_initialized<int> x;<br><br>watch(x) ; // operator T& used.<br>watch(x.data());<br>watch( get(x) ) // function get() used</pre> | ||||
|                      | ||||
| <p>Both <code>const</code> and non-<code>const</code> objects can be wrapped.  | ||||
|     Mutable objects can be modified directly from within the wrapper but constant | ||||
|     objects cannot:</p> | ||||
|                     | ||||
| <pre>value_initialized<int> x ; <br>static_cast<int&>(x) = 1 ; // OK<br>get(x) = 1 ; // OK<br><br>value_initialized<int const> y ; <br>static_cast<int&>(y) = 1 ; // ERROR: cannot cast to int&<br>static_cast<int const&>(y) = 1 ; // ERROR: cannot modify a const value<br>get(y) = 1 ; // ERROR: cannot modify a const value</pre> | ||||
|                      | ||||
| <h3>Warning:</h3> | ||||
|                     | ||||
| <p>Both the conversion operator and the <code>data()</code> member function  | ||||
|     are <code>const</code> in order to allow access to the wrapped object  | ||||
| from    a constant wrapper:</p> | ||||
|                     | ||||
| <pre>void foo(int);<br>value_initialized<int> const x ;<br>foo(x);<br></pre> | ||||
|                      | ||||
| <p>But notice that this conversion operator is to <code>T&</code> although  | ||||
|     it is itself <code>const</code>. As a consequence, if <code>T</code> is | ||||
|   a  non-<code>const</code> type, you can modify the wrapped object even from | ||||
|    within a constant wrapper:</p> | ||||
|                     | ||||
| <pre>value_initialized<int> const x_c ;<br>int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const.<br>xr = 2 ; </pre> | ||||
|                      | ||||
| <p>The reason for this obscure behavior is that some commonly used compilers | ||||
|      just don't accept the following valid code:</p> | ||||
|                     | ||||
| <pre>struct X<br>{<br>  operator int&() ;<br>  operator int const&() const ;   <br>};<br>X x ;<br>(x == 1 ) ; // ERROR HERE!</pre> | ||||
|                      | ||||
| <p>These compilers complain about ambiguity between the conversion operators.  | ||||
|     This complaint is incorrect, but the only workaround that I know of is  | ||||
|  to   provide only one of them, which leads to the obscure behavior just explained.<br> | ||||
|           </p> | ||||
|                     | ||||
| <h3>Recommended practice: The non-member get() idiom</h3> | ||||
|                     | ||||
| <p>The obscure behavior of being able to modify a non-<code>const</code> | ||||
| wrapped object from within a constant wrapper can be avoided if access to | ||||
| the wrapped object is always performed with the <code>get()</code> idiom:</p> | ||||
|                     | ||||
| <pre>value_initialized<int> x ;<br>get(x) = 1 ; // OK<br><br>value_initialized<int const> cx ;<br>get(x) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized<int> const x_c ;<br>get(x_c) = 1 ; // ERROR: Cannot modify a const object<br><br>value_initialized<int const> const cx_c ;<br>get(cx_c) = 1 ; // ERROR: Cannot modify a const object<br></pre> | ||||
|                      | ||||
| <h3><a name="references">References</a></h3> | ||||
|           [1] The C++ Standard, ISO/IEC 14882:98 <br> | ||||
|           [2] Plain Old Data            | ||||
| <h3><a name="acknowledgements"></a>Acknowledgements</h3> | ||||
|      value_initialized was developed by Fernando Cacciola, with help and | ||||
| suggestions from David Abrahams and Darin Adler.<br> | ||||
| Special thanks to Bj<42>rn Karlsson who carefully edited and completed this documentation. | ||||
| <pre> </pre> | ||||
|                      | ||||
| <hr>           | ||||
| <p>Revised 19 September 2002</p> | ||||
|                     | ||||
| <p>© Copyright boost.org 2002. 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>Developed by <a href="mailto:fernando_cacciola@hotmail.com">Fernando Cacciola</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.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>. | ||||
|      </p> | ||||
|  <br> | ||||
|  <br> | ||||
|      | ||||
| </body> | ||||
| </html> | ||||
| @@ -1,107 +0,0 @@ | ||||
| // (C) 2002, Fernando Luis Cacciola Carballal. | ||||
| // | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
| // Test program for "boost/utility/value_init.hpp" | ||||
| // | ||||
| // Initial: 21 Agu 2002 | ||||
|  | ||||
| #include <iostream> | ||||
| #include <string> | ||||
|  | ||||
| #include "boost/utility/value_init.hpp" | ||||
|  | ||||
| #ifdef __BORLANDC__ | ||||
| #pragma hdrstop | ||||
| #endif | ||||
|  | ||||
| #include "boost/test/minimal.hpp" | ||||
|  | ||||
| // | ||||
| // Sample POD type | ||||
| // | ||||
| struct POD | ||||
| { | ||||
|   POD () : c(0), i(0), f(0) {} | ||||
|  | ||||
|   POD ( char c_, int i_, float f_ ) : c(c_), i(i_), f(f_) {} | ||||
|  | ||||
|   friend std::ostream& operator << ( std::ostream& os, POD const& pod ) | ||||
|     { return os << '(' << pod.c << ',' << pod.i << ',' << pod.f << ')' ; } | ||||
|  | ||||
|   friend bool operator == ( POD const& lhs, POD const& rhs ) | ||||
|     { return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; } | ||||
|  | ||||
|   float f; | ||||
|   char  c; | ||||
|   int   i; | ||||
| } ; | ||||
|  | ||||
| // | ||||
| // Sample non POD type | ||||
| // | ||||
| struct NonPODBase | ||||
| { | ||||
|   virtual ~NonPODBase() {} | ||||
| } ; | ||||
| struct NonPOD : NonPODBase | ||||
| { | ||||
|   NonPOD () : id() {} | ||||
|   NonPOD ( std::string const& id_) : id(id_) {} | ||||
|  | ||||
|   friend std::ostream& operator << ( std::ostream& os, NonPOD const& npod ) | ||||
|     { return os << '(' << npod.id << ')' ; } | ||||
|  | ||||
|   friend bool operator == ( NonPOD const& lhs, NonPOD const& rhs ) | ||||
|     { return lhs.id == rhs.id ; } | ||||
|  | ||||
|   std::string id ; | ||||
| } ; | ||||
|  | ||||
| template<class T> | ||||
| void test ( T const& y, T const& z ) | ||||
| { | ||||
|   boost::value_initialized<T> x ; | ||||
|   BOOST_CHECK ( y == x ) ; | ||||
|   BOOST_CHECK ( y == boost::get(x) ) ; | ||||
|   static_cast<T&>(x) = z ; | ||||
|   boost::get(x) = z ; | ||||
|   BOOST_CHECK ( x == z ) ; | ||||
|  | ||||
|   boost::value_initialized<T> const x_c ; | ||||
|   BOOST_CHECK ( y == x_c ) ; | ||||
|   BOOST_CHECK ( y == boost::get(x_c) ) ; | ||||
|   T& x_c_ref = x_c ; | ||||
|   x_c_ref = z ; | ||||
|   BOOST_CHECK ( x_c == z ) ; | ||||
|  | ||||
| #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) | ||||
|   boost::value_initialized<T const> cx ; | ||||
|   BOOST_CHECK ( y == cx ) ; | ||||
|   BOOST_CHECK ( y == boost::get(cx) ) ; | ||||
|  | ||||
|   boost::value_initialized<T const> const cx_c ; | ||||
|   BOOST_CHECK ( y == cx_c ) ; | ||||
|   BOOST_CHECK ( y == boost::get(cx_c) ) ; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| int test_main(int, char **) | ||||
| { | ||||
|   test( 0,1234 ) ; | ||||
|   test( 0.0,12.34 ) ; | ||||
|   test( POD(0,0,0.0), POD('a',1234,56.78) ) ; | ||||
|   test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ; | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| unsigned int expected_failures = 0; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -1,37 +0,0 @@ | ||||
| // (C) 2002, Fernando Luis Cacciola Carballal. | ||||
| // | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
| // Test program for "boost/utility/value_init.hpp" | ||||
| // | ||||
| // Initial: 21 Agu 2002 | ||||
|  | ||||
| #include <iostream> | ||||
| #include <string> | ||||
|  | ||||
| #include "boost/utility/value_init.hpp" | ||||
|  | ||||
| #ifdef __BORLANDC__ | ||||
| #pragma hdrstop | ||||
| #endif | ||||
|  | ||||
| #include "boost/test/minimal.hpp" | ||||
|  | ||||
| int test_main(int, char **) | ||||
| { | ||||
|   boost::value_initialized<int> const x_c ; | ||||
|  | ||||
|   get(x_c) = 1234 ; // this should produce an ERROR | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| unsigned int expected_failures = 0; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -1,36 +0,0 @@ | ||||
| // (C) 2002, Fernando Luis Cacciola Carballal. | ||||
| // | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
| // Test program for "boost/utility/value_init.hpp" | ||||
| // | ||||
| // Initial: 21 Agu 2002 | ||||
|  | ||||
| #include <iostream> | ||||
| #include <string> | ||||
|  | ||||
| #include "boost/utility/value_init.hpp" | ||||
|  | ||||
| #ifdef __BORLANDC__ | ||||
| #pragma hdrstop | ||||
| #endif | ||||
|  | ||||
| #include "boost/test/minimal.hpp" | ||||
|  | ||||
| int test_main(int, char **) | ||||
| { | ||||
|   boost::value_initialized<int const> cx ; | ||||
|  | ||||
|   get(cx) = 1234 ; // this should produce an ERROR | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| unsigned int expected_failures = 0; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| @@ -1,37 +0,0 @@ | ||||
| // (C) 2002, Fernando Luis Cacciola Carballal. | ||||
| // | ||||
| // Distributed under the Boost Software License, Version 1.0. (See | ||||
| // accompanying file LICENSE_1_0.txt or copy at | ||||
| // http://www.boost.org/LICENSE_1_0.txt) | ||||
| // | ||||
| // Test program for "boost/utility/value_init.hpp" | ||||
| // | ||||
| // Initial: 21 Agu 2002 | ||||
|  | ||||
| #include <iostream> | ||||
| #include <string> | ||||
|  | ||||
| #include "boost/utility/value_init.hpp" | ||||
|  | ||||
| #ifdef __BORLANDC__ | ||||
| #pragma hdrstop | ||||
| #endif | ||||
|  | ||||
| #include "boost/test/minimal.hpp" | ||||
|  | ||||
| int test_main(int, char **) | ||||
| { | ||||
|   boost::value_initialized<int const> const cx_c ; | ||||
|  | ||||
|   get(cx_c) = 1234 ; // this should produce an ERROR | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| unsigned int expected_failures = 0; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user