forked from boostorg/utility
		
	Compare commits
	
		
			280 Commits
		
	
	
		
			svn-branch
			...
			boost-1.31
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					2af1ebee76 | ||
| 
						 | 
					eff257498c | ||
| 
						 | 
					ca866f21b2 | ||
| 
						 | 
					bd5abfb4d0 | ||
| 
						 | 
					06e6a36cea | ||
| 
						 | 
					0eb427cabe | ||
| 
						 | 
					7d6f944d85 | ||
| 
						 | 
					806745f24e | ||
| 
						 | 
					4231f774e4 | ||
| 
						 | 
					dfc320124f | ||
| 
						 | 
					be43ba1569 | ||
| 
						 | 
					f3f879555a | ||
| 
						 | 
					3155044abd | ||
| 
						 | 
					484d184de5 | ||
| 
						 | 
					3305cf1592 | ||
| 
						 | 
					ec36cd8c54 | ||
| 
						 | 
					61fb5a0b8f | ||
| 
						 | 
					8024c3e9c7 | ||
| 
						 | 
					2f5945d0cd | ||
| 
						 | 
					929517d6d7 | ||
| 
						 | 
					abcab174a5 | ||
| 
						 | 
					801be90699 | ||
| 
						 | 
					265c2348b8 | ||
| 
						 | 
					fb95bcc64c | ||
| 
						 | 
					aedc410525 | ||
| 
						 | 
					7fa440c154 | ||
| 
						 | 
					746e0fad2b | ||
| 
						 | 
					1616f6f5a8 | ||
| 
						 | 
					ca3e7d8530 | ||
| 
						 | 
					f0f753ba6c | ||
| 
						 | 
					532065b51b | ||
| 
						 | 
					4bfb534bae | ||
| 
						 | 
					95ba7a4381 | ||
| 
						 | 
					e92213431e | ||
| 
						 | 
					7dd7daee1b | ||
| 
						 | 
					953cc46220 | ||
| 
						 | 
					b5ae0ad86b | ||
| 
						 | 
					c86fcbf456 | ||
| 
						 | 
					6ded8b9ad6 | ||
| 
						 | 
					bb6a6272e1 | ||
| 
						 | 
					242634b3fc | ||
| 
						 | 
					662cf14bf6 | ||
| 
						 | 
					fe3aaf62cd | ||
| 
						 | 
					cb189bd6be | ||
| 
						 | 
					f57c914b8f | ||
| 
						 | 
					7cec198e14 | ||
| 
						 | 
					52d3120528 | ||
| 
						 | 
					f1aff5670c | ||
| 
						 | 
					632f682292 | ||
| 
						 | 
					d1d0d6b788 | ||
| 
						 | 
					3bd833c8ff | ||
| 
						 | 
					1ef77b0853 | ||
| 
						 | 
					074007ab8c | ||
| 
						 | 
					c4b7aaf281 | ||
| 
						 | 
					22b8494e9a | ||
| 
						 | 
					c1c8329403 | ||
| 
						 | 
					20a89040e1 | ||
| 
						 | 
					1c7a2a1476 | ||
| 
						 | 
					7c40cc0b63 | ||
| 
						 | 
					73a9e0d351 | ||
| 
						 | 
					dc9856744a | ||
| 
						 | 
					88f4e47550 | ||
| 
						 | 
					1be04eeec5 | ||
| 
						 | 
					56acf9c325 | ||
| 
						 | 
					c6e3957efc | ||
| 
						 | 
					25e8284950 | ||
| 
						 | 
					37a6537a5b | ||
| 
						 | 
					80df1d8f12 | ||
| 
						 | 
					75afed7f17 | ||
| 
						 | 
					1d7066aee1 | ||
| 
						 | 
					12272a38d4 | ||
| 
						 | 
					04f901e52e | ||
| 
						 | 
					fabfb31bf6 | ||
| 
						 | 
					683701cd07 | ||
| 
						 | 
					119c64be0b | ||
| 
						 | 
					d429c9a7d8 | ||
| 
						 | 
					1e8216431b | ||
| 
						 | 
					e45b2e2136 | ||
| 
						 | 
					9e6951009b | ||
| 
						 | 
					a009a209f1 | ||
| 
						 | 
					97605056ed | ||
| 
						 | 
					8fcfa33d33 | ||
| 
						 | 
					aa65e3da3b | ||
| 
						 | 
					b4cfadb4d5 | ||
| 
						 | 
					45a6249668 | ||
| 
						 | 
					1d601aef4d | ||
| 
						 | 
					32fb45eba9 | ||
| 
						 | 
					2b7d10aceb | ||
| 
						 | 
					5dc62711e1 | ||
| 
						 | 
					252c02aca0 | ||
| 
						 | 
					9655beb7ba | ||
| 
						 | 
					f0ea53e77e | ||
| 
						 | 
					4755b42909 | ||
| 
						 | 
					ef9af03c6c | ||
| 
						 | 
					7439073cbf | ||
| 
						 | 
					aff985a563 | ||
| 
						 | 
					db425222d5 | ||
| 
						 | 
					e20af510f7 | ||
| 
						 | 
					d8230c6a73 | ||
| 
						 | 
					f5690787bf | ||
| 
						 | 
					a4fd7b32dd | ||
| 
						 | 
					f4336ec693 | ||
| 
						 | 
					03d906976b | ||
| 
						 | 
					4ba6a96822 | ||
| 
						 | 
					1ea4140d56 | ||
| 
						 | 
					351d4ecb15 | ||
| 
						 | 
					7fbf84dcc6 | ||
| 
						 | 
					3ff49b272d | ||
| 
						 | 
					5b52e3d418 | ||
| 
						 | 
					8c0eb498d3 | ||
| 
						 | 
					48a81ef7ea | ||
| 
						 | 
					f7610c9b26 | ||
| 
						 | 
					1755eaf019 | ||
| 
						 | 
					6b8b218efb | ||
| 
						 | 
					333d79b345 | ||
| 
						 | 
					f0fa436fe4 | ||
| 
						 | 
					13e6d78fa8 | ||
| 
						 | 
					7126ea2685 | ||
| 
						 | 
					a37518cb4a | ||
| 
						 | 
					64b3e8c3bd | ||
| 
						 | 
					339937380e | ||
| 
						 | 
					6156f0d302 | ||
| 
						 | 
					00560e8e17 | ||
| 
						 | 
					029ff9828f | ||
| 
						 | 
					ec188c7c3e | ||
| 
						 | 
					0a0296a5d0 | ||
| 
						 | 
					6e26a5bbe7 | ||
| 
						 | 
					dc1b6246a0 | ||
| 
						 | 
					15f69eaf14 | ||
| 
						 | 
					4774a0d325 | ||
| 
						 | 
					be78ab72c9 | ||
| 
						 | 
					0bc4a1b20d | ||
| 
						 | 
					c8b674d105 | ||
| 
						 | 
					b421d4725a | ||
| 
						 | 
					1662bb5713 | ||
| 
						 | 
					ad79a21abd | ||
| 
						 | 
					19645a52e6 | ||
| 
						 | 
					74c3077c9a | ||
| 
						 | 
					1f29191329 | ||
| 
						 | 
					4b636a7680 | ||
| 
						 | 
					e6fc2555f3 | ||
| 
						 | 
					e27d0fcf2a | ||
| 
						 | 
					2643c33b20 | ||
| 
						 | 
					71af1e77c8 | ||
| 
						 | 
					99e7406bd9 | ||
| 
						 | 
					413265f497 | ||
| 
						 | 
					fe44cdf09b | ||
| 
						 | 
					e413428d71 | ||
| 
						 | 
					88b9822db7 | ||
| 
						 | 
					24045c0cd7 | ||
| 
						 | 
					d2aa9f4a84 | ||
| 
						 | 
					d2a5fd169f | ||
| 
						 | 
					4e350d9934 | ||
| 
						 | 
					f3f697bbc8 | ||
| 
						 | 
					c7c09696db | ||
| 
						 | 
					dbcc58d984 | ||
| 
						 | 
					8231310c4d | ||
| 
						 | 
					2988140430 | ||
| 
						 | 
					7387966005 | ||
| 
						 | 
					e0a5a61375 | ||
| 
						 | 
					66ecd70689 | ||
| 
						 | 
					67f4f45653 | ||
| 
						 | 
					1bf28b3de2 | ||
| 
						 | 
					eb3c3435d7 | ||
| 
						 | 
					8a81d8b16c | ||
| 
						 | 
					bc9d8b13d0 | ||
| 
						 | 
					4768b167ab | ||
| 
						 | 
					591ff70ed1 | ||
| 
						 | 
					7bf2ad0b22 | ||
| 
						 | 
					409c79b2e4 | ||
| 
						 | 
					d0410691a1 | ||
| 
						 | 
					64e5115138 | ||
| 
						 | 
					7ae912d83c | ||
| 
						 | 
					2937f5876c | ||
| 
						 | 
					8619c9b5c3 | ||
| 
						 | 
					e4d5684f6b | ||
| 
						 | 
					3d69cf95da | ||
| 
						 | 
					18944572b7 | ||
| 
						 | 
					3e9d0f80c2 | ||
| 
						 | 
					a2c4d1990a | ||
| 
						 | 
					404261c6ee | ||
| 
						 | 
					87abc59612 | ||
| 
						 | 
					cb98ddf7db | ||
| 
						 | 
					7d2e6c9025 | ||
| 
						 | 
					75eaa14a18 | ||
| 
						 | 
					082d6e3b32 | ||
| 
						 | 
					35b3770b6f | ||
| 
						 | 
					5b9d20c7e2 | ||
| 
						 | 
					5bbed2372e | ||
| 
						 | 
					a9d407d239 | ||
| 
						 | 
					3ca4a33a65 | ||
| 
						 | 
					95197f427c | ||
| 
						 | 
					84cdfb032c | ||
| 
						 | 
					ec2ceb9c96 | ||
| 
						 | 
					6286c893fd | ||
| 
						 | 
					354aef0e8c | ||
| 
						 | 
					139e33c36d | ||
| 
						 | 
					e01de59cdd | ||
| 
						 | 
					686f822dea | ||
| 
						 | 
					9961d5c9af | ||
| 
						 | 
					628be0d125 | ||
| 
						 | 
					633e45f61a | ||
| 
						 | 
					2f357c3805 | ||
| 
						 | 
					cda0894d0d | ||
| 
						 | 
					117720a8bc | ||
| 
						 | 
					a6f6c3613a | ||
| 
						 | 
					7914f5b931 | ||
| 
						 | 
					a1add0a6f6 | ||
| 
						 | 
					c032b337c4 | ||
| 
						 | 
					ec363261ae | ||
| 
						 | 
					97cde2183d | ||
| 
						 | 
					7f43c682db | ||
| 
						 | 
					0c9eee3c6b | ||
| 
						 | 
					3b1afa3ba6 | ||
| 
						 | 
					93e6a75125 | ||
| 
						 | 
					52f8a7c0ca | ||
| 
						 | 
					55bfeb646f | ||
| 
						 | 
					75c9dd3be1 | ||
| 
						 | 
					6392e2788f | ||
| 
						 | 
					6a97f3f9ba | ||
| 
						 | 
					6e5f52e279 | ||
| 
						 | 
					7f92bed902 | ||
| 
						 | 
					d68a11cc42 | ||
| 
						 | 
					328a81e194 | ||
| 
						 | 
					31d0908b74 | ||
| 
						 | 
					32c77599f4 | ||
| 
						 | 
					812ebf3562 | ||
| 
						 | 
					37f476013d | ||
| 
						 | 
					9f3104166f | ||
| 
						 | 
					64cc0daf34 | ||
| 
						 | 
					d5d64df124 | ||
| 
						 | 
					0edcfcd5c1 | ||
| 
						 | 
					50ba2d419a | ||
| 
						 | 
					ff3a77ca5a | ||
| 
						 | 
					4eaed6c23d | ||
| 
						 | 
					4d0dd46471 | ||
| 
						 | 
					9c2549bd00 | ||
| 
						 | 
					b7c8e0c17f | ||
| 
						 | 
					dd3cfe1837 | ||
| 
						 | 
					43f525298e | ||
| 
						 | 
					1bb1898ab9 | ||
| 
						 | 
					9578f24be9 | ||
| 
						 | 
					46fae3aed2 | ||
| 
						 | 
					e35f91a70a | ||
| 
						 | 
					851052fcca | ||
| 
						 | 
					5ef81b2952 | ||
| 
						 | 
					ef2851c053 | ||
| 
						 | 
					0b4387cff5 | ||
| 
						 | 
					a40cf11fbf | ||
| 
						 | 
					5c495cd223 | ||
| 
						 | 
					cf1296dff8 | ||
| 
						 | 
					d6d88db6e8 | ||
| 
						 | 
					85c2a35257 | ||
| 
						 | 
					836d8b1c64 | ||
| 
						 | 
					98d8c8ab71 | ||
| 
						 | 
					db45013339 | ||
| 
						 | 
					a55c37e7f6 | ||
| 
						 | 
					46a270fcca | ||
| 
						 | 
					967856518e | ||
| 
						 | 
					7f93e739fe | ||
| 
						 | 
					2cd1422514 | ||
| 
						 | 
					feb370b201 | ||
| 
						 | 
					d1b34e64d8 | ||
| 
						 | 
					b9a1eead40 | ||
| 
						 | 
					1e4bfac98c | ||
| 
						 | 
					3bb504fbf3 | ||
| 
						 | 
					5029791c90 | ||
| 
						 | 
					a1a68f0970 | ||
| 
						 | 
					f8543d79eb | ||
| 
						 | 
					f353415136 | ||
| 
						 | 
					26240403b0 | ||
| 
						 | 
					3a39729b58 | ||
| 
						 | 
					096c961d9a | ||
| 
						 | 
					01fe04a6a2 | ||
| 
						 | 
					7ea4014993 | ||
| 
						 | 
					d50b374f88 | ||
| 
						 | 
					27dfb25570 | ||
| 
						 | 
					b5ed77985e | ||
| 
						 | 
					61243bd15f | ||
| 
						 | 
					368b94d804 | 
							
								
								
									
										116
									
								
								Assignable.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								Assignable.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
			
		||||
<HTML>
 | 
			
		||||
<!--
 | 
			
		||||
  -- Copyright (c) Jeremy Siek 2000
 | 
			
		||||
  --
 | 
			
		||||
  -- Permission to use, copy, modify, distribute and sell this software
 | 
			
		||||
  -- and its documentation for any purpose is hereby granted without fee,
 | 
			
		||||
  -- provided that the above copyright notice appears in all copies and
 | 
			
		||||
  -- that both that copyright notice and this permission notice appear
 | 
			
		||||
  -- in supporting documentation.  Silicon Graphics makes no
 | 
			
		||||
  -- representations about the suitability of this software for any
 | 
			
		||||
  -- purpose.  It is provided "as is" without express or implied warranty.
 | 
			
		||||
  -->
 | 
			
		||||
<Head>
 | 
			
		||||
<Title>Assignable</Title>
 | 
			
		||||
</HEAD>
 | 
			
		||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b" 
 | 
			
		||||
        ALINK="#ff0000"> 
 | 
			
		||||
<IMG SRC="../../c++boost.gif" 
 | 
			
		||||
     ALT="C++ Boost" width="277" height="86"> 
 | 
			
		||||
<!--end header-->
 | 
			
		||||
<BR Clear>
 | 
			
		||||
<H1>Assignable</H1>
 | 
			
		||||
 | 
			
		||||
<h3>Description</h3>
 | 
			
		||||
A type is Assignable if it is possible to assign one object of the type
 | 
			
		||||
to another object of that type.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Notation</h3>
 | 
			
		||||
<Table>
 | 
			
		||||
<TR>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>T</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
is type that is a model of Assignable
 | 
			
		||||
</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>t</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
is an object of type <tt>T</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
</tr>
 | 
			
		||||
 | 
			
		||||
<TR>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>u</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
is an object of type <tt>T</tt> or possibly <tt>const T</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
</tr>
 | 
			
		||||
 | 
			
		||||
</table>
 | 
			
		||||
<h3>Definitions</h3>
 | 
			
		||||
<h3>Valid expressions</h3>
 | 
			
		||||
<Table border>
 | 
			
		||||
<TR>
 | 
			
		||||
<TH>
 | 
			
		||||
Name
 | 
			
		||||
</TH>
 | 
			
		||||
<TH>
 | 
			
		||||
Expression
 | 
			
		||||
</TH>
 | 
			
		||||
<TH>
 | 
			
		||||
Return type
 | 
			
		||||
</TH>
 | 
			
		||||
<TH>
 | 
			
		||||
Semantics
 | 
			
		||||
</TH>
 | 
			
		||||
</TR>
 | 
			
		||||
<TR>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
Assignment
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>t = u</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>T&</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>t</tt> is equivalent to <tt>u</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
</table>
 | 
			
		||||
<h3>Models</h3>
 | 
			
		||||
 | 
			
		||||
<UL>
 | 
			
		||||
<LI><tt>int</tt>
 | 
			
		||||
<LI><tt>std::pair</tt>
 | 
			
		||||
</UL>
 | 
			
		||||
 | 
			
		||||
<h3>See also</h3>
 | 
			
		||||
<a href="http://www.sgi.com/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
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										648
									
								
								Collection.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,648 @@
 | 
			
		||||
<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="../../c++boost.gif" 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> 
 | 
			
		||||
							
								
								
									
										210
									
								
								CopyConstructible.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								CopyConstructible.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,210 @@
 | 
			
		||||
<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="../../c++boost.gif" 
 | 
			
		||||
     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> 
 | 
			
		||||
							
								
								
									
										212
									
								
								LessThanComparable.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										212
									
								
								LessThanComparable.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,212 @@
 | 
			
		||||
<HTML>
 | 
			
		||||
<!--
 | 
			
		||||
  -- Copyright (c) Jeremy Siek 2000
 | 
			
		||||
  --
 | 
			
		||||
  -- Permission to use, copy, modify, distribute and sell this software
 | 
			
		||||
  -- and its documentation for any purpose is hereby granted without fee,
 | 
			
		||||
  -- provided that the above copyright notice appears in all copies and
 | 
			
		||||
  -- that both that copyright notice and this permission notice appear
 | 
			
		||||
  -- in supporting documentation.  Silicon Graphics makes no
 | 
			
		||||
  -- representations about the suitability of this software for any
 | 
			
		||||
  -- purpose.  It is provided "as is" without express or implied warranty.
 | 
			
		||||
  -->
 | 
			
		||||
<!--
 | 
			
		||||
  -- Copyright (c) 1996-1999
 | 
			
		||||
  -- Silicon Graphics Computer Systems, Inc.
 | 
			
		||||
  --
 | 
			
		||||
  -- Permission to use, copy, modify, distribute and sell this software
 | 
			
		||||
  -- and its documentation for any purpose is hereby granted without fee,
 | 
			
		||||
  -- provided that the above copyright notice appears in all copies and
 | 
			
		||||
  -- that both that copyright notice and this permission notice appear
 | 
			
		||||
  -- in supporting documentation.  Silicon Graphics makes no
 | 
			
		||||
  -- representations about the suitability of this software for any
 | 
			
		||||
  -- purpose.  It is provided "as is" without express or implied warranty.
 | 
			
		||||
  --
 | 
			
		||||
  -- Copyright (c) 1994
 | 
			
		||||
  -- Hewlett-Packard Company
 | 
			
		||||
  --
 | 
			
		||||
  -- Permission to use, copy, modify, distribute and sell this software
 | 
			
		||||
  -- and its documentation for any purpose is hereby granted without fee,
 | 
			
		||||
  -- provided that the above copyright notice appears in all copies and
 | 
			
		||||
  -- that both that copyright notice and this permission notice appear
 | 
			
		||||
  -- in supporting documentation.  Hewlett-Packard Company makes no
 | 
			
		||||
  -- representations about the suitability of this software for any
 | 
			
		||||
  -- purpose.  It is provided "as is" without express or implied warranty.
 | 
			
		||||
  --
 | 
			
		||||
  -->
 | 
			
		||||
<Head>
 | 
			
		||||
<Title>LessThanComparable</Title>
 | 
			
		||||
</Head>
 | 
			
		||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b" 
 | 
			
		||||
        ALINK="#ff0000"> 
 | 
			
		||||
<IMG SRC="../../c++boost.gif" 
 | 
			
		||||
     ALT="C++ Boost" width="277" height="86"> 
 | 
			
		||||
<!--end header-->
 | 
			
		||||
<BR Clear>
 | 
			
		||||
<H1>LessThanComparable</H1>
 | 
			
		||||
 | 
			
		||||
<h3>Description</h3>
 | 
			
		||||
A type is LessThanComparable if it is ordered: it must
 | 
			
		||||
be possible to compare two objects of that type using <tt>operator<</tt>, and
 | 
			
		||||
<tt>operator<</tt> must be a strict weak ordering relation.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Refinement of</h3>
 | 
			
		||||
<h3>Associated types</h3>
 | 
			
		||||
<h3>Notation</h3>
 | 
			
		||||
<Table>
 | 
			
		||||
<TR>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>X</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
A type that is a model of LessThanComparable
 | 
			
		||||
</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
<TR>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>x</tt>, <tt>y</tt>, <tt>z</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
Object of type <tt>X</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
</tr>
 | 
			
		||||
</table>
 | 
			
		||||
<h3>Definitions</h3>
 | 
			
		||||
Consider the relation <tt>!(x < y) && !(y < x)</tt>.  If this relation is
 | 
			
		||||
transitive (that is, if <tt>!(x < y) && !(y < x) && !(y < z) && !(z < y)</tt>
 | 
			
		||||
implies <tt>!(x < z) && !(z < x)</tt>), then it satisfies the mathematical
 | 
			
		||||
definition of an equivalence relation.  In this case, <tt>operator<</tt>
 | 
			
		||||
is a <i>strict weak ordering</i>.
 | 
			
		||||
<P>
 | 
			
		||||
If <tt>operator<</tt> is a strict weak ordering, and if each equivalence class
 | 
			
		||||
has only a single element, then <tt>operator<</tt> is a <i>total ordering</i>.
 | 
			
		||||
<h3>Valid expressions</h3>
 | 
			
		||||
<Table border>
 | 
			
		||||
<TR>
 | 
			
		||||
<TH>
 | 
			
		||||
Name
 | 
			
		||||
</TH>
 | 
			
		||||
<TH>
 | 
			
		||||
Expression
 | 
			
		||||
</TH>
 | 
			
		||||
<TH>
 | 
			
		||||
Type requirements
 | 
			
		||||
</TH>
 | 
			
		||||
<TH>
 | 
			
		||||
Return type
 | 
			
		||||
</TH>
 | 
			
		||||
</TR>
 | 
			
		||||
<TR>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
Less
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>x < y</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
 
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
Convertible to <tt>bool</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Expression semantics</h3>
 | 
			
		||||
<Table border>
 | 
			
		||||
<TR>
 | 
			
		||||
<TH>
 | 
			
		||||
Name
 | 
			
		||||
</TH>
 | 
			
		||||
<TH>
 | 
			
		||||
Expression
 | 
			
		||||
</TH>
 | 
			
		||||
<TH>
 | 
			
		||||
Precondition
 | 
			
		||||
</TH>
 | 
			
		||||
<TH>
 | 
			
		||||
Semantics
 | 
			
		||||
</TH>
 | 
			
		||||
<TH>
 | 
			
		||||
Postcondition
 | 
			
		||||
</TH>
 | 
			
		||||
</TR>
 | 
			
		||||
<TR>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
Less
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>x < y</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>x</tt> and <tt>y</tt> are in the domain of <tt><</tt>
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
 
 | 
			
		||||
</TD>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<h3>Complexity guarantees</h3>
 | 
			
		||||
<h3>Invariants</h3>
 | 
			
		||||
<Table border>
 | 
			
		||||
<TR>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
Irreflexivity
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>x < x</tt> must be false.
 | 
			
		||||
</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
<TR>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
Antisymmetry
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>x < y</tt> implies !(y < x) <A href="#2">[2]</A>
 | 
			
		||||
</TD>
 | 
			
		||||
</TR>
 | 
			
		||||
<TR>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
Transitivity
 | 
			
		||||
</TD>
 | 
			
		||||
<TD VAlign=top>
 | 
			
		||||
<tt>x < y</tt> and <tt>y < z</tt> implies <tt>x < z</tt> <A href="#3">[3]</A>
 | 
			
		||||
</TD>
 | 
			
		||||
</tr>
 | 
			
		||||
</table>
 | 
			
		||||
<h3>Models</h3>
 | 
			
		||||
<UL>
 | 
			
		||||
<LI>
 | 
			
		||||
int
 | 
			
		||||
</UL>
 | 
			
		||||
<h3>Notes</h3>
 | 
			
		||||
<P><A name="1">[1]</A>
 | 
			
		||||
Only <tt>operator<</tt> is fundamental; the other inequality operators
 | 
			
		||||
are essentially syntactic sugar.
 | 
			
		||||
<P><A name="2">[2]</A>
 | 
			
		||||
Antisymmetry is a theorem, not an axiom: it follows from
 | 
			
		||||
irreflexivity and transitivity.
 | 
			
		||||
<P><A name="3">[3]</A>
 | 
			
		||||
Because of irreflexivity and transitivity, <tt>operator<</tt> always
 | 
			
		||||
satisfies the definition of a <i>partial ordering</i>.  The definition of
 | 
			
		||||
a <i>strict weak ordering</i> is stricter, and the definition of a
 | 
			
		||||
<i>total ordering</i> is stricter still.
 | 
			
		||||
<h3>See also</h3>
 | 
			
		||||
<A href="http://www.sgi.com/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> 
 | 
			
		||||
							
								
								
									
										92
									
								
								MultiPassInputIterator.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								MultiPassInputIterator.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
			
		||||
<HTML>
 | 
			
		||||
<!--
 | 
			
		||||
  -- Copyright (c) Jeremy Siek 2000
 | 
			
		||||
  --
 | 
			
		||||
  -- Permission to use, copy, modify, distribute and sell this software
 | 
			
		||||
  -- and its documentation for any purpose is hereby granted without fee,
 | 
			
		||||
  -- provided that the above copyright notice appears in all copies and
 | 
			
		||||
  -- that both that copyright notice and this permission notice appear
 | 
			
		||||
  -- in supporting documentation.  Silicon Graphics makes no
 | 
			
		||||
  -- representations about the suitability of this software for any
 | 
			
		||||
  -- purpose.  It is provided "as is" without express or implied warranty.
 | 
			
		||||
  -->
 | 
			
		||||
<Head>
 | 
			
		||||
<Title>MultiPassInputIterator</Title>
 | 
			
		||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b" 
 | 
			
		||||
	ALINK="#ff0000"> 
 | 
			
		||||
<IMG SRC="../../c++boost.gif" 
 | 
			
		||||
     ALT="C++ Boost" width="277" height="86"> 
 | 
			
		||||
 | 
			
		||||
<BR Clear>
 | 
			
		||||
 | 
			
		||||
<H2>
 | 
			
		||||
<A NAME="concept:MultiPassInputIterator"></A>
 | 
			
		||||
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.hmtl">Forward Iterator</a>. The
 | 
			
		||||
only difference is that a <a
 | 
			
		||||
href="http://www.sgi.com/tech/stl/ForwardIterator.hmtl">Forward Iterator</a>
 | 
			
		||||
requires the <TT>reference</TT> type to be <TT>value_type&</TT>, whereas
 | 
			
		||||
MultiPassInputIterator is like <a
 | 
			
		||||
href="http://www.sgi.com/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> 
 | 
			
		||||
							
								
								
									
										158
									
								
								OptionalPointee.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								OptionalPointee.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,158 @@
 | 
			
		||||
<HTML>
 | 
			
		||||
<Head>
 | 
			
		||||
<Title>OptionalPointee Concept</Title>
 | 
			
		||||
</HEAD>
 | 
			
		||||
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b" 
 | 
			
		||||
        ALINK="#ff0000"> 
 | 
			
		||||
<IMG SRC="../../c++boost.gif" 
 | 
			
		||||
     ALT="C++ Boost" width="277" height="86"> 
 | 
			
		||||
<!--end header-->
 | 
			
		||||
<BR Clear>
 | 
			
		||||
<H1>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>
 | 
			
		||||
							
								
								
									
										46
									
								
								addressof_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								addressof_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
// Copyright (C) 2002 Brad King (brad.king@kitware.com) 
 | 
			
		||||
//                    Doug Gregor (gregod@cs.rpi.edu)
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, sell and distribute this software is granted
 | 
			
		||||
// provided this copyright notice appears in all copies.
 | 
			
		||||
// Permission to modify the code and to distribute modified code is granted
 | 
			
		||||
// provided this copyright notice appears in all copies, and a notice
 | 
			
		||||
// that the code was modified is included with the copyright notice.
 | 
			
		||||
//
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
#define BOOST_INCLUDE_MAIN
 | 
			
		||||
#include <boost/test/test_tools.hpp>
 | 
			
		||||
#include <boost/utility.hpp>
 | 
			
		||||
 | 
			
		||||
struct useless_type {};
 | 
			
		||||
 | 
			
		||||
class nonaddressable {
 | 
			
		||||
public:
 | 
			
		||||
  void dummy(); // Silence GCC warning: all member of class are private
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
  useless_type operator&() const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int test_main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  nonaddressable* px = new nonaddressable();
 | 
			
		||||
 | 
			
		||||
  nonaddressable& x = *px;
 | 
			
		||||
  BOOST_TEST(boost::addressof(x) == px);
 | 
			
		||||
 | 
			
		||||
  const nonaddressable& cx = *px;
 | 
			
		||||
  BOOST_TEST(boost::addressof(cx) == static_cast<const nonaddressable*>(px));
 | 
			
		||||
 | 
			
		||||
  volatile nonaddressable& vx = *px;
 | 
			
		||||
  BOOST_TEST(boost::addressof(vx) == static_cast<volatile nonaddressable*>(px));
 | 
			
		||||
 | 
			
		||||
  const volatile nonaddressable& cvx = *px;
 | 
			
		||||
  BOOST_TEST(boost::addressof(cvx) == static_cast<const volatile nonaddressable*>(px));
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										57
									
								
								assert.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								assert.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
<!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="../../c++boost.gif" alt="c++boost.gif (8819 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>
 | 
			
		||||
							
								
								
									
										105
									
								
								assert_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								assert_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
//
 | 
			
		||||
//  assert_test.cpp - a test for boost/assert.hpp
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//
 | 
			
		||||
//  Permission to copy, use, modify, sell and distribute this software
 | 
			
		||||
//  is granted provided this copyright notice appears in all copies.
 | 
			
		||||
//  This software is provided "as is" without express or implied
 | 
			
		||||
//  warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <boost/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 <cstdio>
 | 
			
		||||
 | 
			
		||||
int handler_invoked = 0;
 | 
			
		||||
 | 
			
		||||
void boost::assertion_failed(char const * expr, char const * function, char const * file, long line)
 | 
			
		||||
{
 | 
			
		||||
    std::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();
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										355
									
								
								base_from_member.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										355
									
								
								base_from_member.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,355 @@
 | 
			
		||||
<!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="../../c++boost.gif" 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>.
 | 
			
		||||
The class template is forward declared in <i><a href="../../boost/utility_fwd.hpp">boost/utility_fwd.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>
 | 
			
		||||
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>
 | 
			
		||||
 | 
			
		||||
<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><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: 14 June 2003</p>
 | 
			
		||||
 | 
			
		||||
<p>Copyright 2001, 2003 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>
 | 
			
		||||
							
								
								
									
										595
									
								
								base_from_member_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										595
									
								
								base_from_member_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,595 @@
 | 
			
		||||
//  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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										258
									
								
								binary_search_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										258
									
								
								binary_search_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,258 @@
 | 
			
		||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify,
 | 
			
		||||
// sell and distribute this software is granted provided this
 | 
			
		||||
// copyright notice appears in all copies. This software is provided
 | 
			
		||||
// "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
// to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include <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>
 | 
			
		||||
 | 
			
		||||
#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
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										764
									
								
								call_traits.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,764 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type"
 | 
			
		||||
content="text/html; charset=iso-8859-1">
 | 
			
		||||
<meta name="Template"
 | 
			
		||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
 | 
			
		||||
<title>Call Traits</title>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
 | 
			
		||||
vlink="#800080">
 | 
			
		||||
 | 
			
		||||
<h1><img src="../../c++boost.gif" width="276" height="86">Header
 | 
			
		||||
<<a href="../../boost/detail/call_traits.hpp">boost/call_traits.hpp</a>></h1>
 | 
			
		||||
 | 
			
		||||
<p>All of the contents of <boost/call_traits.hpp> are
 | 
			
		||||
defined inside namespace boost.</p>
 | 
			
		||||
 | 
			
		||||
<p>The template class call_traits<T> encapsulates the
 | 
			
		||||
"best" method to pass a parameter of some type T to or
 | 
			
		||||
from a function, and consists of a collection of typedefs defined
 | 
			
		||||
as in the table below. The purpose of call_traits is to ensure
 | 
			
		||||
that problems like "<a href="#refs">references to references</a>"
 | 
			
		||||
never occur, and that parameters are passed in the most efficient
 | 
			
		||||
manner possible (see <a href="#examples">examples</a>). In each
 | 
			
		||||
case if your existing practice is to use the type defined on the
 | 
			
		||||
left, then replace it with the call_traits defined type on the
 | 
			
		||||
right. </p>
 | 
			
		||||
 | 
			
		||||
<p>Note that for compilers that do not support either partial
 | 
			
		||||
specialization or member templates, no benefit will occur from
 | 
			
		||||
using call_traits: the call_traits defined types will always be
 | 
			
		||||
the same as the existing practice in this case. In addition if
 | 
			
		||||
only member templates and not partial template specialisation is
 | 
			
		||||
support by the compiler (for example Visual C++ 6) then
 | 
			
		||||
call_traits can not be used with array types (although it can be
 | 
			
		||||
used to solve the reference to reference problem).</p>
 | 
			
		||||
 | 
			
		||||
<table border="0" cellpadding="7" cellspacing="1" width="797">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#008080"><p
 | 
			
		||||
        align="center">Existing practice</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="35%" bgcolor="#008080"><p
 | 
			
		||||
        align="center">call_traits equivalent</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="32%" bgcolor="#008080"><p
 | 
			
		||||
        align="center">Description</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="16%" bgcolor="#008080"><p
 | 
			
		||||
        align="center">Notes</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">T<br>
 | 
			
		||||
        (return by value)</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="35%"><p align="center"><code>call_traits<T>::value_type</code></p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="32%">Defines a type that
 | 
			
		||||
        represents the "value" of type T. Use this for
 | 
			
		||||
        functions that return by value, or possibly for stored
 | 
			
		||||
        values of type T.</td>
 | 
			
		||||
        <td valign="top" width="16%"><p align="center">2</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">T&<br>
 | 
			
		||||
        (return value)</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="35%"><p align="center"><code>call_traits<T>::reference</code></p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="32%">Defines a type that
 | 
			
		||||
        represents a reference to type T. Use for functions that
 | 
			
		||||
        would normally return a T&.</td>
 | 
			
		||||
        <td valign="top" width="16%"><p align="center">1</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        T&<br>
 | 
			
		||||
        (return value)</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="35%"><p align="center"><code>call_traits<T>::const_reference</code></p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="32%">Defines a type that
 | 
			
		||||
        represents a constant reference to type T. Use for
 | 
			
		||||
        functions that would normally return a const T&.</td>
 | 
			
		||||
        <td valign="top" width="16%"><p align="center">1</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        T&<br>
 | 
			
		||||
        (function parameter)</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="35%"><p align="center"><code>call_traits<T>::param_type</code></p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="32%">Defines a type that
 | 
			
		||||
        represents the "best" way to pass a parameter
 | 
			
		||||
        of type T to a function.</td>
 | 
			
		||||
        <td valign="top" width="16%"><p align="center">1,3</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p>Notes:</p>
 | 
			
		||||
 | 
			
		||||
<ol>
 | 
			
		||||
    <li>If T is already reference type, then call_traits is
 | 
			
		||||
        defined such that <a href="#refs">references to
 | 
			
		||||
        references</a> do not occur (requires partial
 | 
			
		||||
        specialization).</li>
 | 
			
		||||
    <li>If T is an array type, then call_traits defines <code>value_type</code>
 | 
			
		||||
        as a "constant pointer to type" rather than an
 | 
			
		||||
        "array of type" (requires partial
 | 
			
		||||
        specialization). Note that if you are using value_type as
 | 
			
		||||
        a stored value then this will result in storing a "constant
 | 
			
		||||
        pointer to an array" rather than the array itself.
 | 
			
		||||
        This may or may not be a good thing depending upon what
 | 
			
		||||
        you actually need (in other words take care!).</li>
 | 
			
		||||
    <li>If T is a small built in type or a pointer, then <code>param_type</code>
 | 
			
		||||
        is defined as <code>T const</code>, instead of <code>T
 | 
			
		||||
        const&</code>. This can improve the ability of the
 | 
			
		||||
        compiler to optimize loops in the body of the function if
 | 
			
		||||
        they depend upon the passed parameter, the semantics of
 | 
			
		||||
        the passed parameter is otherwise unchanged (requires
 | 
			
		||||
        partial specialization).</li>
 | 
			
		||||
</ol>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<h3>Copy constructibility</h3>
 | 
			
		||||
 | 
			
		||||
<p>The following table defines which call_traits types can always
 | 
			
		||||
be copy-constructed from which other types, those entries marked
 | 
			
		||||
with a '?' are true only if and only if T is copy constructible:</p>
 | 
			
		||||
 | 
			
		||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"> </td>
 | 
			
		||||
        <td valign="top" colspan="5" width="85%"
 | 
			
		||||
        bgcolor="#008080"><p align="center">To:</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#008080">From:</td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">T</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">value_type</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">reference</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">const_reference</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">param_type</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">N</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">N</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">N</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">N</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">?</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">N</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">N</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<p>If T is an assignable type the following assignments are
 | 
			
		||||
possible:</p>
 | 
			
		||||
 | 
			
		||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"> </td>
 | 
			
		||||
        <td valign="top" colspan="5" width="85%"
 | 
			
		||||
        bgcolor="#008080"><p align="center">To:</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#008080">From:</td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">T</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">value_type</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">reference</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">const_reference</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">param_type</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">T</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">value_type</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">reference</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">const_reference</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0">param_type</td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">Y</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">-</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<h3><a name="examples"></a>Examples</h3>
 | 
			
		||||
 | 
			
		||||
<p>The following table shows the effect that call_traits has on
 | 
			
		||||
various types, the table assumes that the compiler supports
 | 
			
		||||
partial specialization: if it doesn't then all types behave in
 | 
			
		||||
the same way as the entry for "myclass", and
 | 
			
		||||
call_traits can not be used with reference or array types.</p>
 | 
			
		||||
 | 
			
		||||
<table border="0" cellpadding="7" cellspacing="1" width="766">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%"> </td>
 | 
			
		||||
        <td valign="top" colspan="5" width="85%"
 | 
			
		||||
        bgcolor="#008080"><p align="center">Call_traits type:</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#008080"><p
 | 
			
		||||
        align="center">Original type T</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">value_type</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">reference</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">const_reference</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">param_type</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">Applies to:</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">myclass</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">myclass</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">myclass&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        myclass&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">myclass
 | 
			
		||||
        const&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All user
 | 
			
		||||
        defined types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">int</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int const</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All small
 | 
			
		||||
        built-in types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">int*</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int*</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int*&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int*const&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int* const</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All
 | 
			
		||||
        pointer types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All
 | 
			
		||||
        reference types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">const int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const
 | 
			
		||||
        int&</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All
 | 
			
		||||
        constant-references.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">int[3]</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int*</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">int(&)[3]</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int(&)[3]</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int*
 | 
			
		||||
        const</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All array
 | 
			
		||||
        types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <td valign="top" width="17%" bgcolor="#C0C0C0"><p
 | 
			
		||||
        align="center">const int[3]</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int*</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int(&)[3]</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int(&)[3]</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">const int*
 | 
			
		||||
        const</p>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td valign="top" width="17%"><p align="center">All
 | 
			
		||||
        constant-array types.</p>
 | 
			
		||||
        </td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<p> </p>
 | 
			
		||||
 | 
			
		||||
<h4>Example 1:</h4>
 | 
			
		||||
 | 
			
		||||
<p>The following class is a trivial class that stores some type T
 | 
			
		||||
by value (see the <a href="call_traits_test.cpp">call_traits_test.cpp</a>
 | 
			
		||||
file), the aim is to illustrate how each of the available
 | 
			
		||||
call_traits typedefs may be used:</p>
 | 
			
		||||
 | 
			
		||||
<pre>template <class T>
 | 
			
		||||
struct contained
 | 
			
		||||
{
 | 
			
		||||
   // define our typedefs first, arrays are stored by value
 | 
			
		||||
   // so value_type is not the same as result_type:
 | 
			
		||||
   typedef typename boost::call_traits<T>::param_type       param_type;
 | 
			
		||||
   typedef typename boost::call_traits<T>::reference        reference;
 | 
			
		||||
   typedef typename boost::call_traits<T>::const_reference  const_reference;
 | 
			
		||||
   typedef T                                                value_type;
 | 
			
		||||
   typedef typename boost::call_traits<T>::value_type       result_type;
 | 
			
		||||
 | 
			
		||||
   // stored value:
 | 
			
		||||
   value_type v_;
 | 
			
		||||
   
 | 
			
		||||
   // constructors:
 | 
			
		||||
   contained() {}
 | 
			
		||||
   contained(param_type p) : v_(p){}
 | 
			
		||||
   // return byval:
 | 
			
		||||
   result_type value() { return v_; }
 | 
			
		||||
   // return by_ref:
 | 
			
		||||
   reference get() { return v_; }
 | 
			
		||||
   const_reference const_get()const { return v_; }
 | 
			
		||||
   // pass value:
 | 
			
		||||
   void call(param_type p){}
 | 
			
		||||
 | 
			
		||||
};</pre>
 | 
			
		||||
 | 
			
		||||
<h4><a name="refs"></a>Example 2 (the reference to reference
 | 
			
		||||
problem):</h4>
 | 
			
		||||
 | 
			
		||||
<p>Consider the definition of std::binder1st:</p>
 | 
			
		||||
 | 
			
		||||
<pre>template <class Operation> 
 | 
			
		||||
class binder1st : 
 | 
			
		||||
   public unary_function<typename Operation::second_argument_type, typename Operation::result_type> 
 | 
			
		||||
{ 
 | 
			
		||||
protected: 
 | 
			
		||||
   Operation op; 
 | 
			
		||||
   typename Operation::first_argument_type value; 
 | 
			
		||||
public: 
 | 
			
		||||
   binder1st(const Operation& x, const typename Operation::first_argument_type& y); 
 | 
			
		||||
   typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const; 
 | 
			
		||||
}; </pre>
 | 
			
		||||
 | 
			
		||||
<p>Now consider what happens in the relatively common case that
 | 
			
		||||
the functor takes its second argument as a reference, that
 | 
			
		||||
implies that <code>Operation::second_argument_type</code> is a
 | 
			
		||||
reference type, <code>operator()</code> will now end up taking a
 | 
			
		||||
reference to a reference as an argument, and that is not
 | 
			
		||||
currently legal. The solution here is to modify <code>operator()</code>
 | 
			
		||||
to use call_traits:</p>
 | 
			
		||||
 | 
			
		||||
<pre>typename Operation::result_type operator()(typename call_traits<typename Operation::second_argument_type>::param_type x) const;</pre>
 | 
			
		||||
 | 
			
		||||
<p>Now in the case that <code>Operation::second_argument_type</code>
 | 
			
		||||
is a reference type, the argument is passed as a reference, and
 | 
			
		||||
the no "reference to reference" occurs.</p>
 | 
			
		||||
 | 
			
		||||
<h4><a name="ex3"></a>Example 3 (the make_pair problem):</h4>
 | 
			
		||||
 | 
			
		||||
<p>If we pass the name of an array as one (or both) arguments to <code>std::make_pair</code>,
 | 
			
		||||
then template argument deduction deduces the passed parameter as
 | 
			
		||||
"const reference to array of T", this also applies to
 | 
			
		||||
string literals (which are really array literals). Consequently
 | 
			
		||||
instead of returning a pair of pointers, it tries to return a
 | 
			
		||||
pair of arrays, and since an array type is not copy-constructible
 | 
			
		||||
the code fails to compile. One solution is to explicitly cast the
 | 
			
		||||
arguments to make_pair to pointers, but call_traits provides a
 | 
			
		||||
better (i.e. automatic) solution (and one that works safely even
 | 
			
		||||
in generic code where the cast might do the wrong thing):</p>
 | 
			
		||||
 | 
			
		||||
<pre>template <class T1, class T2>
 | 
			
		||||
std::pair<
 | 
			
		||||
   typename boost::call_traits<T1>::value_type, 
 | 
			
		||||
   typename boost::call_traits<T2>::value_type> 
 | 
			
		||||
      make_pair(const T1& t1, const T2& t2)
 | 
			
		||||
{
 | 
			
		||||
   return std::pair<
 | 
			
		||||
      typename boost::call_traits<T1>::value_type, 
 | 
			
		||||
      typename boost::call_traits<T2>::value_type>(t1, t2);
 | 
			
		||||
}</pre>
 | 
			
		||||
 | 
			
		||||
<p>Here, the deduced argument types will be automatically
 | 
			
		||||
degraded to pointers if the deduced types are arrays, similar
 | 
			
		||||
situations occur in the standard binders and adapters: in
 | 
			
		||||
principle in any function that "wraps" a temporary
 | 
			
		||||
whose type is deduced. Note that the function arguments to
 | 
			
		||||
make_pair are not expressed in terms of call_traits: doing so
 | 
			
		||||
would prevent template argument deduction from functioning.</p>
 | 
			
		||||
 | 
			
		||||
<h4><a name="ex4"></a>Example 4 (optimising fill):</h4>
 | 
			
		||||
 | 
			
		||||
<p>The call_traits template will "optimize" the passing
 | 
			
		||||
of a small built-in type as a function parameter, this mainly has
 | 
			
		||||
an effect when the parameter is used within a loop body. In the
 | 
			
		||||
following example (see <a
 | 
			
		||||
href="../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>
 | 
			
		||||
							
								
								
									
										431
									
								
								call_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										431
									
								
								call_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,431 @@
 | 
			
		||||
//  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 <boost/type_traits/type_traits_test.hpp>
 | 
			
		||||
 | 
			
		||||
// 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;
 | 
			
		||||
 | 
			
		||||
   type_test(comparible_UDT, boost::call_traits<comparible_UDT>::value_type)
 | 
			
		||||
   type_test(comparible_UDT&, boost::call_traits<comparible_UDT>::reference)
 | 
			
		||||
   type_test(const comparible_UDT&, boost::call_traits<comparible_UDT>::const_reference)
 | 
			
		||||
   type_test(const comparible_UDT&, boost::call_traits<comparible_UDT>::param_type)
 | 
			
		||||
   type_test(int, boost::call_traits<int>::value_type)
 | 
			
		||||
   type_test(int&, boost::call_traits<int>::reference)
 | 
			
		||||
   type_test(const int&, boost::call_traits<int>::const_reference)
 | 
			
		||||
   type_test(const int, boost::call_traits<int>::param_type)
 | 
			
		||||
   type_test(int*, boost::call_traits<int*>::value_type)
 | 
			
		||||
   type_test(int*&, boost::call_traits<int*>::reference)
 | 
			
		||||
   type_test(int*const&, boost::call_traits<int*>::const_reference)
 | 
			
		||||
   type_test(int*const, boost::call_traits<int*>::param_type)
 | 
			
		||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES)
 | 
			
		||||
   type_test(int&, boost::call_traits<int&>::value_type)
 | 
			
		||||
   type_test(int&, boost::call_traits<int&>::reference)
 | 
			
		||||
   type_test(const int&, boost::call_traits<int&>::const_reference)
 | 
			
		||||
   type_test(int&, boost::call_traits<int&>::param_type)
 | 
			
		||||
#if !(defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1)))
 | 
			
		||||
   type_test(int&, boost::call_traits<cr_type>::value_type)
 | 
			
		||||
   type_test(int&, boost::call_traits<cr_type>::reference)
 | 
			
		||||
   type_test(const int&, boost::call_traits<cr_type>::const_reference)
 | 
			
		||||
   type_test(int&, boost::call_traits<cr_type>::param_type)
 | 
			
		||||
#else
 | 
			
		||||
   std::cout << "Your compiler cannot instantiate call_traits<int&const>, skipping four tests (4 errors)" << std::endl;
 | 
			
		||||
   failures += 4;
 | 
			
		||||
   test_count += 4;
 | 
			
		||||
#endif
 | 
			
		||||
   type_test(const int&, boost::call_traits<const int&>::value_type)
 | 
			
		||||
   type_test(const int&, boost::call_traits<const int&>::reference)
 | 
			
		||||
   type_test(const int&, boost::call_traits<const int&>::const_reference)
 | 
			
		||||
   type_test(const int&, boost::call_traits<const int&>::param_type)
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
   type_test(const int*, boost::call_traits<int[3]>::value_type)
 | 
			
		||||
   type_test(int(&)[3], boost::call_traits<int[3]>::reference)
 | 
			
		||||
   type_test(const int(&)[3], boost::call_traits<int[3]>::const_reference)
 | 
			
		||||
   type_test(const int*const, boost::call_traits<int[3]>::param_type)
 | 
			
		||||
   type_test(const int*, boost::call_traits<const int[3]>::value_type)
 | 
			
		||||
   type_test(const int(&)[3], boost::call_traits<const int[3]>::reference)
 | 
			
		||||
   type_test(const int(&)[3], boost::call_traits<const int[3]>::const_reference)
 | 
			
		||||
   type_test(const int*const, boost::call_traits<const int[3]>::param_type)
 | 
			
		||||
   // test with abstract base class:
 | 
			
		||||
   type_test(test_abc1, boost::call_traits<test_abc1>::value_type)
 | 
			
		||||
   type_test(test_abc1&, boost::call_traits<test_abc1>::reference)
 | 
			
		||||
   type_test(const test_abc1&, boost::call_traits<test_abc1>::const_reference)
 | 
			
		||||
   type_test(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:
 | 
			
		||||
   type_test(incomplete_type, boost::call_traits<incomplete_type>::value_type)
 | 
			
		||||
   type_test(incomplete_type&, boost::call_traits<incomplete_type>::reference)
 | 
			
		||||
   type_test(const incomplete_type&, boost::call_traits<incomplete_type>::const_reference)
 | 
			
		||||
   type_test(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 = 14;
 | 
			
		||||
#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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										124
									
								
								checked_delete.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								checked_delete.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
			
		||||
<!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="../../c++boost.gif" alt="c++boost.gif (8819 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>
 | 
			
		||||
							
								
								
									
										27
									
								
								checked_delete_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								checked_delete_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
//  Boost checked_delete test program  ---------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  Copyright Beman Dawes 2001.
 | 
			
		||||
//  See accompanying license for terms and conditions of use.
 | 
			
		||||
 | 
			
		||||
//  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
 | 
			
		||||
							
								
								
									
										98
									
								
								compressed_pair.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								compressed_pair.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,98 @@
 | 
			
		||||
<html>
 | 
			
		||||
 | 
			
		||||
<head>
 | 
			
		||||
<meta http-equiv="Content-Type"
 | 
			
		||||
content="text/html; charset=iso-8859-1">
 | 
			
		||||
<meta name="Template"
 | 
			
		||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
 | 
			
		||||
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
 | 
			
		||||
<title>Header </title>
 | 
			
		||||
<boost/compressed_pair.hpp>
 | 
			
		||||
</head>
 | 
			
		||||
 | 
			
		||||
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF"
 | 
			
		||||
vlink="#800080">
 | 
			
		||||
 | 
			
		||||
<h2><img src="../../c++boost.gif" width="276" height="86">Header
 | 
			
		||||
<<a href="../../boost/detail/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 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>
 | 
			
		||||
							
								
								
									
										401
									
								
								compressed_pair_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										401
									
								
								compressed_pair_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,401 @@
 | 
			
		||||
//  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/type_traits/type_traits_test.hpp>
 | 
			
		||||
#define BOOST_INCLUDE_MAIN
 | 
			
		||||
#include <boost/test/test_tools.hpp>
 | 
			
		||||
 | 
			
		||||
using namespace boost;
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
 | 
			
		||||
template <> struct is_empty<empty_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct is_empty<empty_POD_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
template <> struct is_POD<empty_POD_UDT>
 | 
			
		||||
{ static const bool value = true; };
 | 
			
		||||
#else
 | 
			
		||||
template <> struct is_empty<empty_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct is_empty<empty_POD_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
template <> struct is_POD<empty_POD_UDT>
 | 
			
		||||
{ enum{ value = true }; };
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct non_empty1
 | 
			
		||||
{ 
 | 
			
		||||
   int i;
 | 
			
		||||
   non_empty1() : i(1){}
 | 
			
		||||
   non_empty1(int v) : i(v){}
 | 
			
		||||
   friend bool operator==(const non_empty1& a, const non_empty1& b)
 | 
			
		||||
   { return a.i == b.i; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct non_empty2
 | 
			
		||||
{ 
 | 
			
		||||
   int i;
 | 
			
		||||
   non_empty2() : i(3){}
 | 
			
		||||
   non_empty2(int v) : i(v){}
 | 
			
		||||
   friend bool operator==(const non_empty2& a, const non_empty2& b)
 | 
			
		||||
   { return a.i == b.i; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#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_TEST(cp2.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp2.second() == p2);
 | 
			
		||||
   // second param construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp3(p2);
 | 
			
		||||
   cp3.first() = p1;
 | 
			
		||||
   BOOST_TEST(cp3.second() == p2);
 | 
			
		||||
   BOOST_TEST(cp3.first() == p1);
 | 
			
		||||
   // both param construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp4(p1, p2);
 | 
			
		||||
   BOOST_TEST(cp4.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp4.second() == p2);
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp5(p3, p4);
 | 
			
		||||
   BOOST_TEST(cp5.first() == p3);
 | 
			
		||||
   BOOST_TEST(cp5.second() == p4);
 | 
			
		||||
   // check const members:
 | 
			
		||||
   const boost::compressed_pair<T1,T2>& cpr1 = cp4;
 | 
			
		||||
   BOOST_TEST(cpr1.first() == p1);
 | 
			
		||||
   BOOST_TEST(cpr1.second() == p2);
 | 
			
		||||
 | 
			
		||||
   // copy construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp6(cp4);
 | 
			
		||||
   BOOST_TEST(cp6.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp6.second() == p2);
 | 
			
		||||
   // assignment:
 | 
			
		||||
   cp1 = cp4;
 | 
			
		||||
   BOOST_TEST(cp1.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp1.second() == p2);
 | 
			
		||||
   cp1 = cp5;
 | 
			
		||||
   BOOST_TEST(cp1.first() == p3);
 | 
			
		||||
   BOOST_TEST(cp1.second() == p4);
 | 
			
		||||
   // swap:
 | 
			
		||||
   cp4.swap(cp5);
 | 
			
		||||
   BOOST_TEST(cp4.first() == p3);
 | 
			
		||||
   BOOST_TEST(cp4.second() == p4);
 | 
			
		||||
   BOOST_TEST(cp5.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp5.second() == p2);
 | 
			
		||||
   swap(cp4,cp5);
 | 
			
		||||
   BOOST_TEST(cp4.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp4.second() == p2);
 | 
			
		||||
   BOOST_TEST(cp5.first() == p3);
 | 
			
		||||
   BOOST_TEST(cp5.second() == p4);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// tests for case where one or both 
 | 
			
		||||
// parameters are reference types:
 | 
			
		||||
//
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
struct compressed_pair_reference_tester
 | 
			
		||||
{
 | 
			
		||||
   // define the types we need:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   // define our test proc:
 | 
			
		||||
   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_reference_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
 | 
			
		||||
{
 | 
			
		||||
#ifndef __GNUC__
 | 
			
		||||
   // gcc 2.90 can't cope with function scope using
 | 
			
		||||
   // declarations, and generates an internal compiler error...
 | 
			
		||||
   using std::swap;
 | 
			
		||||
#endif
 | 
			
		||||
   // both param construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp4(p1, p2);
 | 
			
		||||
   BOOST_TEST(cp4.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp4.second() == p2);
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp5(p3, p4);
 | 
			
		||||
   BOOST_TEST(cp5.first() == p3);
 | 
			
		||||
   BOOST_TEST(cp5.second() == p4);
 | 
			
		||||
   // check const members:
 | 
			
		||||
   const boost::compressed_pair<T1,T2>& cpr1 = cp4;
 | 
			
		||||
   BOOST_TEST(cpr1.first() == p1);
 | 
			
		||||
   BOOST_TEST(cpr1.second() == p2);
 | 
			
		||||
 | 
			
		||||
   // copy construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp6(cp4);
 | 
			
		||||
   BOOST_TEST(cp6.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp6.second() == p2);
 | 
			
		||||
   // assignment:
 | 
			
		||||
   // VC6 bug:
 | 
			
		||||
   // When second() is an empty class, VC6 performs the
 | 
			
		||||
   // assignment by doing a memcpy - even though the empty
 | 
			
		||||
   // class is really a zero sized base class, the result
 | 
			
		||||
   // is that the memory of first() gets trampled over.
 | 
			
		||||
   // Similar arguments apply to the case that first() is 
 | 
			
		||||
   // an empty base class.
 | 
			
		||||
   // Strangely the problem is dependent upon the compiler
 | 
			
		||||
   // settings - some generate the problem others do not.
 | 
			
		||||
   cp4.first() = p3;
 | 
			
		||||
   cp4.second() = p4;
 | 
			
		||||
   BOOST_TEST(cp4.first() == p3);
 | 
			
		||||
   BOOST_TEST(cp4.second() == p4);
 | 
			
		||||
}
 | 
			
		||||
//
 | 
			
		||||
// supplimentary tests for case where first arg only is a reference type:
 | 
			
		||||
//
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
struct compressed_pair_reference1_tester
 | 
			
		||||
{
 | 
			
		||||
   // define the types we need:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   // define our test proc:
 | 
			
		||||
   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_reference1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
 | 
			
		||||
{
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
   // first param construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp2(p1);
 | 
			
		||||
   cp2.second() = p2;
 | 
			
		||||
   BOOST_TEST(cp2.first() == p1);
 | 
			
		||||
   BOOST_TEST(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_TEST(cp3.second() == p2);
 | 
			
		||||
   BOOST_TEST(cp3.first() == p1);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// tests for where one or the other parameter is an array:
 | 
			
		||||
//
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
struct compressed_pair_array1_tester
 | 
			
		||||
{
 | 
			
		||||
   // define the types we need:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   // define our test proc:
 | 
			
		||||
   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_array1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, 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_TEST(cp3.second() == p2);
 | 
			
		||||
   BOOST_TEST(cp3.first()[0] == p1[0]);
 | 
			
		||||
   // check const members:
 | 
			
		||||
   const boost::compressed_pair<T1,T2>& cpr1 = cp3;
 | 
			
		||||
   BOOST_TEST(cpr1.first()[0] == p1[0]);
 | 
			
		||||
   BOOST_TEST(cpr1.second() == p2);
 | 
			
		||||
 | 
			
		||||
   BOOST_TEST(sizeof(T1) == sizeof(cp1.first()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
struct compressed_pair_array2_tester
 | 
			
		||||
{
 | 
			
		||||
   // define the types we need:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   // define our test proc:
 | 
			
		||||
   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_array2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, 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_TEST(cp2.first() == p1);
 | 
			
		||||
   BOOST_TEST(cp2.second()[0] == p2[0]);
 | 
			
		||||
   // check const members:
 | 
			
		||||
   const boost::compressed_pair<T1,T2>& cpr1 = cp2;
 | 
			
		||||
   BOOST_TEST(cpr1.first() == p1);
 | 
			
		||||
   BOOST_TEST(cpr1.second()[0] == p2[0]);
 | 
			
		||||
 | 
			
		||||
   BOOST_TEST(sizeof(T2) == sizeof(cp1.second()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
struct compressed_pair_array_tester
 | 
			
		||||
{
 | 
			
		||||
   // define the types we need:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   // define our test proc:
 | 
			
		||||
   static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type)
 | 
			
		||||
{
 | 
			
		||||
   // default construct:
 | 
			
		||||
   boost::compressed_pair<T1,T2> cp1;
 | 
			
		||||
   cp1.first()[0] = p1[0];
 | 
			
		||||
   cp1.second()[0] = p2[0];
 | 
			
		||||
   BOOST_TEST(cp1.first()[0] == p1[0]);
 | 
			
		||||
   BOOST_TEST(cp1.second()[0] == p2[0]);
 | 
			
		||||
   // check const members:
 | 
			
		||||
   const boost::compressed_pair<T1,T2>& cpr1 = cp1;
 | 
			
		||||
   BOOST_TEST(cpr1.first()[0] == p1[0]);
 | 
			
		||||
   BOOST_TEST(cpr1.second()[0] == p2[0]);
 | 
			
		||||
 | 
			
		||||
   BOOST_TEST(sizeof(T1) == sizeof(cp1.first()));
 | 
			
		||||
   BOOST_TEST(sizeof(T2) == sizeof(cp1.second()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int test_main(int, 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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										60
									
								
								counting_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								counting_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <boost/iterator/counting_iterator.hpp>
 | 
			
		||||
#include <boost/iterator/indirect_iterator.hpp>
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  // Example of using counting_iterator_generator
 | 
			
		||||
  std::cout << "counting from 0 to 4:" << std::endl;
 | 
			
		||||
  boost::counting_iterator<int> first(0), last(4);
 | 
			
		||||
  std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Example of using make_counting_iterator()
 | 
			
		||||
  std::cout << "counting from -5 to 4:" << std::endl;
 | 
			
		||||
  std::copy(boost::make_counting_iterator(-5),
 | 
			
		||||
            boost::make_counting_iterator(5),
 | 
			
		||||
            std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Example of using counting iterator to create an array of pointers.
 | 
			
		||||
#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
 | 
			
		||||
  const
 | 
			
		||||
#endif 
 | 
			
		||||
      int N = 7;
 | 
			
		||||
  std::vector<int> numbers;
 | 
			
		||||
  // Fill "numbers" array with [0,N)
 | 
			
		||||
  std::copy(
 | 
			
		||||
      boost::make_counting_iterator(0)
 | 
			
		||||
      , boost::make_counting_iterator(N)
 | 
			
		||||
      , std::back_inserter(numbers));
 | 
			
		||||
 | 
			
		||||
  std::vector<std::vector<int>::iterator> pointers;
 | 
			
		||||
 | 
			
		||||
  // Use counting iterator to fill in the array of pointers.
 | 
			
		||||
  // causes an ICE with MSVC6
 | 
			
		||||
  std::copy(boost::make_counting_iterator(numbers.begin()),
 | 
			
		||||
            boost::make_counting_iterator(numbers.end()),
 | 
			
		||||
            std::back_inserter(pointers));
 | 
			
		||||
 | 
			
		||||
  // Use indirect iterator to print out numbers by accessing
 | 
			
		||||
  // them through the array of pointers.
 | 
			
		||||
  std::cout << "indirectly printing out the numbers from 0 to " 
 | 
			
		||||
            << N << std::endl;
 | 
			
		||||
  std::copy(boost::make_indirect_iterator(pointers.begin()),
 | 
			
		||||
            boost::make_indirect_iterator(pointers.end()),
 | 
			
		||||
            std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								current_function.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								current_function.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<!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="../../c++boost.gif" alt="c++boost.gif (8819 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>
 | 
			
		||||
							
								
								
									
										34
									
								
								current_function_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								current_function_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
#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.
 | 
			
		||||
//
 | 
			
		||||
//  Permission to copy, use, modify, sell and distribute this software
 | 
			
		||||
//  is granted provided this copyright notice appears in all copies.
 | 
			
		||||
//  This software is provided "as is" without express or implied
 | 
			
		||||
//  warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#include <boost/current_function.hpp>
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
 | 
			
		||||
void message(char const * file, long line, char const * func, char const * msg)
 | 
			
		||||
{
 | 
			
		||||
    std::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");
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										388
									
								
								enable_if.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										388
									
								
								enable_if.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,388 @@
 | 
			
		||||
<!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="../../c++boost.gif" 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="http://www.boost.org/libs/type_traits">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 <class T> 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>
 | 
			
		||||
							
								
								
									
										62
									
								
								enable_if_constructors.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								enable_if_constructors.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
// 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										46
									
								
								enable_if_dummy_arg_disambiguation.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								enable_if_dummy_arg_disambiguation.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
// 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										82
									
								
								enable_if_lazy.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								enable_if_lazy.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
// 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										100
									
								
								enable_if_lazy_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								enable_if_lazy_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,100 @@
 | 
			
		||||
// 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										43
									
								
								enable_if_member_templates.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								enable_if_member_templates.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
// 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										47
									
								
								enable_if_namespace_disambiguation.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								enable_if_namespace_disambiguation.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
// 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										43
									
								
								enable_if_no_disambiguation.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								enable_if_no_disambiguation.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
// 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										67
									
								
								enable_if_partial_specializations.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								enable_if_partial_specializations.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
// 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										62
									
								
								filter_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								filter_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
// Example of using the filter iterator adaptor from
 | 
			
		||||
// boost/iterator_adaptors.hpp.
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <boost/iterator/filter_iterator.hpp>
 | 
			
		||||
 | 
			
		||||
struct is_positive_number {
 | 
			
		||||
  bool operator()(int x) { return 0 < x; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
  int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 };
 | 
			
		||||
  const int N = sizeof(numbers_)/sizeof(int);
 | 
			
		||||
  
 | 
			
		||||
  typedef int* base_iterator;
 | 
			
		||||
  base_iterator numbers(numbers_);
 | 
			
		||||
  
 | 
			
		||||
  // Example using make_filter_iterator()
 | 
			
		||||
  std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
 | 
			
		||||
            boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
 | 
			
		||||
            std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Example using filter_iterator
 | 
			
		||||
  typedef boost::filter_iterator<is_positive_number, base_iterator>
 | 
			
		||||
    FilterIter;
 | 
			
		||||
  
 | 
			
		||||
  is_positive_number predicate;
 | 
			
		||||
  FilterIter filter_iter_first(predicate, numbers, numbers + N);
 | 
			
		||||
  FilterIter filter_iter_last(predicate, numbers + N, numbers + N);
 | 
			
		||||
 | 
			
		||||
  std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Another example using make_filter_iterator()
 | 
			
		||||
  std::copy(
 | 
			
		||||
      boost::make_filter_iterator(
 | 
			
		||||
          std::bind2nd(std::greater<int>(), -2)
 | 
			
		||||
        , numbers, numbers + N)
 | 
			
		||||
            
 | 
			
		||||
    , boost::make_filter_iterator(
 | 
			
		||||
          std::bind2nd(std::greater<int>(), -2)
 | 
			
		||||
        , numbers + N, numbers + N)
 | 
			
		||||
      
 | 
			
		||||
    , std::ostream_iterator<int>(std::cout, " ")
 | 
			
		||||
  );
 | 
			
		||||
  
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								fun_out_iter_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								fun_out_iter_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2001. Permission to copy, use, modify,
 | 
			
		||||
// sell and distribute this software is granted provided this
 | 
			
		||||
// copyright notice appears in all copies. This software is provided
 | 
			
		||||
// "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
// to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
// Revision History:
 | 
			
		||||
 | 
			
		||||
// 27 Feb 2001   Jeremy Siek
 | 
			
		||||
//      Initial checkin.
 | 
			
		||||
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include <boost/function_output_iterator.hpp>
 | 
			
		||||
 | 
			
		||||
struct string_appender
 | 
			
		||||
{
 | 
			
		||||
    string_appender(std::string& s)
 | 
			
		||||
        : m_str(&s)
 | 
			
		||||
    {}
 | 
			
		||||
    
 | 
			
		||||
    void operator()(const std::string& x) const
 | 
			
		||||
    {
 | 
			
		||||
        *m_str += x;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string* m_str;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  std::vector<std::string> x;
 | 
			
		||||
  x.push_back("hello");
 | 
			
		||||
  x.push_back(" ");
 | 
			
		||||
  x.push_back("world");
 | 
			
		||||
  x.push_back("!");
 | 
			
		||||
 | 
			
		||||
  std::string s = "";
 | 
			
		||||
  std::copy(x.begin(), x.end(), 
 | 
			
		||||
            boost::make_function_output_iterator(string_appender(s)));
 | 
			
		||||
  
 | 
			
		||||
  std::cout << s << std::endl;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										150
									
								
								generator_iterator.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								generator_iterator.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,150 @@
 | 
			
		||||
<!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="../../c++boost.gif" alt="c++boost.gif (8819 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 <a href="iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...> 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>
 | 
			
		||||
							
								
								
									
										366
									
								
								half_open_range_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										366
									
								
								half_open_range_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,366 @@
 | 
			
		||||
// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears in
 | 
			
		||||
// all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
//
 | 
			
		||||
// Revision History
 | 
			
		||||
// 11 Feb 2001  Compile with Borland, re-enable failing tests (David Abrahams)
 | 
			
		||||
// 29 Jan 2001  Initial revision (David Abrahams)
 | 
			
		||||
 | 
			
		||||
#include <boost/half_open_range.hpp>
 | 
			
		||||
#include <boost/utility.hpp>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <stdexcept>
 | 
			
		||||
#ifndef BOOST_NO_LIMITS
 | 
			
		||||
# include <limits>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_NO_SLIST
 | 
			
		||||
# include <slist>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
inline unsigned unsigned_random(unsigned max)
 | 
			
		||||
{
 | 
			
		||||
    return (max > 0) ? (unsigned)rand() % max : 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Special tests for ranges supporting random access
 | 
			
		||||
template <class T>
 | 
			
		||||
void category_test_1(
 | 
			
		||||
    const boost::half_open_range<T>& r, std::random_access_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
    typedef boost::half_open_range<T> range;
 | 
			
		||||
    typedef typename range::size_type size_type;
 | 
			
		||||
    size_type size = r.size();
 | 
			
		||||
 | 
			
		||||
    // pick a random offset
 | 
			
		||||
    size_type offset = unsigned_random(size);
 | 
			
		||||
 | 
			
		||||
    typename range::value_type x = *(r.begin() + offset);
 | 
			
		||||
    // test contains(value_type)
 | 
			
		||||
    assert(r.contains(r.start()) == !r.empty());
 | 
			
		||||
    assert(!r.contains(r.finish()));
 | 
			
		||||
    assert(r.contains(x) == (offset != size));
 | 
			
		||||
 | 
			
		||||
    range::const_iterator p = r.find(x);
 | 
			
		||||
    assert((p == r.end()) == (x == r.finish()));
 | 
			
		||||
    assert(r.find(r.finish()) == r.end());
 | 
			
		||||
 | 
			
		||||
    if (offset != size)
 | 
			
		||||
    {
 | 
			
		||||
        assert(x == r[offset]);
 | 
			
		||||
        assert(x == r.at(offset));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool caught_out_of_range = false;
 | 
			
		||||
    try {
 | 
			
		||||
        bool never_initialized = x == r.at(size);
 | 
			
		||||
        (void)never_initialized;
 | 
			
		||||
    }
 | 
			
		||||
    catch(std::out_of_range&)
 | 
			
		||||
    {
 | 
			
		||||
        caught_out_of_range = true;
 | 
			
		||||
    }
 | 
			
		||||
    catch(...)
 | 
			
		||||
    {
 | 
			
		||||
    }
 | 
			
		||||
    assert(caught_out_of_range);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Those tests must be skipped for other ranges
 | 
			
		||||
template <class T>
 | 
			
		||||
void category_test_1(
 | 
			
		||||
    const boost::half_open_range<T>&, std::forward_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned indices[][2] = { {0,0},{0,1},{0,2},{0,3},
 | 
			
		||||
                                {1,1},{1,2},{1,3},
 | 
			
		||||
                                      {2,2},{2,3},
 | 
			
		||||
                                            {3,3}};
 | 
			
		||||
 | 
			
		||||
template <class Range>
 | 
			
		||||
void category_test_2(
 | 
			
		||||
    const std::vector<Range>& ranges, unsigned i, unsigned j, std::random_access_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
    typedef Range range;
 | 
			
		||||
    const range& ri = ranges[i];
 | 
			
		||||
    const range& rj = ranges[j];
 | 
			
		||||
 | 
			
		||||
    if (indices[i][0] <= indices[j][0] && indices[i][1] >= indices[j][1])
 | 
			
		||||
        assert(ri.contains(rj));
 | 
			
		||||
 | 
			
		||||
    if (ri.contains(rj))
 | 
			
		||||
        assert((ri & rj) == rj);
 | 
			
		||||
    assert(boost::intersects(ri, rj) == !(ri & rj).empty());
 | 
			
		||||
 | 
			
		||||
    range t1(ri);
 | 
			
		||||
    t1 &= rj;
 | 
			
		||||
    assert(t1 == range(indices[i][0] > indices[j][0] ? ri.start() : rj.start(),
 | 
			
		||||
                       indices[i][1] < indices[j][1] ? ri.finish() : rj.finish()));
 | 
			
		||||
    assert(t1 == (ri & rj));
 | 
			
		||||
    
 | 
			
		||||
    range t2(ri);
 | 
			
		||||
    t2 |= rj;
 | 
			
		||||
    
 | 
			
		||||
    if (ri.empty())
 | 
			
		||||
        assert(t2 == rj);
 | 
			
		||||
    else if (rj.empty())
 | 
			
		||||
        assert(t2 == ri);
 | 
			
		||||
    else
 | 
			
		||||
        assert(t2 == range(indices[i][0] < indices[j][0] ? ri.start() : rj.start(),
 | 
			
		||||
                           indices[i][1] > indices[j][1] ? ri.finish() : rj.finish()));
 | 
			
		||||
    assert(t2 == (ri | rj));
 | 
			
		||||
    if (i == j)
 | 
			
		||||
        assert(ri == rj);
 | 
			
		||||
    
 | 
			
		||||
    if (ri.empty() || rj.empty())
 | 
			
		||||
        assert((ri == rj) == (ri.empty() && rj.empty()));
 | 
			
		||||
    else
 | 
			
		||||
        assert((ri == rj) == (ri.start() == rj.start() && ri.finish() == rj.finish()));
 | 
			
		||||
 | 
			
		||||
    assert((ri == rj) == !(ri != rj));
 | 
			
		||||
 | 
			
		||||
    bool same = ri == rj;
 | 
			
		||||
    bool one_empty = ri.empty() != rj.empty();
 | 
			
		||||
 | 
			
		||||
    std::less<range> less;
 | 
			
		||||
    std::less_equal<range> less_equal;
 | 
			
		||||
    std::greater<range> greater;
 | 
			
		||||
    std::greater_equal<range> greater_equal;
 | 
			
		||||
    
 | 
			
		||||
    if (same)
 | 
			
		||||
    {
 | 
			
		||||
        assert(greater_equal(ri,rj));
 | 
			
		||||
        assert(less_equal(ri,rj));
 | 
			
		||||
        assert(!greater(ri,rj));
 | 
			
		||||
        assert(!less(ri,rj));
 | 
			
		||||
    }
 | 
			
		||||
    else if (one_empty)
 | 
			
		||||
    {
 | 
			
		||||
        const range& empty = ri.empty() ? ri : rj;
 | 
			
		||||
        const range& non_empty = rj.empty() ? ri : rj;
 | 
			
		||||
        
 | 
			
		||||
        assert(less(empty,non_empty));
 | 
			
		||||
        assert(less_equal(empty,non_empty));
 | 
			
		||||
        assert(!greater(empty,non_empty));
 | 
			
		||||
        assert(!greater_equal(empty,non_empty));
 | 
			
		||||
        assert(!less(non_empty,empty));
 | 
			
		||||
        assert(!less_equal(non_empty,empty));
 | 
			
		||||
        assert(greater(non_empty,empty));
 | 
			
		||||
        assert(greater_equal(non_empty,empty));
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        if (indices[i][0] < indices[j][0] ||
 | 
			
		||||
            indices[i][0] == indices[j][0] && indices[i][1] < indices[j][1])
 | 
			
		||||
        {
 | 
			
		||||
            assert(!greater_equal(ri,rj));
 | 
			
		||||
            assert(less(ri,rj));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (indices[i][0] < indices[j][0] ||
 | 
			
		||||
            indices[i][0] == indices[j][0] && indices[i][1] <= indices[j][1])
 | 
			
		||||
        {
 | 
			
		||||
            assert(!greater(ri,rj));
 | 
			
		||||
            assert(less_equal(ri,rj));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (indices[i][0] > indices[j][0] ||
 | 
			
		||||
            indices[i][0] == indices[j][0] && indices[i][1] > indices[j][1])
 | 
			
		||||
        {
 | 
			
		||||
            assert(!less_equal(ri,rj));
 | 
			
		||||
            assert(greater(ri,rj));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (indices[i][0] > indices[j][0] ||
 | 
			
		||||
            indices[i][0] == indices[j][0] && indices[i][1] >= indices[j][1])
 | 
			
		||||
        {
 | 
			
		||||
            assert(!less(ri,rj));
 | 
			
		||||
            assert(greater_equal(ri,rj));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
template <class Range>
 | 
			
		||||
void category_test_2(
 | 
			
		||||
    const std::vector<Range>&, unsigned, unsigned, std::forward_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
void category_test_2(
 | 
			
		||||
    const std::vector<boost::half_open_range<T> >&, unsigned, unsigned, std::bidirectional_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Range>
 | 
			
		||||
void test_back(Range& x, std::bidirectional_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
    assert(x.back() == boost::prior(x.finish()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Range>
 | 
			
		||||
void test_back(Range& x, std::forward_iterator_tag)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
boost::half_open_range<T> range_identity(const boost::half_open_range<T>& x)
 | 
			
		||||
{
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
void test(T x0, T x1, T x2, T x3)
 | 
			
		||||
{
 | 
			
		||||
    std::vector<boost::half_open_range<T> > ranges;
 | 
			
		||||
    typedef boost::half_open_range<T> range;
 | 
			
		||||
 | 
			
		||||
    T bounds[4] = { x0, x1, x2, x3 };
 | 
			
		||||
 | 
			
		||||
    const std::size_t num_ranges = sizeof(indices)/sizeof(*indices);
 | 
			
		||||
    // test construction
 | 
			
		||||
    for (std::size_t n = 0; n < num_ranges;++n)
 | 
			
		||||
    {
 | 
			
		||||
        T start = bounds[indices[n][0]];
 | 
			
		||||
        T finish = bounds[indices[n][1]];
 | 
			
		||||
        boost::half_open_range<T> r(start, finish);
 | 
			
		||||
        ranges.push_back(r);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // test implicit conversion from std::pair<T,T>
 | 
			
		||||
    range converted = std::pair<T,T>(x0,x0);
 | 
			
		||||
    (void)converted;
 | 
			
		||||
 | 
			
		||||
    // test assignment, equality and inequality
 | 
			
		||||
    range r00 = range(x0, x0);
 | 
			
		||||
    assert(r00 == range(x0,x0));
 | 
			
		||||
    assert(r00 == range(x1,x1)); // empty ranges are all equal
 | 
			
		||||
    if (x3 != x0)
 | 
			
		||||
        assert(r00 != range(x0, x3));
 | 
			
		||||
    r00 = range(x0, x3);
 | 
			
		||||
    assert(r00 == range(x0, x3));
 | 
			
		||||
    if (x3 != x0)
 | 
			
		||||
        assert(r00 != range(x0, x0));
 | 
			
		||||
 | 
			
		||||
    typedef typename range::iterator iterator;
 | 
			
		||||
    typedef typename iterator::iterator_category category;
 | 
			
		||||
    
 | 
			
		||||
    for (unsigned i = 0; i < num_ranges; ++i)
 | 
			
		||||
    {
 | 
			
		||||
        const range& r = ranges[i];
 | 
			
		||||
            
 | 
			
		||||
        // test begin(), end(), basic iteration.
 | 
			
		||||
        unsigned count = 0;
 | 
			
		||||
        for (range::const_iterator p = r.begin(), finish = r.end();
 | 
			
		||||
             p != finish;
 | 
			
		||||
             ++p, ++count)
 | 
			
		||||
        {
 | 
			
		||||
            assert(count < 2100);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // test size(), empty(), front(), back()
 | 
			
		||||
        assert((unsigned)r.size() == count);
 | 
			
		||||
        if (indices[i][0] == indices[i][1])
 | 
			
		||||
            assert(r.empty());
 | 
			
		||||
        if (r.empty())
 | 
			
		||||
            assert(r.size() == 0);
 | 
			
		||||
        if (!r.empty())
 | 
			
		||||
        {
 | 
			
		||||
            assert(r.front() == r.start());
 | 
			
		||||
            test_back(r, category());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            // test swap
 | 
			
		||||
        range r1(r);
 | 
			
		||||
        range r2(x0,x3);
 | 
			
		||||
        const bool same = r1 == r2;
 | 
			
		||||
        r1.swap(r2);
 | 
			
		||||
        assert(r1 == range(x0,x3));
 | 
			
		||||
        assert(r2 == r);
 | 
			
		||||
        if (!same) {
 | 
			
		||||
            assert(r1 != r);
 | 
			
		||||
            assert(r2 != range(x0,x3));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // do individual tests for random-access iterators
 | 
			
		||||
        category_test_1(r, category());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (unsigned j = 0; j < num_ranges; ++j) {
 | 
			
		||||
        for (unsigned k = 0; k < num_ranges; ++k) {
 | 
			
		||||
            category_test_2(ranges, j, k, category());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Integer>
 | 
			
		||||
void test_integer(Integer* = 0) // default arg works around MSVC bug
 | 
			
		||||
{
 | 
			
		||||
    Integer a = 0;
 | 
			
		||||
    Integer b = a + unsigned_random(128 - a);
 | 
			
		||||
    Integer c = b + unsigned_random(128 - b);
 | 
			
		||||
    Integer d = c + unsigned_random(128 - c);
 | 
			
		||||
 | 
			
		||||
    test(a, b, c, d);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class Container>
 | 
			
		||||
void test_container(Container* = 0)  // default arg works around MSVC bug
 | 
			
		||||
{
 | 
			
		||||
    Container c(unsigned_random(1673));
 | 
			
		||||
 | 
			
		||||
    const typename Container::size_type offset1 = unsigned_random(c.size());
 | 
			
		||||
    const typename Container::size_type offset2 = unsigned_random(c.size() - offset1);
 | 
			
		||||
    typename Container::iterator internal1 = c.begin();
 | 
			
		||||
    std::advance(internal1, offset1);
 | 
			
		||||
    typename Container::iterator internal2 = internal1;
 | 
			
		||||
    std::advance(internal2, offset2);
 | 
			
		||||
    
 | 
			
		||||
    test(c.begin(), internal1, internal2, c.end());
 | 
			
		||||
 | 
			
		||||
    typedef typename Container::const_iterator const_iterator;
 | 
			
		||||
    test(const_iterator(c.begin()),
 | 
			
		||||
         const_iterator(internal1),
 | 
			
		||||
         const_iterator(internal2),
 | 
			
		||||
         const_iterator(c.end()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    // Test the built-in integer types.
 | 
			
		||||
    test_integer<char>();
 | 
			
		||||
    test_integer<unsigned char>();
 | 
			
		||||
    test_integer<signed char>();
 | 
			
		||||
    test_integer<wchar_t>();
 | 
			
		||||
    test_integer<short>();
 | 
			
		||||
    test_integer<unsigned short>();
 | 
			
		||||
    test_integer<int>();
 | 
			
		||||
    test_integer<unsigned int>();
 | 
			
		||||
    test_integer<long>();
 | 
			
		||||
    test_integer<unsigned long>();
 | 
			
		||||
#if defined(BOOST_HAS_LONG_LONG)
 | 
			
		||||
    test_integer<long long>();
 | 
			
		||||
    test_integer<unsigned long long>();
 | 
			
		||||
#endif
 | 
			
		||||
    // Some tests on container iterators, to prove we handle a few different categories
 | 
			
		||||
    test_container<std::vector<int> >();
 | 
			
		||||
    test_container<std::list<int> >();
 | 
			
		||||
#ifndef BOOST_NO_SLIST
 | 
			
		||||
    test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
 | 
			
		||||
#endif
 | 
			
		||||
    // Also prove that we can handle raw pointers.
 | 
			
		||||
    int array[2000];
 | 
			
		||||
    const std::size_t a = 0;
 | 
			
		||||
    const std::size_t b = a + unsigned_random(2000 - a);
 | 
			
		||||
    const std::size_t c = b + unsigned_random(2000 - b);
 | 
			
		||||
    test(array, array+b, array+c, array+2000);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								include/boost/assert.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								include/boost/assert.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
//
 | 
			
		||||
//  boost/assert.hpp - BOOST_ASSERT(expr)
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//
 | 
			
		||||
//  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.
 | 
			
		||||
//
 | 
			
		||||
//  Note: There are no include guards. This is intentional.
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/utility/assert.html for documentation.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
#undef BOOST_ASSERT
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_DISABLE_ASSERTS)
 | 
			
		||||
 | 
			
		||||
# define BOOST_ASSERT(expr) ((void)0)
 | 
			
		||||
 | 
			
		||||
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
 | 
			
		||||
 | 
			
		||||
#include <boost/current_function.hpp>
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
# include <assert.h>
 | 
			
		||||
# define BOOST_ASSERT(expr) assert(expr)
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										24
									
								
								include/boost/call_traits.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								include/boost/call_traits.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
//  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & 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).
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/utility for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp
 | 
			
		||||
//  for full copyright notices.
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_CALL_TRAITS_HPP
 | 
			
		||||
#define BOOST_CALL_TRAITS_HPP
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_CONFIG_HPP
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
#include <boost/detail/ob_call_traits.hpp>
 | 
			
		||||
#else
 | 
			
		||||
#include <boost/detail/call_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_CALL_TRAITS_HPP
 | 
			
		||||
							
								
								
									
										71
									
								
								include/boost/checked_delete.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								include/boost/checked_delete.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
 | 
			
		||||
#define BOOST_CHECKED_DELETE_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
// MS compatible compilers support #pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 | 
			
		||||
# pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  boost/checked_delete.hpp
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 1999, 2000, 2001, 2002 boost.org
 | 
			
		||||
//  Copyright (c) 2002, 2003 Peter Dimov
 | 
			
		||||
//  Copyright (c) 2003 Daniel Frey
 | 
			
		||||
//  Copyright (c) 2003 Howard Hinnant
 | 
			
		||||
//
 | 
			
		||||
//  Permission to copy, use, modify, sell and distribute this software
 | 
			
		||||
//  is granted provided this copyright notice appears in all copies.
 | 
			
		||||
//  This software is provided "as is" without express or implied
 | 
			
		||||
//  warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/utility/checked_delete.html for documentation.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
// verify that types are complete for increased safety
 | 
			
		||||
 | 
			
		||||
template<class T> inline void checked_delete(T * x)
 | 
			
		||||
{
 | 
			
		||||
    // intentionally complex - simplification causes regressions
 | 
			
		||||
    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
 | 
			
		||||
    (void) sizeof(type_must_be_complete);
 | 
			
		||||
    delete x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline void checked_array_delete(T * x)
 | 
			
		||||
{
 | 
			
		||||
    typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
 | 
			
		||||
    (void) sizeof(type_must_be_complete);
 | 
			
		||||
    delete [] x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> struct checked_deleter
 | 
			
		||||
{
 | 
			
		||||
    typedef void result_type;
 | 
			
		||||
    typedef T * argument_type;
 | 
			
		||||
 | 
			
		||||
    void operator()(T * x) const
 | 
			
		||||
    {
 | 
			
		||||
        // boost:: disables ADL
 | 
			
		||||
        boost::checked_delete(x);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<class T> struct checked_array_deleter
 | 
			
		||||
{
 | 
			
		||||
    typedef void result_type;
 | 
			
		||||
    typedef T * argument_type;
 | 
			
		||||
 | 
			
		||||
    void operator()(T * x) const
 | 
			
		||||
    {
 | 
			
		||||
        boost::checked_array_delete(x);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif  // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
 | 
			
		||||
							
								
								
									
										24
									
								
								include/boost/compressed_pair.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								include/boost/compressed_pair.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,24 @@
 | 
			
		||||
//  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & 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).
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/utility for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp
 | 
			
		||||
//  for full copyright notices.
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_COMPRESSED_PAIR_HPP
 | 
			
		||||
#define BOOST_COMPRESSED_PAIR_HPP
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_CONFIG_HPP
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
#include <boost/detail/ob_compressed_pair.hpp>
 | 
			
		||||
#else
 | 
			
		||||
#include <boost/detail/compressed_pair.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_COMPRESSED_PAIR_HPP
 | 
			
		||||
							
								
								
									
										64
									
								
								include/boost/current_function.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								include/boost/current_function.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
			
		||||
#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
 | 
			
		||||
#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
// MS compatible compilers support #pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 | 
			
		||||
# pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  boost/current_function.hpp - BOOST_CURRENT_FUNCTION
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
 | 
			
		||||
//
 | 
			
		||||
//  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.
 | 
			
		||||
//
 | 
			
		||||
//  http://www.boost.org/libs/utility/current_function.html
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
inline void current_function_helper()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600))
 | 
			
		||||
 | 
			
		||||
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
 | 
			
		||||
 | 
			
		||||
#elif defined(__FUNCSIG__)
 | 
			
		||||
 | 
			
		||||
# define BOOST_CURRENT_FUNCTION __FUNCSIG__
 | 
			
		||||
 | 
			
		||||
#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
 | 
			
		||||
 | 
			
		||||
# define BOOST_CURRENT_FUNCTION __FUNCTION__
 | 
			
		||||
 | 
			
		||||
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
 | 
			
		||||
 | 
			
		||||
# define BOOST_CURRENT_FUNCTION __FUNC__
 | 
			
		||||
 | 
			
		||||
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
 | 
			
		||||
 | 
			
		||||
# define BOOST_CURRENT_FUNCTION __func__
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
# define BOOST_CURRENT_FUNCTION "(unknown)"
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace detail
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
 | 
			
		||||
							
								
								
									
										154
									
								
								include/boost/detail/call_traits.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								include/boost/detail/call_traits.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,154 @@
 | 
			
		||||
//  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & 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).
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/utility for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
// call_traits: defines typedefs for function usage
 | 
			
		||||
// (see libs/utility/call_traits.htm)
 | 
			
		||||
 | 
			
		||||
/* Release notes:
 | 
			
		||||
   23rd July 2000:
 | 
			
		||||
      Fixed array specialization. (JM)
 | 
			
		||||
      Added Borland specific fixes for reference types
 | 
			
		||||
      (issue raised by Steve Cleary).
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_DETAIL_CALL_TRAITS_HPP
 | 
			
		||||
#define BOOST_DETAIL_CALL_TRAITS_HPP
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_CONFIG_HPP
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
 | 
			
		||||
#include <boost/type_traits/is_arithmetic.hpp>
 | 
			
		||||
#include <boost/type_traits/is_pointer.hpp>
 | 
			
		||||
 | 
			
		||||
namespace boost{
 | 
			
		||||
 | 
			
		||||
namespace detail{
 | 
			
		||||
 | 
			
		||||
template <typename T, bool small_>
 | 
			
		||||
struct ct_imp2
 | 
			
		||||
{
 | 
			
		||||
   typedef const T& param_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct ct_imp2<T, true>
 | 
			
		||||
{
 | 
			
		||||
   typedef const T param_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T, bool isp, bool b1>
 | 
			
		||||
struct ct_imp
 | 
			
		||||
{
 | 
			
		||||
   typedef const T& param_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T, bool isp>
 | 
			
		||||
struct ct_imp<T, isp, true>
 | 
			
		||||
{
 | 
			
		||||
   typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T, bool b1>
 | 
			
		||||
struct ct_imp<T, true, b1>
 | 
			
		||||
{
 | 
			
		||||
   typedef T const param_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct call_traits
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
   typedef T value_type;
 | 
			
		||||
   typedef T& reference;
 | 
			
		||||
   typedef const T& const_reference;
 | 
			
		||||
   //
 | 
			
		||||
   // C++ Builder workaround: we should be able to define a compile time
 | 
			
		||||
   // constant and pass that as a single template parameter to ct_imp<T,bool>,
 | 
			
		||||
   // however compiler bugs prevent this - instead pass three bool's to
 | 
			
		||||
   // ct_imp<T,bool,bool,bool> and add an extra partial specialisation
 | 
			
		||||
   // of ct_imp to handle the logic. (JM)
 | 
			
		||||
   typedef typename detail::ct_imp<
 | 
			
		||||
      T,
 | 
			
		||||
      ::boost::is_pointer<T>::value,
 | 
			
		||||
      ::boost::is_arithmetic<T>::value
 | 
			
		||||
   >::param_type param_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct call_traits<T&>
 | 
			
		||||
{
 | 
			
		||||
   typedef T& value_type;
 | 
			
		||||
   typedef T& reference;
 | 
			
		||||
   typedef const T& const_reference;
 | 
			
		||||
   typedef T& param_type;  // hh removed const
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
 | 
			
		||||
// these are illegal specialisations; cv-qualifies applied to
 | 
			
		||||
// references have no effect according to [8.3.2p1],
 | 
			
		||||
// C++ Builder requires them though as it treats cv-qualified
 | 
			
		||||
// references as distinct types...
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct call_traits<T&const>
 | 
			
		||||
{
 | 
			
		||||
   typedef T& value_type;
 | 
			
		||||
   typedef T& reference;
 | 
			
		||||
   typedef const T& const_reference;
 | 
			
		||||
   typedef T& param_type;  // hh removed const
 | 
			
		||||
};
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct call_traits<T&volatile>
 | 
			
		||||
{
 | 
			
		||||
   typedef T& value_type;
 | 
			
		||||
   typedef T& reference;
 | 
			
		||||
   typedef const T& const_reference;
 | 
			
		||||
   typedef T& param_type;  // hh removed const
 | 
			
		||||
};
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct call_traits<T&const volatile>
 | 
			
		||||
{
 | 
			
		||||
   typedef T& value_type;
 | 
			
		||||
   typedef T& reference;
 | 
			
		||||
   typedef const T& const_reference;
 | 
			
		||||
   typedef T& param_type;  // hh removed const
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)
 | 
			
		||||
template <typename T, std::size_t N>
 | 
			
		||||
struct call_traits<T [N]>
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   typedef T array_type[N];
 | 
			
		||||
public:
 | 
			
		||||
   // degrades array to pointer:
 | 
			
		||||
   typedef const T* value_type;
 | 
			
		||||
   typedef array_type& reference;
 | 
			
		||||
   typedef const array_type& const_reference;
 | 
			
		||||
   typedef const T* const param_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T, std::size_t N>
 | 
			
		||||
struct call_traits<const T [N]>
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   typedef const T array_type[N];
 | 
			
		||||
public:
 | 
			
		||||
   // degrades array to pointer:
 | 
			
		||||
   typedef const T* value_type;
 | 
			
		||||
   typedef array_type& reference;
 | 
			
		||||
   typedef const array_type& const_reference;
 | 
			
		||||
   typedef const T* const param_type;
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_DETAIL_CALL_TRAITS_HPP
 | 
			
		||||
							
								
								
									
										434
									
								
								include/boost/detail/compressed_pair.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										434
									
								
								include/boost/detail/compressed_pair.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,434 @@
 | 
			
		||||
//  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & 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).
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/utility for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
// compressed_pair: pair that "compresses" empty members
 | 
			
		||||
// (see libs/utility/compressed_pair.htm)
 | 
			
		||||
//
 | 
			
		||||
// JM changes 25 Jan 2004:
 | 
			
		||||
// For the case where T1 == T2 and both are empty, then first() and second()
 | 
			
		||||
// should return different objects.
 | 
			
		||||
// JM changes 25 Jan 2000:
 | 
			
		||||
// Removed default arguments from compressed_pair_switch to get
 | 
			
		||||
// C++ Builder 4 to accept them
 | 
			
		||||
// rewriten swap to get gcc and C++ builder to compile.
 | 
			
		||||
// added partial specialisations for case T1 == T2 to avoid duplicate constructor defs.
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP
 | 
			
		||||
#define BOOST_DETAIL_COMPRESSED_PAIR_HPP
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
 | 
			
		||||
#include <boost/type_traits/remove_cv.hpp>
 | 
			
		||||
#include <boost/type_traits/is_empty.hpp>
 | 
			
		||||
#include <boost/type_traits/is_same.hpp>
 | 
			
		||||
#include <boost/call_traits.hpp>
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// compressed_pair
 | 
			
		||||
 | 
			
		||||
namespace details
 | 
			
		||||
{
 | 
			
		||||
   // JM altered 26 Jan 2000:
 | 
			
		||||
   template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
 | 
			
		||||
   struct compressed_pair_switch;
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct compressed_pair_switch<T1, T2, false, false, false>
 | 
			
		||||
      {static const int value = 0;};
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct compressed_pair_switch<T1, T2, false, true, true>
 | 
			
		||||
      {static const int value = 3;};
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct compressed_pair_switch<T1, T2, false, true, false>
 | 
			
		||||
      {static const int value = 1;};
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct compressed_pair_switch<T1, T2, false, false, true>
 | 
			
		||||
      {static const int value = 2;};
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct compressed_pair_switch<T1, T2, true, true, true>
 | 
			
		||||
      {static const int value = 4;};
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct compressed_pair_switch<T1, T2, true, false, false>
 | 
			
		||||
      {static const int value = 5;};
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2, int Version> class compressed_pair_imp;
 | 
			
		||||
 | 
			
		||||
#ifdef __GNUC__
 | 
			
		||||
   // workaround for GCC (JM):
 | 
			
		||||
   using std::swap;
 | 
			
		||||
#endif
 | 
			
		||||
   //
 | 
			
		||||
   // can't call unqualified swap from within classname::swap
 | 
			
		||||
   // as Koenig lookup rules will find only the classname::swap
 | 
			
		||||
   // member function not the global declaration, so use cp_swap
 | 
			
		||||
   // as a forwarding function (JM):
 | 
			
		||||
   template <typename T>
 | 
			
		||||
   inline void cp_swap(T& t1, T& t2)
 | 
			
		||||
   {
 | 
			
		||||
#ifndef __GNUC__
 | 
			
		||||
      using std::swap;
 | 
			
		||||
#endif
 | 
			
		||||
      swap(t1, t2);
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   // 0    derive from neither
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   class compressed_pair_imp<T1, T2, 0>
 | 
			
		||||
   {
 | 
			
		||||
   public:
 | 
			
		||||
      typedef T1                                                 first_type;
 | 
			
		||||
      typedef T2                                                 second_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
      typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
      typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp() {} 
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x, second_param_type y)
 | 
			
		||||
         : first_(x), second_(y) {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x)
 | 
			
		||||
         : first_(x) {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(second_param_type y)
 | 
			
		||||
         : second_(y) {}
 | 
			
		||||
 | 
			
		||||
      first_reference       first()       {return first_;}
 | 
			
		||||
      first_const_reference first() const {return first_;}
 | 
			
		||||
 | 
			
		||||
      second_reference       second()       {return second_;}
 | 
			
		||||
      second_const_reference second() const {return second_;}
 | 
			
		||||
 | 
			
		||||
      void swap(::boost::compressed_pair<T1, T2>& y)
 | 
			
		||||
      {
 | 
			
		||||
         cp_swap(first_, y.first());
 | 
			
		||||
         cp_swap(second_, y.second());
 | 
			
		||||
      }
 | 
			
		||||
   private:
 | 
			
		||||
      first_type first_;
 | 
			
		||||
      second_type second_;
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   // 1    derive from T1
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   class compressed_pair_imp<T1, T2, 1>
 | 
			
		||||
      : private T1
 | 
			
		||||
   {
 | 
			
		||||
   public:
 | 
			
		||||
      typedef T1                                                 first_type;
 | 
			
		||||
      typedef T2                                                 second_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
      typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
      typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp() {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x, second_param_type y)
 | 
			
		||||
         : first_type(x), second_(y) {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x)
 | 
			
		||||
         : first_type(x) {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(second_param_type y)
 | 
			
		||||
         : second_(y) {}
 | 
			
		||||
 | 
			
		||||
      first_reference       first()       {return *this;}
 | 
			
		||||
      first_const_reference first() const {return *this;}
 | 
			
		||||
 | 
			
		||||
      second_reference       second()       {return second_;}
 | 
			
		||||
      second_const_reference second() const {return second_;}
 | 
			
		||||
 | 
			
		||||
      void swap(::boost::compressed_pair<T1,T2>& y)
 | 
			
		||||
      {
 | 
			
		||||
         // no need to swap empty base class:
 | 
			
		||||
         cp_swap(second_, y.second());
 | 
			
		||||
      }
 | 
			
		||||
   private:
 | 
			
		||||
      second_type second_;
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   // 2    derive from T2
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   class compressed_pair_imp<T1, T2, 2>
 | 
			
		||||
      : private T2
 | 
			
		||||
   {
 | 
			
		||||
   public:
 | 
			
		||||
      typedef T1                                                 first_type;
 | 
			
		||||
      typedef T2                                                 second_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
      typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
      typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp() {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x, second_param_type y)
 | 
			
		||||
         : second_type(y), first_(x) {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x)
 | 
			
		||||
         : first_(x) {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(second_param_type y)
 | 
			
		||||
         : second_type(y) {}
 | 
			
		||||
 | 
			
		||||
      first_reference       first()       {return first_;}
 | 
			
		||||
      first_const_reference first() const {return first_;}
 | 
			
		||||
 | 
			
		||||
      second_reference       second()       {return *this;}
 | 
			
		||||
      second_const_reference second() const {return *this;}
 | 
			
		||||
 | 
			
		||||
      void swap(::boost::compressed_pair<T1,T2>& y)
 | 
			
		||||
      {
 | 
			
		||||
         // no need to swap empty base class:
 | 
			
		||||
         cp_swap(first_, y.first());
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
   private:
 | 
			
		||||
      first_type first_;
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   // 3    derive from T1 and T2
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   class compressed_pair_imp<T1, T2, 3>
 | 
			
		||||
      : private T1,
 | 
			
		||||
        private T2
 | 
			
		||||
   {
 | 
			
		||||
   public:
 | 
			
		||||
      typedef T1                                                 first_type;
 | 
			
		||||
      typedef T2                                                 second_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
      typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
      typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp() {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x, second_param_type y)
 | 
			
		||||
         : first_type(x), second_type(y) {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x)
 | 
			
		||||
         : first_type(x) {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(second_param_type y)
 | 
			
		||||
         : second_type(y) {}
 | 
			
		||||
 | 
			
		||||
      first_reference       first()       {return *this;}
 | 
			
		||||
      first_const_reference first() const {return *this;}
 | 
			
		||||
 | 
			
		||||
      second_reference       second()       {return *this;}
 | 
			
		||||
      second_const_reference second() const {return *this;}
 | 
			
		||||
      //
 | 
			
		||||
      // no need to swap empty bases:
 | 
			
		||||
      void swap(::boost::compressed_pair<T1,T2>&) {}
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   // JM
 | 
			
		||||
   // 4    T1 == T2, T1 and T2 both empty
 | 
			
		||||
   //      Note does not actually store an instance of T2 at all -
 | 
			
		||||
   //      but reuses T1 base class for both first() and second().
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   class compressed_pair_imp<T1, T2, 4>
 | 
			
		||||
      : private T1
 | 
			
		||||
   {
 | 
			
		||||
   public:
 | 
			
		||||
      typedef T1                                                 first_type;
 | 
			
		||||
      typedef T2                                                 second_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
      typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
      typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp() {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x, second_param_type y)
 | 
			
		||||
         : first_type(x), m_second(y) {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x)
 | 
			
		||||
         : first_type(x), m_second(x) {}
 | 
			
		||||
 | 
			
		||||
      first_reference       first()       {return *this;}
 | 
			
		||||
      first_const_reference first() const {return *this;}
 | 
			
		||||
 | 
			
		||||
      second_reference       second()       {return m_second;}
 | 
			
		||||
      second_const_reference second() const {return m_second;}
 | 
			
		||||
 | 
			
		||||
      void swap(::boost::compressed_pair<T1,T2>&) {}
 | 
			
		||||
   private:
 | 
			
		||||
      T2 m_second;
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
   // 5    T1 == T2 and are not empty:   //JM
 | 
			
		||||
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   class compressed_pair_imp<T1, T2, 5>
 | 
			
		||||
   {
 | 
			
		||||
   public:
 | 
			
		||||
      typedef T1                                                 first_type;
 | 
			
		||||
      typedef T2                                                 second_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
      typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
      typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
      typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
      typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp() {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x, second_param_type y)
 | 
			
		||||
         : first_(x), second_(y) {}
 | 
			
		||||
 | 
			
		||||
      compressed_pair_imp(first_param_type x)
 | 
			
		||||
         : first_(x), second_(x) {}
 | 
			
		||||
 | 
			
		||||
      first_reference       first()       {return first_;}
 | 
			
		||||
      first_const_reference first() const {return first_;}
 | 
			
		||||
 | 
			
		||||
      second_reference       second()       {return second_;}
 | 
			
		||||
      second_const_reference second() const {return second_;}
 | 
			
		||||
 | 
			
		||||
      void swap(::boost::compressed_pair<T1, T2>& y)
 | 
			
		||||
      {
 | 
			
		||||
         cp_swap(first_, y.first());
 | 
			
		||||
         cp_swap(second_, y.second());
 | 
			
		||||
      }
 | 
			
		||||
   private:
 | 
			
		||||
      first_type first_;
 | 
			
		||||
      second_type second_;
 | 
			
		||||
   };
 | 
			
		||||
 | 
			
		||||
}  // details
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair
 | 
			
		||||
   : private ::boost::details::compressed_pair_imp<T1, T2,
 | 
			
		||||
             ::boost::details::compressed_pair_switch<
 | 
			
		||||
                    T1,
 | 
			
		||||
                    T2,
 | 
			
		||||
                    ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
 | 
			
		||||
                    ::boost::is_empty<T1>::value,
 | 
			
		||||
                    ::boost::is_empty<T2>::value>::value>
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   typedef details::compressed_pair_imp<T1, T2,
 | 
			
		||||
             ::boost::details::compressed_pair_switch<
 | 
			
		||||
                    T1,
 | 
			
		||||
                    T2,
 | 
			
		||||
                    ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
 | 
			
		||||
                    ::boost::is_empty<T1>::value,
 | 
			
		||||
                    ::boost::is_empty<T2>::value>::value> base;
 | 
			
		||||
public:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
   typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
            compressed_pair() : base() {}
 | 
			
		||||
            compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
 | 
			
		||||
   explicit compressed_pair(first_param_type x) : base(x) {}
 | 
			
		||||
   explicit compressed_pair(second_param_type y) : base(y) {}
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       {return base::first();}
 | 
			
		||||
   first_const_reference first() const {return base::first();}
 | 
			
		||||
 | 
			
		||||
   second_reference       second()       {return base::second();}
 | 
			
		||||
   second_const_reference second() const {return base::second();}
 | 
			
		||||
 | 
			
		||||
   void swap(compressed_pair& y) { base::swap(y); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// JM
 | 
			
		||||
// Partial specialisation for case where T1 == T2:
 | 
			
		||||
//
 | 
			
		||||
template <class T>
 | 
			
		||||
class compressed_pair<T, T>
 | 
			
		||||
   : private details::compressed_pair_imp<T, T,
 | 
			
		||||
             ::boost::details::compressed_pair_switch<
 | 
			
		||||
                    T,
 | 
			
		||||
                    T,
 | 
			
		||||
                    ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
 | 
			
		||||
                    ::boost::is_empty<T>::value,
 | 
			
		||||
                    ::boost::is_empty<T>::value>::value>
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   typedef details::compressed_pair_imp<T, T,
 | 
			
		||||
             ::boost::details::compressed_pair_switch<
 | 
			
		||||
                    T,
 | 
			
		||||
                    T,
 | 
			
		||||
                    ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
 | 
			
		||||
                    ::boost::is_empty<T>::value,
 | 
			
		||||
                    ::boost::is_empty<T>::value>::value> base;
 | 
			
		||||
public:
 | 
			
		||||
   typedef T                                                  first_type;
 | 
			
		||||
   typedef T                                                  second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
   typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
            compressed_pair() : base() {}
 | 
			
		||||
            compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
 | 
			
		||||
#if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
 | 
			
		||||
   explicit 
 | 
			
		||||
#endif
 | 
			
		||||
      compressed_pair(first_param_type x) : base(x) {}
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       {return base::first();}
 | 
			
		||||
   first_const_reference first() const {return base::first();}
 | 
			
		||||
 | 
			
		||||
   second_reference       second()       {return base::second();}
 | 
			
		||||
   second_const_reference second() const {return base::second();}
 | 
			
		||||
 | 
			
		||||
   void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
inline
 | 
			
		||||
void
 | 
			
		||||
swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
 | 
			
		||||
{
 | 
			
		||||
   x.swap(y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // boost
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										168
									
								
								include/boost/detail/ob_call_traits.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								include/boost/detail/ob_call_traits.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,168 @@
 | 
			
		||||
//  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & 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).
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/utility for most recent version including documentation.
 | 
			
		||||
//
 | 
			
		||||
//  Crippled version for crippled compilers:
 | 
			
		||||
//  see libs/utility/call_traits.htm
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
/* Release notes:
 | 
			
		||||
   01st October 2000:
 | 
			
		||||
      Fixed call_traits on VC6, using "poor man's partial specialisation",
 | 
			
		||||
      using ideas taken from "Generative programming" by Krzysztof Czarnecki 
 | 
			
		||||
      & Ulrich Eisenecker.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_OB_CALL_TRAITS_HPP
 | 
			
		||||
#define BOOST_OB_CALL_TRAITS_HPP
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_CONFIG_HPP
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/arithmetic_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/composite_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace boost{
 | 
			
		||||
 | 
			
		||||
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
 | 
			
		||||
//
 | 
			
		||||
// use member templates to emulate
 | 
			
		||||
// partial specialisation:
 | 
			
		||||
//
 | 
			
		||||
namespace detail{
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
struct standard_call_traits
 | 
			
		||||
{
 | 
			
		||||
   typedef T value_type;
 | 
			
		||||
   typedef T& reference;
 | 
			
		||||
   typedef const T& const_reference;
 | 
			
		||||
   typedef const T& param_type;
 | 
			
		||||
};
 | 
			
		||||
template <class T>
 | 
			
		||||
struct simple_call_traits
 | 
			
		||||
{
 | 
			
		||||
   typedef T value_type;
 | 
			
		||||
   typedef T& reference;
 | 
			
		||||
   typedef const T& const_reference;
 | 
			
		||||
   typedef const T param_type;
 | 
			
		||||
};
 | 
			
		||||
template <class T>
 | 
			
		||||
struct reference_call_traits
 | 
			
		||||
{
 | 
			
		||||
   typedef T value_type;
 | 
			
		||||
   typedef T reference;
 | 
			
		||||
   typedef T const_reference;
 | 
			
		||||
   typedef T param_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <bool pointer, bool arithmetic, bool reference>
 | 
			
		||||
struct call_traits_chooser
 | 
			
		||||
{
 | 
			
		||||
   template <class T>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef standard_call_traits<T> type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct call_traits_chooser<true, false, false>
 | 
			
		||||
{
 | 
			
		||||
   template <class T>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef simple_call_traits<T> type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct call_traits_chooser<false, false, true>
 | 
			
		||||
{
 | 
			
		||||
   template <class T>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef reference_call_traits<T> type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <bool size_is_small> 
 | 
			
		||||
struct call_traits_sizeof_chooser2
 | 
			
		||||
{
 | 
			
		||||
   template <class T>
 | 
			
		||||
   struct small_rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef simple_call_traits<T> small_type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<> 
 | 
			
		||||
struct call_traits_sizeof_chooser2<false>
 | 
			
		||||
{
 | 
			
		||||
   template <class T>
 | 
			
		||||
   struct small_rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef standard_call_traits<T> small_type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct call_traits_chooser<false, true, false>
 | 
			
		||||
{
 | 
			
		||||
   template <class T>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      enum { sizeof_choice = (sizeof(T) <= sizeof(void*)) };
 | 
			
		||||
      typedef call_traits_sizeof_chooser2<(sizeof(T) <= sizeof(void*))> chooser;
 | 
			
		||||
      typedef typename chooser::template small_rebind<T> bound_type;
 | 
			
		||||
      typedef typename bound_type::small_type type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace detail
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct call_traits
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
    typedef detail::call_traits_chooser<
 | 
			
		||||
         ::boost::is_pointer<T>::value,
 | 
			
		||||
         ::boost::is_arithmetic<T>::value, 
 | 
			
		||||
         ::boost::is_reference<T>::value
 | 
			
		||||
      > chooser;
 | 
			
		||||
   typedef typename chooser::template rebind<T> bound_type;
 | 
			
		||||
   typedef typename bound_type::type call_traits_type;
 | 
			
		||||
public:
 | 
			
		||||
   typedef typename call_traits_type::value_type       value_type;
 | 
			
		||||
   typedef typename call_traits_type::reference        reference;
 | 
			
		||||
   typedef typename call_traits_type::const_reference  const_reference;
 | 
			
		||||
   typedef typename call_traits_type::param_type       param_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
//
 | 
			
		||||
// sorry call_traits is completely non-functional
 | 
			
		||||
// blame your broken compiler:
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct call_traits
 | 
			
		||||
{
 | 
			
		||||
   typedef T value_type;
 | 
			
		||||
   typedef T& reference;
 | 
			
		||||
   typedef const T& const_reference;
 | 
			
		||||
   typedef const T& param_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // member templates
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_OB_CALL_TRAITS_HPP
 | 
			
		||||
							
								
								
									
										510
									
								
								include/boost/detail/ob_compressed_pair.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										510
									
								
								include/boost/detail/ob_compressed_pair.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,510 @@
 | 
			
		||||
//  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & 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).
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/utility for most recent version including documentation.
 | 
			
		||||
//  see libs/utility/compressed_pair.hpp
 | 
			
		||||
//
 | 
			
		||||
/* Release notes:
 | 
			
		||||
   20 Jan 2001:
 | 
			
		||||
        Fixed obvious bugs (David Abrahams)
 | 
			
		||||
   07 Oct 2000:
 | 
			
		||||
      Added better single argument constructor support.
 | 
			
		||||
   03 Oct 2000:
 | 
			
		||||
      Added VC6 support (JM).
 | 
			
		||||
   23rd July 2000:
 | 
			
		||||
      Additional comments added. (JM)
 | 
			
		||||
   Jan 2000:
 | 
			
		||||
      Original version: this version crippled for use with crippled compilers
 | 
			
		||||
      - John Maddock Jan 2000.
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_OB_COMPRESSED_PAIR_HPP
 | 
			
		||||
#define BOOST_OB_COMPRESSED_PAIR_HPP
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/object_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_SAME_TRAITS_HPP
 | 
			
		||||
#include <boost/type_traits/same_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef BOOST_CALL_TRAITS_HPP
 | 
			
		||||
#include <boost/call_traits.hpp>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
 | 
			
		||||
//
 | 
			
		||||
// use member templates to emulate
 | 
			
		||||
// partial specialisation.  Note that due to
 | 
			
		||||
// problems with overload resolution with VC6
 | 
			
		||||
// each of the compressed_pair versions that follow
 | 
			
		||||
// have one template single-argument constructor
 | 
			
		||||
// in place of two specific constructors:
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair;
 | 
			
		||||
 | 
			
		||||
namespace detail{
 | 
			
		||||
 | 
			
		||||
template <class A, class T1, class T2>
 | 
			
		||||
struct best_conversion_traits
 | 
			
		||||
{
 | 
			
		||||
   typedef char one;
 | 
			
		||||
   typedef char (&two)[2];
 | 
			
		||||
   static A a;
 | 
			
		||||
   static one test(T1);
 | 
			
		||||
   static two test(T2);
 | 
			
		||||
 | 
			
		||||
   enum { value = sizeof(test(a)) };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <int>
 | 
			
		||||
struct init_one;
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct init_one<1>
 | 
			
		||||
{
 | 
			
		||||
   template <class A, class T1, class T2>
 | 
			
		||||
   static void init(const A& a, T1* p1, T2*)
 | 
			
		||||
   {
 | 
			
		||||
      *p1 = a;
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct init_one<2>
 | 
			
		||||
{
 | 
			
		||||
   template <class A, class T1, class T2>
 | 
			
		||||
   static void init(const A& a, T1*, T2* p2)
 | 
			
		||||
   {
 | 
			
		||||
      *p2 = a;
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// T1 != T2, both non-empty
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair_0
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   T1 _first;
 | 
			
		||||
   T2 _second;
 | 
			
		||||
public:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
   typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
            compressed_pair_0() : _first(), _second() {}
 | 
			
		||||
            compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {}
 | 
			
		||||
   template <class A>
 | 
			
		||||
   explicit compressed_pair_0(const A& val)
 | 
			
		||||
   {
 | 
			
		||||
      init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
 | 
			
		||||
   }
 | 
			
		||||
   compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x)
 | 
			
		||||
      : _first(x.first()), _second(x.second()) {}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  compressed_pair_0& operator=(const compressed_pair_0& x) {
 | 
			
		||||
    cout << "assigning compressed pair 0" << endl;
 | 
			
		||||
    _first = x._first;
 | 
			
		||||
    _second = x._second;
 | 
			
		||||
    cout << "finished assigning compressed pair 0" << endl;
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       { return _first; }
 | 
			
		||||
   first_const_reference first() const { return _first; }
 | 
			
		||||
 | 
			
		||||
   second_reference       second()       { return _second; }
 | 
			
		||||
   second_const_reference second() const { return _second; }
 | 
			
		||||
 | 
			
		||||
   void swap(compressed_pair_0& y)
 | 
			
		||||
   {
 | 
			
		||||
      using std::swap;
 | 
			
		||||
      swap(_first, y._first);
 | 
			
		||||
      swap(_second, y._second);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// T1 != T2, T2 empty
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair_1 : T2
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   T1 _first;
 | 
			
		||||
public:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
   typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
            compressed_pair_1() : T2(), _first() {}
 | 
			
		||||
            compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
 | 
			
		||||
 | 
			
		||||
   template <class A>
 | 
			
		||||
   explicit compressed_pair_1(const A& val)
 | 
			
		||||
   {
 | 
			
		||||
      init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
 | 
			
		||||
      : T2(x.second()), _first(x.first()) {}
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
 | 
			
		||||
  // Total weirdness. If the assignment to _first is moved after
 | 
			
		||||
  // the call to the inherited operator=, then this breaks graph/test/graph.cpp
 | 
			
		||||
  // by way of iterator_adaptor.
 | 
			
		||||
  compressed_pair_1& operator=(const compressed_pair_1& x) {
 | 
			
		||||
    _first = x._first;
 | 
			
		||||
    T2::operator=(x);
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       { return _first; }
 | 
			
		||||
   first_const_reference first() const { return _first; }
 | 
			
		||||
 | 
			
		||||
   second_reference       second()       { return *this; }
 | 
			
		||||
   second_const_reference second() const { return *this; }
 | 
			
		||||
 | 
			
		||||
   void swap(compressed_pair_1& y)
 | 
			
		||||
   {
 | 
			
		||||
      // no need to swap empty base class:
 | 
			
		||||
      using std::swap;
 | 
			
		||||
      swap(_first, y._first);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// T1 != T2, T1 empty
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair_2 : T1
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   T2 _second;
 | 
			
		||||
public:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
   typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
            compressed_pair_2() : T1(), _second() {}
 | 
			
		||||
            compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {}
 | 
			
		||||
   template <class A>
 | 
			
		||||
   explicit compressed_pair_2(const A& val)
 | 
			
		||||
   {
 | 
			
		||||
      init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
 | 
			
		||||
   }
 | 
			
		||||
   compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x)
 | 
			
		||||
      : T1(x.first()), _second(x.second()) {}
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
  compressed_pair_2& operator=(const compressed_pair_2& x) {
 | 
			
		||||
    cout << "assigning compressed pair 2" << endl;
 | 
			
		||||
    T1::operator=(x);
 | 
			
		||||
    _second = x._second;
 | 
			
		||||
    cout << "finished assigning compressed pair 2" << endl;
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
   first_reference       first()       { return *this; }
 | 
			
		||||
   first_const_reference first() const { return *this; }
 | 
			
		||||
 | 
			
		||||
   second_reference       second()       { return _second; }
 | 
			
		||||
   second_const_reference second() const { return _second; }
 | 
			
		||||
 | 
			
		||||
   void swap(compressed_pair_2& y)
 | 
			
		||||
   {
 | 
			
		||||
      // no need to swap empty base class:
 | 
			
		||||
      using std::swap;
 | 
			
		||||
      swap(_second, y._second);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// T1 != T2, both empty
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair_3 : T1, T2
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
   typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
            compressed_pair_3() : T1(), T2() {}
 | 
			
		||||
            compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {}
 | 
			
		||||
   template <class A>
 | 
			
		||||
   explicit compressed_pair_3(const A& val)
 | 
			
		||||
   {
 | 
			
		||||
      init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
 | 
			
		||||
   }
 | 
			
		||||
   compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x)
 | 
			
		||||
      : T1(x.first()), T2(x.second()) {}
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       { return *this; }
 | 
			
		||||
   first_const_reference first() const { return *this; }
 | 
			
		||||
 | 
			
		||||
   second_reference       second()       { return *this; }
 | 
			
		||||
   second_const_reference second() const { return *this; }
 | 
			
		||||
 | 
			
		||||
   void swap(compressed_pair_3& y)
 | 
			
		||||
   {
 | 
			
		||||
      // no need to swap empty base classes:
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// T1 == T2, and empty
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair_4 : T1
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
   typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
            compressed_pair_4() : T1() {}
 | 
			
		||||
            compressed_pair_4(first_param_type x, second_param_type y) : T1(x), m_second(y) {}
 | 
			
		||||
   // only one single argument constructor since T1 == T2
 | 
			
		||||
   explicit compressed_pair_4(first_param_type x) : T1(x), m_second(x) {}
 | 
			
		||||
   compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
 | 
			
		||||
      : T1(x.first()), m_second(x.second()) {}
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       { return *this; }
 | 
			
		||||
   first_const_reference first() const { return *this; }
 | 
			
		||||
 | 
			
		||||
   second_reference       second()       { return m_second; }
 | 
			
		||||
   second_const_reference second() const { return m_second; }
 | 
			
		||||
 | 
			
		||||
   void swap(compressed_pair_4& y)
 | 
			
		||||
   {
 | 
			
		||||
      // no need to swap empty base classes:
 | 
			
		||||
   }
 | 
			
		||||
private:
 | 
			
		||||
   T2 m_second;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// T1 == T2, not empty
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair_5
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   T1 _first;
 | 
			
		||||
   T2 _second;
 | 
			
		||||
public:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
   typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
            compressed_pair_5() : _first(), _second() {}
 | 
			
		||||
            compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
 | 
			
		||||
   // only one single argument constructor since T1 == T2
 | 
			
		||||
   explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
 | 
			
		||||
   compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c) 
 | 
			
		||||
      : _first(c.first()), _second(c.second()) {}
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       { return _first; }
 | 
			
		||||
   first_const_reference first() const { return _first; }
 | 
			
		||||
 | 
			
		||||
   second_reference       second()       { return _second; }
 | 
			
		||||
   second_const_reference second() const { return _second; }
 | 
			
		||||
 | 
			
		||||
   void swap(compressed_pair_5& y)
 | 
			
		||||
   {
 | 
			
		||||
      using std::swap;
 | 
			
		||||
      swap(_first, y._first);
 | 
			
		||||
      swap(_second, y._second);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <bool e1, bool e2, bool same>
 | 
			
		||||
struct compressed_pair_chooser
 | 
			
		||||
{
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef compressed_pair_0<T1, T2> type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct compressed_pair_chooser<false, true, false>
 | 
			
		||||
{
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef compressed_pair_1<T1, T2> type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct compressed_pair_chooser<true, false, false>
 | 
			
		||||
{
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef compressed_pair_2<T1, T2> type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct compressed_pair_chooser<true, true, false>
 | 
			
		||||
{
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef compressed_pair_3<T1, T2> type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct compressed_pair_chooser<true, true, true>
 | 
			
		||||
{
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef compressed_pair_4<T1, T2> type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <>
 | 
			
		||||
struct compressed_pair_chooser<false, false, true>
 | 
			
		||||
{
 | 
			
		||||
   template <class T1, class T2>
 | 
			
		||||
   struct rebind
 | 
			
		||||
   {
 | 
			
		||||
      typedef compressed_pair_5<T1, T2> type;
 | 
			
		||||
   };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
struct compressed_pair_traits
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   typedef compressed_pair_chooser<is_empty<T1>::value, is_empty<T2>::value, is_same<T1,T2>::value> chooser;
 | 
			
		||||
   typedef typename chooser::template rebind<T1, T2> bound_type;
 | 
			
		||||
public:
 | 
			
		||||
   typedef typename bound_type::type type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace detail
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   typedef typename detail::compressed_pair_traits<T1, T2>::type base_type;
 | 
			
		||||
public:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
   typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
            compressed_pair() : base_type() {}
 | 
			
		||||
            compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {}
 | 
			
		||||
   template <class A>
 | 
			
		||||
   explicit compressed_pair(const A& x) : base_type(x){}
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       { return base_type::first(); }
 | 
			
		||||
   first_const_reference first() const { return base_type::first(); }
 | 
			
		||||
 | 
			
		||||
   second_reference       second()       { return base_type::second(); }
 | 
			
		||||
   second_const_reference second() const { return base_type::second(); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
 | 
			
		||||
{
 | 
			
		||||
   x.swap(y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
// no partial specialisation, no member templates:
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
class compressed_pair
 | 
			
		||||
{
 | 
			
		||||
private:
 | 
			
		||||
   T1 _first;
 | 
			
		||||
   T2 _second;
 | 
			
		||||
public:
 | 
			
		||||
   typedef T1                                                 first_type;
 | 
			
		||||
   typedef T2                                                 second_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::param_type       first_param_type;
 | 
			
		||||
   typedef typename call_traits<second_type>::param_type      second_param_type;
 | 
			
		||||
   typedef typename call_traits<first_type>::reference        first_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::reference       second_reference;
 | 
			
		||||
   typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | 
			
		||||
   typedef typename call_traits<second_type>::const_reference second_const_reference;
 | 
			
		||||
 | 
			
		||||
            compressed_pair() : _first(), _second() {}
 | 
			
		||||
            compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {}
 | 
			
		||||
   explicit compressed_pair(first_param_type x) : _first(x), _second() {}
 | 
			
		||||
   // can't define this in case T1 == T2:
 | 
			
		||||
   // explicit compressed_pair(second_param_type y) : _first(), _second(y) {}
 | 
			
		||||
 | 
			
		||||
   first_reference       first()       { return _first; }
 | 
			
		||||
   first_const_reference first() const { return _first; }
 | 
			
		||||
 | 
			
		||||
   second_reference       second()       { return _second; }
 | 
			
		||||
   second_const_reference second() const { return _second; }
 | 
			
		||||
 | 
			
		||||
   void swap(compressed_pair& y)
 | 
			
		||||
   {
 | 
			
		||||
      using std::swap;
 | 
			
		||||
      swap(_first, y._first);
 | 
			
		||||
      swap(_second, y._second);
 | 
			
		||||
   }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
 | 
			
		||||
{
 | 
			
		||||
   x.swap(y);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
} // boost
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_OB_COMPRESSED_PAIR_HPP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										81
									
								
								include/boost/generator_iterator.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								include/boost/generator_iterator.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,81 @@
 | 
			
		||||
// (C) Copyright Jens Maurer 2001. Permission to copy, use,
 | 
			
		||||
// modify, sell and distribute this software is granted provided this
 | 
			
		||||
// copyright notice appears in all copies. This software is provided
 | 
			
		||||
// "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
// to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
// Revision History:
 | 
			
		||||
 | 
			
		||||
// 15 Nov 2001   Jens Maurer
 | 
			
		||||
//      created.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org/libs/utility/iterator_adaptors.htm for documentation.
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
 | 
			
		||||
#define BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
 | 
			
		||||
 | 
			
		||||
#include <boost/iterator/iterator_facade.hpp>
 | 
			
		||||
#include <boost/ref.hpp>
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
template<class Generator>
 | 
			
		||||
class generator_iterator
 | 
			
		||||
  : public iterator_facade<
 | 
			
		||||
        generator_iterator<Generator>
 | 
			
		||||
      , typename Generator::result_type
 | 
			
		||||
      , single_pass_traversal_tag
 | 
			
		||||
      , typename Generator::result_type const&
 | 
			
		||||
    >
 | 
			
		||||
{
 | 
			
		||||
    typedef iterator_facade<
 | 
			
		||||
        generator_iterator<Generator>
 | 
			
		||||
      , typename Generator::result_type
 | 
			
		||||
      , single_pass_traversal_tag
 | 
			
		||||
      , typename Generator::result_type const&
 | 
			
		||||
    > super_t;
 | 
			
		||||
    
 | 
			
		||||
 public:
 | 
			
		||||
    generator_iterator() {}
 | 
			
		||||
    generator_iterator(Generator* g) : m_g(g), m_value((*m_g)()) {}
 | 
			
		||||
 | 
			
		||||
    void increment()
 | 
			
		||||
    {
 | 
			
		||||
        m_value = (*m_g)();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const typename Generator::result_type&
 | 
			
		||||
    dereference() const
 | 
			
		||||
    {
 | 
			
		||||
        return m_value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool equal(generator_iterator const& y) const
 | 
			
		||||
    {
 | 
			
		||||
        return this->m_g == y.m_g && this->m_value == y.m_value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
    Generator* m_g;
 | 
			
		||||
    typename Generator::result_type m_value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<class Generator>
 | 
			
		||||
struct generator_iterator_generator
 | 
			
		||||
{
 | 
			
		||||
  typedef generator_iterator<Generator> type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Generator>
 | 
			
		||||
inline generator_iterator<Generator>
 | 
			
		||||
make_generator_iterator(Generator & gen)
 | 
			
		||||
{
 | 
			
		||||
  typedef generator_iterator<Generator> result_t;
 | 
			
		||||
  return result_t(&gen);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										53
									
								
								include/boost/next_prior.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								include/boost/next_prior.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
//  Boost next_prior.hpp header file  ---------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Boost.org 1999-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.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org/libs/utility for documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  13 Dec 2003  Added next(x, n) and prior(x, n) (Daniel Walker)
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NEXT_PRIOR_HPP_INCLUDED
 | 
			
		||||
#define BOOST_NEXT_PRIOR_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
#include <iterator>
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
//  Helper functions for classes like bidirectional iterators not supporting
 | 
			
		||||
//  operator+ and operator-
 | 
			
		||||
//
 | 
			
		||||
//  Usage:
 | 
			
		||||
//    const std::list<T>::iterator p = get_some_iterator();
 | 
			
		||||
//    const std::list<T>::iterator prev = boost::prior(p);
 | 
			
		||||
//    const std::list<T>::iterator next = boost::next(prev, 2);
 | 
			
		||||
 | 
			
		||||
//  Contributed by Dave Abrahams
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
inline T next(T x) { return ++x; }
 | 
			
		||||
 | 
			
		||||
template <class T, class Distance>
 | 
			
		||||
inline T next(T x, Distance n)
 | 
			
		||||
{
 | 
			
		||||
    std::advance(x, n);
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <class T>
 | 
			
		||||
inline T prior(T x) { return --x; }
 | 
			
		||||
 | 
			
		||||
template <class T, class Distance>
 | 
			
		||||
inline T prior(T x, Distance n)
 | 
			
		||||
{
 | 
			
		||||
    std::advance(x, -n);
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif  // BOOST_NEXT_PRIOR_HPP_INCLUDED
 | 
			
		||||
							
								
								
									
										33
									
								
								include/boost/noncopyable.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								include/boost/noncopyable.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
//  Boost noncopyable.hpp header file  --------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Boost.org 1999-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.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org/libs/utility for documentation.
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NONCOPYABLE_HPP_INCLUDED
 | 
			
		||||
#define BOOST_NONCOPYABLE_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
//  Private copy constructor and copy assignment ensure classes derived from
 | 
			
		||||
//  class noncopyable cannot be copied.
 | 
			
		||||
 | 
			
		||||
//  Contributed by Dave Abrahams
 | 
			
		||||
 | 
			
		||||
class noncopyable
 | 
			
		||||
{
 | 
			
		||||
 protected:
 | 
			
		||||
    noncopyable() {}
 | 
			
		||||
    ~noncopyable() {}
 | 
			
		||||
 private:  // emphasize the following members are private
 | 
			
		||||
    noncopyable( const noncopyable& );
 | 
			
		||||
    const noncopyable& operator=( const noncopyable& );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif  // BOOST_NONCOPYABLE_HPP_INCLUDED
 | 
			
		||||
							
								
								
									
										942
									
								
								include/boost/operators.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										942
									
								
								include/boost/operators.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,942 @@
 | 
			
		||||
//  Boost operators.hpp header file  ----------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-2001.
 | 
			
		||||
//  Permission to copy, use, modify, sell and distribute this software is
 | 
			
		||||
//  granted provided this copyright notice appears in all copies.  This
 | 
			
		||||
//  software is provided "as is" without express or implied warranty, and
 | 
			
		||||
//  with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org/libs/utility/operators.htm for documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  21 Oct 02 Modified implementation of operators to allow compilers with a
 | 
			
		||||
//            correct named return value optimization (NRVO) to produce optimal
 | 
			
		||||
//            code.  (Daniel Frey)
 | 
			
		||||
//  02 Dec 01 Bug fixed in random_access_iteratable.  (Helmut Zeisel)
 | 
			
		||||
//  28 Sep 01 Factored out iterator operator groups.  (Daryle Walker)
 | 
			
		||||
//  27 Aug 01 'left' form for non commutative operators added;
 | 
			
		||||
//            additional classes for groups of related operators added;
 | 
			
		||||
//            workaround for empty base class optimization
 | 
			
		||||
//            bug of GCC 3.0 (Helmut Zeisel)
 | 
			
		||||
//  25 Jun 01 output_iterator_helper changes: removed default template 
 | 
			
		||||
//            parameters, added support for self-proxying, additional 
 | 
			
		||||
//            documentation and tests (Aleksey Gurtovoy)
 | 
			
		||||
//  29 May 01 Added operator classes for << and >>.  Added input and output
 | 
			
		||||
//            iterator helper classes.  Added classes to connect equality and
 | 
			
		||||
//            relational operators.  Added classes for groups of related
 | 
			
		||||
//            operators.  Reimplemented example operator and iterator helper
 | 
			
		||||
//            classes in terms of the new groups.  (Daryle Walker, with help
 | 
			
		||||
//            from Alexy Gurtovoy)
 | 
			
		||||
//  11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
 | 
			
		||||
//            supplied arguments from actually being used (Dave Abrahams)
 | 
			
		||||
//  04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
 | 
			
		||||
//            refactoring of compiler workarounds, additional documentation
 | 
			
		||||
//            (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
 | 
			
		||||
//            Dave Abrahams) 
 | 
			
		||||
//  28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and
 | 
			
		||||
//            Jeremy Siek (Dave Abrahams)
 | 
			
		||||
//  20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5
 | 
			
		||||
//            (Mark Rodgers)
 | 
			
		||||
//  20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy)
 | 
			
		||||
//  10 Jun 00 Support for the base class chaining technique was added
 | 
			
		||||
//            (Aleksey Gurtovoy). See documentation and the comments below 
 | 
			
		||||
//            for the details. 
 | 
			
		||||
//  12 Dec 99 Initial version with iterator operators (Jeremy Siek)
 | 
			
		||||
//  18 Nov 99 Change name "divideable" to "dividable", remove unnecessary
 | 
			
		||||
//            specializations of dividable, subtractable, modable (Ed Brey) 
 | 
			
		||||
//  17 Nov 99 Add comments (Beman Dawes)
 | 
			
		||||
//            Remove unnecessary specialization of operators<> (Ed Brey)
 | 
			
		||||
//  15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two
 | 
			
		||||
//            operators.(Beman Dawes)
 | 
			
		||||
//  12 Nov 99 Add operators templates (Ed Brey)
 | 
			
		||||
//  11 Nov 99 Add single template parameter version for compilers without
 | 
			
		||||
//            partial specialization (Beman Dawes)
 | 
			
		||||
//  10 Nov 99 Initial version
 | 
			
		||||
 | 
			
		||||
// 10 Jun 00:
 | 
			
		||||
// An additional optional template parameter was added to most of 
 | 
			
		||||
// operator templates to support the base class chaining technique (see 
 | 
			
		||||
// documentation for the details). Unfortunately, a straightforward
 | 
			
		||||
// implementation of this change would have broken compatibility with the
 | 
			
		||||
// previous version of the library by making it impossible to use the same
 | 
			
		||||
// template name (e.g. 'addable') for both the 1- and 2-argument versions of
 | 
			
		||||
// an operator template. This implementation solves the backward-compatibility
 | 
			
		||||
// issue at the cost of some simplicity.
 | 
			
		||||
//
 | 
			
		||||
// One of the complications is an existence of special auxiliary class template
 | 
			
		||||
// 'is_chained_base<>' (see 'detail' namespace below), which is used
 | 
			
		||||
// to determine whether its template parameter is a library's operator template
 | 
			
		||||
// or not. You have to specialize 'is_chained_base<>' for each new 
 | 
			
		||||
// operator template you add to the library.
 | 
			
		||||
//
 | 
			
		||||
// However, most of the non-trivial implementation details are hidden behind 
 | 
			
		||||
// several local macros defined below, and as soon as you understand them,
 | 
			
		||||
// you understand the whole library implementation. 
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_OPERATORS_HPP
 | 
			
		||||
#define BOOST_OPERATORS_HPP
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <boost/iterator.hpp>
 | 
			
		||||
#include <boost/detail/workaround.hpp>
 | 
			
		||||
 | 
			
		||||
#if defined(__sgi) && !defined(__GNUC__)
 | 
			
		||||
#   pragma set woff 1234
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC)
 | 
			
		||||
#   pragma warning( disable : 4284 ) // complaint about return type of 
 | 
			
		||||
#endif                               // operator-> not begin a UDT
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
// Helmut Zeisel, empty base class optimization bug with GCC 3.0.0
 | 
			
		||||
#if defined(__GNUC__) && __GNUC__==3 && __GNUC_MINOR__==0 && __GNU_PATCHLEVEL__==0
 | 
			
		||||
class empty_base {
 | 
			
		||||
  bool dummy; 
 | 
			
		||||
};
 | 
			
		||||
#else
 | 
			
		||||
class empty_base {};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
} // namespace detail
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
// In this section we supply the xxxx1 and xxxx2 forms of the operator
 | 
			
		||||
// templates, which are explicitly targeted at the 1-type-argument and
 | 
			
		||||
// 2-type-argument operator forms, respectively. Some compilers get confused
 | 
			
		||||
// when inline friend functions are overloaded in namespaces other than the
 | 
			
		||||
// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of
 | 
			
		||||
// these templates must go in the global namespace.
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//  Basic operator classes (contributed by Dave Abrahams) ------------------//
 | 
			
		||||
 | 
			
		||||
//  Note that friend functions defined in a class are implicitly inline.
 | 
			
		||||
//  See the C++ std, 11.4 [class.friend] paragraph 5
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct less_than_comparable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend bool operator<=(const T& x, const U& y) { return !(x > y); }
 | 
			
		||||
     friend bool operator>=(const T& x, const U& y) { return !(x < y); }
 | 
			
		||||
     friend bool operator>(const U& x, const T& y)  { return y < x; }
 | 
			
		||||
     friend bool operator<(const U& x, const T& y)  { return y > x; }
 | 
			
		||||
     friend bool operator<=(const U& x, const T& y) { return !(y < x); }
 | 
			
		||||
     friend bool operator>=(const U& x, const T& y) { return !(y > x); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct less_than_comparable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend bool operator>(const T& x, const T& y)  { return y < x; }
 | 
			
		||||
     friend bool operator<=(const T& x, const T& y) { return !(y < x); }
 | 
			
		||||
     friend bool operator>=(const T& x, const T& y) { return !(x < y); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct equality_comparable2 : B
 | 
			
		||||
{
 | 
			
		||||
     friend bool operator==(const U& y, const T& x) { return x == y; }
 | 
			
		||||
     friend bool operator!=(const U& y, const T& x) { return !(x == y); }
 | 
			
		||||
     friend bool operator!=(const T& y, const U& x) { return !(y == x); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct equality_comparable1 : B
 | 
			
		||||
{
 | 
			
		||||
     friend bool operator!=(const T& x, const T& y) { return !(x == y); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// A macro which produces "name_2left" from "name".
 | 
			
		||||
#define BOOST_OPERATOR2_LEFT(name) name##2##_##left
 | 
			
		||||
 | 
			
		||||
//  NRVO-friendly implementation (contributed by Daniel Frey) ---------------//
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
 | 
			
		||||
 | 
			
		||||
// This is the optimal implementation for ISO/ANSI C++,
 | 
			
		||||
// but it requires the compiler to implement the NRVO.
 | 
			
		||||
// If the compiler has no NRVO, this is the best symmetric
 | 
			
		||||
// implementation available.
 | 
			
		||||
 | 
			
		||||
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP )                         \
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>            \
 | 
			
		||||
struct NAME##2 : B                                                            \
 | 
			
		||||
{                                                                             \
 | 
			
		||||
  friend T operator OP( const T& lhs, const U& rhs )                          \
 | 
			
		||||
    { T nrv( lhs ); nrv OP##= rhs; return nrv; }                              \
 | 
			
		||||
  friend T operator OP( const U& lhs, const T& rhs )                          \
 | 
			
		||||
    { T nrv( rhs ); nrv OP##= lhs; return nrv; }                              \
 | 
			
		||||
};                                                                            \
 | 
			
		||||
                                                                              \
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>                     \
 | 
			
		||||
struct NAME##1 : B                                                            \
 | 
			
		||||
{                                                                             \
 | 
			
		||||
  friend T operator OP( const T& lhs, const T& rhs )                          \
 | 
			
		||||
    { T nrv( lhs ); nrv OP##= rhs; return nrv; }                              \
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP )           \
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>  \
 | 
			
		||||
struct NAME##2 : B                                                  \
 | 
			
		||||
{                                                                   \
 | 
			
		||||
  friend T operator OP( const T& lhs, const U& rhs )                \
 | 
			
		||||
    { T nrv( lhs ); nrv OP##= rhs; return nrv; }                    \
 | 
			
		||||
};                                                                  \
 | 
			
		||||
                                                                    \
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>  \
 | 
			
		||||
struct BOOST_OPERATOR2_LEFT(NAME) : B                               \
 | 
			
		||||
{                                                                   \
 | 
			
		||||
  friend T operator OP( const U& lhs, const T& rhs )                \
 | 
			
		||||
    { T nrv( lhs ); nrv OP##= rhs; return nrv; }                    \
 | 
			
		||||
};                                                                  \
 | 
			
		||||
                                                                    \
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>           \
 | 
			
		||||
struct NAME##1 : B                                                  \
 | 
			
		||||
{                                                                   \
 | 
			
		||||
  friend T operator OP( const T& lhs, const T& rhs )                \
 | 
			
		||||
    { T nrv( lhs ); nrv OP##= rhs; return nrv; }                    \
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
 | 
			
		||||
 | 
			
		||||
// For compilers without NRVO the following code is optimal, but not
 | 
			
		||||
// symmetric!  Note that the implementation of
 | 
			
		||||
// BOOST_OPERATOR2_LEFT(NAME) only looks cool, but doesn't provide
 | 
			
		||||
// optimization opportunities to the compiler :)
 | 
			
		||||
 | 
			
		||||
#define BOOST_BINARY_OPERATOR_COMMUTATIVE( NAME, OP )                         \
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>            \
 | 
			
		||||
struct NAME##2 : B                                                            \
 | 
			
		||||
{                                                                             \
 | 
			
		||||
  friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; }       \
 | 
			
		||||
  friend T operator OP( const U& lhs, T rhs ) { return rhs OP##= lhs; }       \
 | 
			
		||||
};                                                                            \
 | 
			
		||||
                                                                              \
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>                     \
 | 
			
		||||
struct NAME##1 : B                                                            \
 | 
			
		||||
{                                                                             \
 | 
			
		||||
  friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; }       \
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( NAME, OP )               \
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>      \
 | 
			
		||||
struct NAME##2 : B                                                      \
 | 
			
		||||
{                                                                       \
 | 
			
		||||
  friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; } \
 | 
			
		||||
};                                                                      \
 | 
			
		||||
                                                                        \
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>      \
 | 
			
		||||
struct BOOST_OPERATOR2_LEFT(NAME) : B                                   \
 | 
			
		||||
{                                                                       \
 | 
			
		||||
  friend T operator OP( const U& lhs, const T& rhs )                    \
 | 
			
		||||
    { return T( lhs ) OP##= rhs; }                                      \
 | 
			
		||||
};                                                                      \
 | 
			
		||||
                                                                        \
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>               \
 | 
			
		||||
struct NAME##1 : B                                                      \
 | 
			
		||||
{                                                                       \
 | 
			
		||||
  friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; } \
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
 | 
			
		||||
 | 
			
		||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( multipliable, * )
 | 
			
		||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( addable, + )
 | 
			
		||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( subtractable, - )
 | 
			
		||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( dividable, / )
 | 
			
		||||
BOOST_BINARY_OPERATOR_NON_COMMUTATIVE( modable, % )
 | 
			
		||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( xorable, ^ )
 | 
			
		||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( andable, & )
 | 
			
		||||
BOOST_BINARY_OPERATOR_COMMUTATIVE( orable, | )
 | 
			
		||||
 | 
			
		||||
#undef BOOST_BINARY_OPERATOR_COMMUTATIVE
 | 
			
		||||
#undef BOOST_BINARY_OPERATOR_NON_COMMUTATIVE
 | 
			
		||||
#undef BOOST_OPERATOR2_LEFT
 | 
			
		||||
 | 
			
		||||
//  incrementable and decrementable contributed by Jeremy Siek
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct incrementable : B
 | 
			
		||||
{
 | 
			
		||||
  friend T operator++(T& x, int)
 | 
			
		||||
  {
 | 
			
		||||
    incrementable_type nrv(x);
 | 
			
		||||
    ++x;
 | 
			
		||||
    return nrv;
 | 
			
		||||
  }
 | 
			
		||||
private: // The use of this typedef works around a Borland bug
 | 
			
		||||
  typedef T incrementable_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct decrementable : B
 | 
			
		||||
{
 | 
			
		||||
  friend T operator--(T& x, int)
 | 
			
		||||
  {
 | 
			
		||||
    decrementable_type nrv(x);
 | 
			
		||||
    --x;
 | 
			
		||||
    return nrv;
 | 
			
		||||
  }
 | 
			
		||||
private: // The use of this typedef works around a Borland bug
 | 
			
		||||
  typedef T decrementable_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//  Iterator operator classes (contributed by Jeremy Siek) ------------------//
 | 
			
		||||
 | 
			
		||||
template <class T, class P, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct dereferenceable : B
 | 
			
		||||
{
 | 
			
		||||
  P operator->() const
 | 
			
		||||
  { 
 | 
			
		||||
    return &*static_cast<const T&>(*this); 
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class I, class R, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct indexable : B
 | 
			
		||||
{
 | 
			
		||||
  R operator[](I n) const
 | 
			
		||||
  {
 | 
			
		||||
    return *(static_cast<const T&>(*this) + n);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//  More operator classes (contributed by Daryle Walker) --------------------//
 | 
			
		||||
//  (NRVO-friendly implementation contributed by Daniel Frey) ---------------//
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
 | 
			
		||||
 | 
			
		||||
#define BOOST_BINARY_OPERATOR( NAME, OP )                                     \
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>            \
 | 
			
		||||
struct NAME##2 : B                                                            \
 | 
			
		||||
{                                                                             \
 | 
			
		||||
  friend T operator OP( const T& lhs, const U& rhs )                          \
 | 
			
		||||
    { T nrv( lhs ); nrv OP##= rhs; return nrv; }                              \
 | 
			
		||||
};                                                                            \
 | 
			
		||||
                                                                              \
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>                     \
 | 
			
		||||
struct NAME##1 : B                                                            \
 | 
			
		||||
{                                                                             \
 | 
			
		||||
  friend T operator OP( const T& lhs, const T& rhs )                          \
 | 
			
		||||
    { T nrv( lhs ); nrv OP##= rhs; return nrv; }                              \
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#else // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
 | 
			
		||||
 | 
			
		||||
#define BOOST_BINARY_OPERATOR( NAME, OP )                                     \
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>            \
 | 
			
		||||
struct NAME##2 : B                                                            \
 | 
			
		||||
{                                                                             \
 | 
			
		||||
  friend T operator OP( T lhs, const U& rhs ) { return lhs OP##= rhs; }       \
 | 
			
		||||
};                                                                            \
 | 
			
		||||
                                                                              \
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>                     \
 | 
			
		||||
struct NAME##1 : B                                                            \
 | 
			
		||||
{                                                                             \
 | 
			
		||||
  friend T operator OP( T lhs, const T& rhs ) { return lhs OP##= rhs; }       \
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // defined(BOOST_HAS_NRVO) || defined(BOOST_FORCE_SYMMETRIC_OPERATORS)
 | 
			
		||||
 | 
			
		||||
BOOST_BINARY_OPERATOR( left_shiftable, << )
 | 
			
		||||
BOOST_BINARY_OPERATOR( right_shiftable, >> )
 | 
			
		||||
 | 
			
		||||
#undef BOOST_BINARY_OPERATOR
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct equivalent2 : B
 | 
			
		||||
{
 | 
			
		||||
  friend bool operator==(const T& x, const U& y)
 | 
			
		||||
  {
 | 
			
		||||
    return !(x < y) && !(x > y);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct equivalent1 : B
 | 
			
		||||
{
 | 
			
		||||
  friend bool operator==(const T&x, const T&y)
 | 
			
		||||
  {
 | 
			
		||||
    return !(x < y) && !(y < x);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct partially_ordered2 : B
 | 
			
		||||
{
 | 
			
		||||
  friend bool operator<=(const T& x, const U& y)
 | 
			
		||||
    { return (x < y) || (x == y); }
 | 
			
		||||
  friend bool operator>=(const T& x, const U& y)
 | 
			
		||||
    { return (x > y) || (x == y); }
 | 
			
		||||
  friend bool operator>(const U& x, const T& y)
 | 
			
		||||
    { return y < x; }
 | 
			
		||||
  friend bool operator<(const U& x, const T& y)
 | 
			
		||||
    { return y > x; }
 | 
			
		||||
  friend bool operator<=(const U& x, const T& y)
 | 
			
		||||
    { return (y > x) || (y == x); }
 | 
			
		||||
  friend bool operator>=(const U& x, const T& y)
 | 
			
		||||
    { return (y < x) || (y == x); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct partially_ordered1 : B
 | 
			
		||||
{
 | 
			
		||||
  friend bool operator>(const T& x, const T& y)
 | 
			
		||||
    { return y < x; }
 | 
			
		||||
  friend bool operator<=(const T& x, const T& y)
 | 
			
		||||
    { return (x < y) || (x == y); }
 | 
			
		||||
  friend bool operator>=(const T& x, const T& y)
 | 
			
		||||
    { return (y < x) || (x == y); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//  Combined operator classes (contributed by Daryle Walker) ----------------//
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct totally_ordered2
 | 
			
		||||
    : less_than_comparable2<T, U
 | 
			
		||||
    , equality_comparable2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct totally_ordered1
 | 
			
		||||
    : less_than_comparable1<T
 | 
			
		||||
    , equality_comparable1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct additive2
 | 
			
		||||
    : addable2<T, U
 | 
			
		||||
    , subtractable2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct additive1
 | 
			
		||||
    : addable1<T
 | 
			
		||||
    , subtractable1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct multiplicative2
 | 
			
		||||
    : multipliable2<T, U
 | 
			
		||||
    , dividable2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct multiplicative1
 | 
			
		||||
    : multipliable1<T
 | 
			
		||||
    , dividable1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct integer_multiplicative2
 | 
			
		||||
    : multiplicative2<T, U
 | 
			
		||||
    , modable2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct integer_multiplicative1
 | 
			
		||||
    : multiplicative1<T
 | 
			
		||||
    , modable1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct arithmetic2
 | 
			
		||||
    : additive2<T, U
 | 
			
		||||
    , multiplicative2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct arithmetic1
 | 
			
		||||
    : additive1<T
 | 
			
		||||
    , multiplicative1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct integer_arithmetic2
 | 
			
		||||
    : additive2<T, U
 | 
			
		||||
    , integer_multiplicative2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct integer_arithmetic1
 | 
			
		||||
    : additive1<T
 | 
			
		||||
    , integer_multiplicative1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct bitwise2
 | 
			
		||||
    : xorable2<T, U
 | 
			
		||||
    , andable2<T, U
 | 
			
		||||
    , orable2<T, U, B
 | 
			
		||||
      > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct bitwise1
 | 
			
		||||
    : xorable1<T
 | 
			
		||||
    , andable1<T
 | 
			
		||||
    , orable1<T, B
 | 
			
		||||
      > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct unit_steppable
 | 
			
		||||
    : incrementable<T
 | 
			
		||||
    , decrementable<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct shiftable2
 | 
			
		||||
    : left_shiftable2<T, U
 | 
			
		||||
    , right_shiftable2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct shiftable1
 | 
			
		||||
    : left_shiftable1<T
 | 
			
		||||
    , right_shiftable1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct ring_operators2
 | 
			
		||||
    : additive2<T, U
 | 
			
		||||
    , subtractable2_left<T, U
 | 
			
		||||
    , multipliable2<T, U, B
 | 
			
		||||
      > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct ring_operators1
 | 
			
		||||
    : additive1<T
 | 
			
		||||
    , multipliable1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct ordered_ring_operators2
 | 
			
		||||
    : ring_operators2<T, U
 | 
			
		||||
    , totally_ordered2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct ordered_ring_operators1
 | 
			
		||||
    : ring_operators1<T
 | 
			
		||||
    , totally_ordered1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct field_operators2
 | 
			
		||||
    : ring_operators2<T, U
 | 
			
		||||
    , dividable2<T, U
 | 
			
		||||
    , dividable2_left<T, U, B
 | 
			
		||||
      > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct field_operators1
 | 
			
		||||
    : ring_operators1<T
 | 
			
		||||
    , dividable1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct ordered_field_operators2
 | 
			
		||||
    : field_operators2<T, U
 | 
			
		||||
    , totally_ordered2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct ordered_field_operators1
 | 
			
		||||
    : field_operators1<T
 | 
			
		||||
    , totally_ordered1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct euclidian_ring_operators2
 | 
			
		||||
    : ring_operators2<T, U
 | 
			
		||||
    , dividable2<T, U
 | 
			
		||||
    , dividable2_left<T, U
 | 
			
		||||
    , modable2<T, U
 | 
			
		||||
    , modable2_left<T, U, B
 | 
			
		||||
      > > > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct euclidian_ring_operators1
 | 
			
		||||
    : ring_operators1<T
 | 
			
		||||
    , dividable1<T
 | 
			
		||||
    , modable1<T, B
 | 
			
		||||
      > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class U, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct ordered_euclidian_ring_operators2
 | 
			
		||||
    : totally_ordered2<T, U
 | 
			
		||||
    , euclidian_ring_operators2<T, U, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct ordered_euclidian_ring_operators1
 | 
			
		||||
    : totally_ordered1<T
 | 
			
		||||
    , euclidian_ring_operators1<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
      
 | 
			
		||||
template <class T, class P, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct input_iteratable
 | 
			
		||||
    : equality_comparable1<T
 | 
			
		||||
    , incrementable<T
 | 
			
		||||
    , dereferenceable<T, P, B
 | 
			
		||||
      > > > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct output_iteratable
 | 
			
		||||
    : incrementable<T, B
 | 
			
		||||
      > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class P, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct forward_iteratable
 | 
			
		||||
    : input_iteratable<T, P, B
 | 
			
		||||
      > {};
 | 
			
		||||
 | 
			
		||||
template <class T, class P, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct bidirectional_iteratable
 | 
			
		||||
    : forward_iteratable<T, P
 | 
			
		||||
    , decrementable<T, B
 | 
			
		||||
      > > {};
 | 
			
		||||
 | 
			
		||||
//  To avoid repeated derivation from equality_comparable,
 | 
			
		||||
//  which is an indirect base class of bidirectional_iterable,
 | 
			
		||||
//  random_access_iteratable must not be derived from totally_ordered1
 | 
			
		||||
//  but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
 | 
			
		||||
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base>
 | 
			
		||||
struct random_access_iteratable
 | 
			
		||||
    : bidirectional_iteratable<T, P
 | 
			
		||||
    , less_than_comparable1<T
 | 
			
		||||
    , additive2<T, D
 | 
			
		||||
    , indexable<T, D, R, B
 | 
			
		||||
      > > > > {};
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
} // namespace boost
 | 
			
		||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 -
 | 
			
		||||
//
 | 
			
		||||
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
 | 
			
		||||
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
 | 
			
		||||
// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for
 | 
			
		||||
// two-argument forms. Note that these macros expect to be invoked from within
 | 
			
		||||
// boost.
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
  // The template is already in boost so we have nothing to do.
 | 
			
		||||
# define BOOST_IMPORT_TEMPLATE4(template_name)
 | 
			
		||||
# define BOOST_IMPORT_TEMPLATE3(template_name)
 | 
			
		||||
# define BOOST_IMPORT_TEMPLATE2(template_name)
 | 
			
		||||
# define BOOST_IMPORT_TEMPLATE1(template_name)
 | 
			
		||||
 | 
			
		||||
#else // BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#  ifndef BOOST_NO_USING_TEMPLATE
 | 
			
		||||
 | 
			
		||||
     // Bring the names in with a using-declaration
 | 
			
		||||
     // to avoid stressing the compiler.
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name;
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
 | 
			
		||||
 | 
			
		||||
#  else
 | 
			
		||||
 | 
			
		||||
     // Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
 | 
			
		||||
     // from working, we are forced to use inheritance for that compiler.
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE4(template_name)                                          \
 | 
			
		||||
     template <class T, class U, class V, class W, class B = ::boost::detail::empty_base>  \
 | 
			
		||||
     struct template_name : ::template_name<T, U, V, W, B> {};
 | 
			
		||||
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE3(template_name)                                 \
 | 
			
		||||
     template <class T, class U, class V, class B = ::boost::detail::empty_base>  \
 | 
			
		||||
     struct template_name : ::template_name<T, U, V, B> {};
 | 
			
		||||
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE2(template_name)                              \
 | 
			
		||||
     template <class T, class U, class B = ::boost::detail::empty_base>        \
 | 
			
		||||
     struct template_name : ::template_name<T, U, B> {};
 | 
			
		||||
 | 
			
		||||
#    define BOOST_IMPORT_TEMPLATE1(template_name)                              \
 | 
			
		||||
     template <class T, class B = ::boost::detail::empty_base>                 \
 | 
			
		||||
     struct template_name : ::template_name<T, B> {};
 | 
			
		||||
 | 
			
		||||
#  endif // BOOST_NO_USING_TEMPLATE
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Here's where we put it all together, defining the xxxx forms of the templates
 | 
			
		||||
// in namespace boost. We also define specializations of is_chained_base<> for
 | 
			
		||||
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
 | 
			
		||||
// neccessary.
 | 
			
		||||
//
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
 | 
			
		||||
// is_chained_base<> - a traits class used to distinguish whether an operator
 | 
			
		||||
// template argument is being used for base class chaining, or is specifying a
 | 
			
		||||
// 2nd argument type.
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
// A type parameter is used instead of a plain bool because Borland's compiler
 | 
			
		||||
// didn't cope well with the more obvious non-type template parameter.
 | 
			
		||||
namespace detail {
 | 
			
		||||
  struct true_t {};
 | 
			
		||||
  struct false_t {};
 | 
			
		||||
} // namespace detail
 | 
			
		||||
 | 
			
		||||
// Unspecialized version assumes that most types are not being used for base
 | 
			
		||||
// class chaining. We specialize for the operator templates defined in this
 | 
			
		||||
// library.
 | 
			
		||||
template<class T> struct is_chained_base {
 | 
			
		||||
  typedef ::boost::detail::false_t value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
// Import a 4-type-argument operator template into boost (if neccessary) and
 | 
			
		||||
// provide a specialization of 'is_chained_base<>' for it.
 | 
			
		||||
# define BOOST_OPERATOR_TEMPLATE4(template_name4)                     \
 | 
			
		||||
  BOOST_IMPORT_TEMPLATE4(template_name4)                              \
 | 
			
		||||
  template<class T, class U, class V, class W, class B>               \
 | 
			
		||||
  struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > {  \
 | 
			
		||||
    typedef ::boost::detail::true_t value;                            \
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
// Import a 3-type-argument operator template into boost (if neccessary) and
 | 
			
		||||
// provide a specialization of 'is_chained_base<>' for it.
 | 
			
		||||
# define BOOST_OPERATOR_TEMPLATE3(template_name3)                     \
 | 
			
		||||
  BOOST_IMPORT_TEMPLATE3(template_name3)                              \
 | 
			
		||||
  template<class T, class U, class V, class B>                        \
 | 
			
		||||
  struct is_chained_base< ::boost::template_name3<T, U, V, B> > {     \
 | 
			
		||||
    typedef ::boost::detail::true_t value;                            \
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
// Import a 2-type-argument operator template into boost (if neccessary) and
 | 
			
		||||
// provide a specialization of 'is_chained_base<>' for it.
 | 
			
		||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2)                  \
 | 
			
		||||
  BOOST_IMPORT_TEMPLATE2(template_name2)                           \
 | 
			
		||||
  template<class T, class U, class B>                              \
 | 
			
		||||
  struct is_chained_base< ::boost::template_name2<T, U, B> > {     \
 | 
			
		||||
    typedef ::boost::detail::true_t value;                         \
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
// Import a 1-type-argument operator template into boost (if neccessary) and
 | 
			
		||||
// provide a specialization of 'is_chained_base<>' for it.
 | 
			
		||||
# define BOOST_OPERATOR_TEMPLATE1(template_name1)                  \
 | 
			
		||||
  BOOST_IMPORT_TEMPLATE1(template_name1)                           \
 | 
			
		||||
  template<class T, class B>                                       \
 | 
			
		||||
  struct is_chained_base< ::boost::template_name1<T, B> > {        \
 | 
			
		||||
    typedef ::boost::detail::true_t value;                         \
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
 | 
			
		||||
// can be used for specifying both 1-argument and 2-argument forms. Requires the
 | 
			
		||||
// existence of two previously defined class templates named '<template_name>1'
 | 
			
		||||
// and '<template_name>2' which must implement the corresponding 1- and 2-
 | 
			
		||||
// argument forms.
 | 
			
		||||
//
 | 
			
		||||
// The template type parameter O == is_chained_base<U>::value is used to
 | 
			
		||||
// distinguish whether the 2nd argument to <template_name> is being used for
 | 
			
		||||
// base class chaining from another boost operator template or is describing a
 | 
			
		||||
// 2nd operand type. O == true_t only when U is actually an another operator
 | 
			
		||||
// template from the library. Partial specialization is used to select an
 | 
			
		||||
// implementation in terms of either '<template_name>1' or '<template_name>2'.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
# define BOOST_OPERATOR_TEMPLATE(template_name)                    \
 | 
			
		||||
template <class T                                                  \
 | 
			
		||||
         ,class U = T                                              \
 | 
			
		||||
         ,class B = ::boost::detail::empty_base                    \
 | 
			
		||||
         ,class O = typename is_chained_base<U>::value             \
 | 
			
		||||
         >                                                         \
 | 
			
		||||
struct template_name : template_name##2<T, U, B> {};               \
 | 
			
		||||
                                                                   \
 | 
			
		||||
template<class T, class U, class B>                                \
 | 
			
		||||
struct template_name<T, U, B, ::boost::detail::true_t>             \
 | 
			
		||||
  : template_name##1<T, U> {};                                     \
 | 
			
		||||
                                                                   \
 | 
			
		||||
template <class T, class B>                                        \
 | 
			
		||||
struct template_name<T, T, B, ::boost::detail::false_t>            \
 | 
			
		||||
  : template_name##1<T, B> {};                                     \
 | 
			
		||||
                                                                   \
 | 
			
		||||
template<class T, class U, class B, class O>                       \
 | 
			
		||||
struct is_chained_base< ::boost::template_name<T, U, B, O> > {     \
 | 
			
		||||
  typedef ::boost::detail::true_t value;                           \
 | 
			
		||||
};                                                                 \
 | 
			
		||||
                                                                   \
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE2(template_name##2)                         \
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE1(template_name##1)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
 | 
			
		||||
#  define BOOST_OPERATOR_TEMPLATE4(template_name4) \
 | 
			
		||||
        BOOST_IMPORT_TEMPLATE4(template_name4)
 | 
			
		||||
#  define BOOST_OPERATOR_TEMPLATE3(template_name3) \
 | 
			
		||||
        BOOST_IMPORT_TEMPLATE3(template_name3)
 | 
			
		||||
#  define BOOST_OPERATOR_TEMPLATE2(template_name2) \
 | 
			
		||||
        BOOST_IMPORT_TEMPLATE2(template_name2)
 | 
			
		||||
#  define BOOST_OPERATOR_TEMPLATE1(template_name1) \
 | 
			
		||||
        BOOST_IMPORT_TEMPLATE1(template_name1)
 | 
			
		||||
 | 
			
		||||
   // In this case we can only assume that template_name<> is equivalent to the
 | 
			
		||||
   // more commonly needed template_name1<> form.
 | 
			
		||||
#  define BOOST_OPERATOR_TEMPLATE(template_name)                   \
 | 
			
		||||
   template <class T, class B = ::boost::detail::empty_base>       \
 | 
			
		||||
   struct template_name : template_name##1<T, B> {};
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
    
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(less_than_comparable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(equality_comparable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(multipliable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(addable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(subtractable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(dividable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE2(dividable2_left)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(modable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE2(modable2_left)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(xorable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(andable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(orable)
 | 
			
		||||
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE1(incrementable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE1(decrementable)
 | 
			
		||||
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE3(indexable)
 | 
			
		||||
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(left_shiftable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(right_shiftable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(equivalent)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(partially_ordered)
 | 
			
		||||
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(totally_ordered)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(additive)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(multiplicative)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(arithmetic)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(bitwise)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE1(unit_steppable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(shiftable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(ring_operators)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(field_operators)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE2(input_iteratable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE1(output_iteratable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
 | 
			
		||||
BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
 | 
			
		||||
 | 
			
		||||
#undef BOOST_OPERATOR_TEMPLATE
 | 
			
		||||
#undef BOOST_OPERATOR_TEMPLATE4
 | 
			
		||||
#undef BOOST_OPERATOR_TEMPLATE3
 | 
			
		||||
#undef BOOST_OPERATOR_TEMPLATE2
 | 
			
		||||
#undef BOOST_OPERATOR_TEMPLATE1
 | 
			
		||||
#undef BOOST_IMPORT_TEMPLATE1
 | 
			
		||||
#undef BOOST_IMPORT_TEMPLATE2
 | 
			
		||||
#undef BOOST_IMPORT_TEMPLATE3
 | 
			
		||||
#undef BOOST_IMPORT_TEMPLATE4
 | 
			
		||||
 | 
			
		||||
// The following 'operators' classes can only be used portably if the derived class
 | 
			
		||||
// declares ALL of the required member operators.
 | 
			
		||||
template <class T, class U>
 | 
			
		||||
struct operators2
 | 
			
		||||
    : totally_ordered2<T,U
 | 
			
		||||
    , integer_arithmetic2<T,U
 | 
			
		||||
    , bitwise2<T,U
 | 
			
		||||
      > > > {};
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
template <class T, class U = T>
 | 
			
		||||
struct operators : operators2<T, U> {};
 | 
			
		||||
 | 
			
		||||
template <class T> struct operators<T, T>
 | 
			
		||||
#else
 | 
			
		||||
template <class T> struct operators
 | 
			
		||||
#endif
 | 
			
		||||
    : totally_ordered<T
 | 
			
		||||
    , integer_arithmetic<T
 | 
			
		||||
    , bitwise<T
 | 
			
		||||
    , unit_steppable<T
 | 
			
		||||
      > > > > {};
 | 
			
		||||
 | 
			
		||||
//  Iterator helper classes (contributed by Jeremy Siek) -------------------//
 | 
			
		||||
//  (Input and output iterator helpers contributed by Daryle Walker) -------//
 | 
			
		||||
//  (Changed to use combined operator classes by Daryle Walker) ------------//
 | 
			
		||||
template <class T,
 | 
			
		||||
          class V,
 | 
			
		||||
          class D = std::ptrdiff_t,
 | 
			
		||||
          class P = V const *,
 | 
			
		||||
          class R = V const &>
 | 
			
		||||
struct input_iterator_helper
 | 
			
		||||
  : input_iteratable<T, P
 | 
			
		||||
  , boost::iterator<std::input_iterator_tag, V, D, P, R
 | 
			
		||||
    > > {};
 | 
			
		||||
 | 
			
		||||
template<class T>
 | 
			
		||||
struct output_iterator_helper
 | 
			
		||||
  : output_iteratable<T
 | 
			
		||||
  , boost::iterator<std::output_iterator_tag, void, void, void, void
 | 
			
		||||
  > >
 | 
			
		||||
{
 | 
			
		||||
  T& operator*()  { return static_cast<T&>(*this); }
 | 
			
		||||
  T& operator++() { return static_cast<T&>(*this); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T,
 | 
			
		||||
          class V,
 | 
			
		||||
          class D = std::ptrdiff_t,
 | 
			
		||||
          class P = V*,
 | 
			
		||||
          class R = V&>
 | 
			
		||||
struct forward_iterator_helper
 | 
			
		||||
  : forward_iteratable<T, P
 | 
			
		||||
  , boost::iterator<std::forward_iterator_tag, V, D, P, R
 | 
			
		||||
    > > {};
 | 
			
		||||
 | 
			
		||||
template <class T,
 | 
			
		||||
          class V,
 | 
			
		||||
          class D = std::ptrdiff_t,
 | 
			
		||||
          class P = V*,
 | 
			
		||||
          class R = V&>
 | 
			
		||||
struct bidirectional_iterator_helper
 | 
			
		||||
  : bidirectional_iteratable<T, P
 | 
			
		||||
  , boost::iterator<std::bidirectional_iterator_tag, V, D, P, R
 | 
			
		||||
    > > {};
 | 
			
		||||
 | 
			
		||||
template <class T,
 | 
			
		||||
          class V, 
 | 
			
		||||
          class D = std::ptrdiff_t,
 | 
			
		||||
          class P = V*,
 | 
			
		||||
          class R = V&>
 | 
			
		||||
struct random_access_iterator_helper
 | 
			
		||||
  : random_access_iteratable<T, P, D, R
 | 
			
		||||
  , boost::iterator<std::random_access_iterator_tag, V, D, P, R
 | 
			
		||||
    > >
 | 
			
		||||
{
 | 
			
		||||
  friend D requires_difference_operator(const T& x, const T& y) {
 | 
			
		||||
    return x - y;
 | 
			
		||||
  }
 | 
			
		||||
}; // random_access_iterator_helper
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#if defined(__sgi) && !defined(__GNUC__)
 | 
			
		||||
#pragma reset woff 1234
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_OPERATORS_HPP
 | 
			
		||||
							
								
								
									
										165
									
								
								include/boost/ref.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								include/boost/ref.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
#ifndef BOOST_REF_HPP_INCLUDED
 | 
			
		||||
#define BOOST_REF_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
// MS compatible compilers support #pragma once
 | 
			
		||||
 | 
			
		||||
#if defined(_MSC_VER) && (_MSC_VER >= 1020)
 | 
			
		||||
# pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <boost/utility/addressof.hpp>
 | 
			
		||||
#include <boost/mpl/bool.hpp>
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  ref.hpp - ref/cref, useful helper functions
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (C) 1999, 2000 Jaakko J<>rvi (jaakko.jarvi@cs.utu.fi)
 | 
			
		||||
//  Copyright (C) 2001, 2002 Peter Dimov
 | 
			
		||||
//  Copyright (C) 2002 David Abrahams
 | 
			
		||||
//
 | 
			
		||||
//  Permission to copy, use, modify, sell and distribute this software
 | 
			
		||||
//  is granted provided this copyright notice appears in all copies.
 | 
			
		||||
//  This software is provided "as is" without express or implied
 | 
			
		||||
//  warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
//
 | 
			
		||||
//  See http://www.boost.org/libs/bind/ref.html for documentation.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
template<class T> class reference_wrapper
 | 
			
		||||
{ 
 | 
			
		||||
public:
 | 
			
		||||
    typedef T type;
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
 | 
			
		||||
 | 
			
		||||
    explicit reference_wrapper(T& t): t_(&t) {}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
    explicit reference_wrapper(T& t): t_(boost::addressof(t)) {}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    operator T& () const { return *t_; }
 | 
			
		||||
 | 
			
		||||
    T& get() const { return *t_; }
 | 
			
		||||
 | 
			
		||||
    T* get_pointer() const { return t_; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    T* t_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x570)
 | 
			
		||||
#  define BOOST_REF_CONST
 | 
			
		||||
# else
 | 
			
		||||
#  define BOOST_REF_CONST const
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
template<class T> inline reference_wrapper<T> BOOST_REF_CONST ref(T & t)
 | 
			
		||||
{ 
 | 
			
		||||
    return reference_wrapper<T>(t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline reference_wrapper<T const> BOOST_REF_CONST cref(T const & t)
 | 
			
		||||
{
 | 
			
		||||
    return reference_wrapper<T const>(t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
# undef BOOST_REF_CONST
 | 
			
		||||
 | 
			
		||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
template<typename T>
 | 
			
		||||
class is_reference_wrapper
 | 
			
		||||
    : public mpl::false_
 | 
			
		||||
{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
class is_reference_wrapper<reference_wrapper<T> >
 | 
			
		||||
    : public mpl::true_
 | 
			
		||||
{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
class unwrap_reference
 | 
			
		||||
{
 | 
			
		||||
 public:
 | 
			
		||||
    typedef T type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
class unwrap_reference<reference_wrapper<T> >
 | 
			
		||||
{
 | 
			
		||||
 public:
 | 
			
		||||
    typedef T type;
 | 
			
		||||
};
 | 
			
		||||
# else // no partial specialization
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#include <boost/type.hpp>
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
namespace detail
 | 
			
		||||
{
 | 
			
		||||
  typedef char (&yes_reference_wrapper_t)[1];
 | 
			
		||||
  typedef char (&no_reference_wrapper_t)[2];
 | 
			
		||||
      
 | 
			
		||||
  no_reference_wrapper_t is_reference_wrapper_test(...);
 | 
			
		||||
 | 
			
		||||
  template<typename T>
 | 
			
		||||
  yes_reference_wrapper_t is_reference_wrapper_test(type< reference_wrapper<T> >);
 | 
			
		||||
 | 
			
		||||
  template<bool wrapped>
 | 
			
		||||
  struct reference_unwrapper
 | 
			
		||||
  {
 | 
			
		||||
      template <class T>
 | 
			
		||||
      struct apply
 | 
			
		||||
      {
 | 
			
		||||
          typedef T type;
 | 
			
		||||
      };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template<>
 | 
			
		||||
  struct reference_unwrapper<true>
 | 
			
		||||
  {
 | 
			
		||||
      template <class T>
 | 
			
		||||
      struct apply
 | 
			
		||||
      {
 | 
			
		||||
          typedef typename T::type type;
 | 
			
		||||
      };
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
class is_reference_wrapper
 | 
			
		||||
{
 | 
			
		||||
 public:
 | 
			
		||||
    BOOST_STATIC_CONSTANT(
 | 
			
		||||
        bool, value = (
 | 
			
		||||
             sizeof(detail::is_reference_wrapper_test(type<T>()))
 | 
			
		||||
            == sizeof(detail::yes_reference_wrapper_t)));
 | 
			
		||||
    
 | 
			
		||||
    typedef ::boost::mpl::bool_<value> type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
class unwrap_reference
 | 
			
		||||
    : public detail::reference_unwrapper<
 | 
			
		||||
        is_reference_wrapper<T>::value
 | 
			
		||||
      >::template apply<T>
 | 
			
		||||
{};
 | 
			
		||||
 | 
			
		||||
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef BOOST_REF_HPP_INCLUDED
 | 
			
		||||
							
								
								
									
										18
									
								
								include/boost/utility.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								include/boost/utility.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
//  Boost utility.hpp header file  -------------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  Copyright 1999-2003 Boost.org.  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.
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_UTILITY_HPP
 | 
			
		||||
#define BOOST_UTILITY_HPP
 | 
			
		||||
 | 
			
		||||
#include <boost/utility/addressof.hpp>
 | 
			
		||||
#include <boost/utility/base_from_member.hpp>  
 | 
			
		||||
#include <boost/checked_delete.hpp>
 | 
			
		||||
#include <boost/next_prior.hpp>
 | 
			
		||||
#include <boost/noncopyable.hpp>
 | 
			
		||||
 | 
			
		||||
#endif  // BOOST_UTILITY_HPP
 | 
			
		||||
							
								
								
									
										43
									
								
								include/boost/utility/addressof.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								include/boost/utility/addressof.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
// Copyright (C) 2002 Brad King (brad.king@kitware.com) 
 | 
			
		||||
//                    Doug Gregor (gregod@cs.rpi.edu)
 | 
			
		||||
//                    Peter Dimov
 | 
			
		||||
//
 | 
			
		||||
// Permission to copy, use, sell and distribute this software is granted
 | 
			
		||||
// provided this copyright notice appears in all copies.
 | 
			
		||||
// Permission to modify the code and to distribute modified code is granted
 | 
			
		||||
// provided this copyright notice appears in all copies, and a notice
 | 
			
		||||
// that the code was modified is included with the copyright notice.
 | 
			
		||||
//
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_UTILITY_ADDRESSOF_HPP
 | 
			
		||||
# define BOOST_UTILITY_ADDRESSOF_HPP
 | 
			
		||||
 | 
			
		||||
# include <boost/config.hpp>
 | 
			
		||||
# include <boost/detail/workaround.hpp>
 | 
			
		||||
# if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
 | 
			
		||||
#  include <boost/type_traits/add_pointer.hpp>
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
// Do not make addressof() inline. Breaks MSVC 7. (Peter Dimov)
 | 
			
		||||
 | 
			
		||||
// VC7 strips const from nested classes unless we add indirection here
 | 
			
		||||
# if BOOST_WORKAROUND(BOOST_MSVC, == 1300)
 | 
			
		||||
template <typename T> typename add_pointer<T>::type
 | 
			
		||||
# else
 | 
			
		||||
template <typename T> T*
 | 
			
		||||
# endif
 | 
			
		||||
addressof(T& v)
 | 
			
		||||
{
 | 
			
		||||
  return reinterpret_cast<T*>(
 | 
			
		||||
       &const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_UTILITY_ADDRESSOF_HPP
 | 
			
		||||
							
								
								
									
										99
									
								
								include/boost/utility/base_from_member.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								include/boost/utility/base_from_member.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
			
		||||
//  boost utility/base_from_member.hpp header file  --------------------------//
 | 
			
		||||
 | 
			
		||||
//  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.
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_UTILITY_BASE_FROM_MEMBER_HPP
 | 
			
		||||
#define BOOST_UTILITY_BASE_FROM_MEMBER_HPP
 | 
			
		||||
 | 
			
		||||
#include <boost/utility_fwd.hpp>  // required for parameter defaults
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
//  Base-from-member class template  -----------------------------------------//
 | 
			
		||||
 | 
			
		||||
// Helper to initialize a base object so a derived class can use this
 | 
			
		||||
// object in the initialization of another base class.  Used by
 | 
			
		||||
// Dietmar Kuehl from ideas by Ron Klatcho to solve the problem of a
 | 
			
		||||
// base class needing to be initialized by a member.
 | 
			
		||||
 | 
			
		||||
// Contributed by Daryle Walker
 | 
			
		||||
 | 
			
		||||
template < typename MemberType, int UniqueID >
 | 
			
		||||
class base_from_member
 | 
			
		||||
{
 | 
			
		||||
protected:
 | 
			
		||||
    MemberType  member;
 | 
			
		||||
 | 
			
		||||
    base_from_member()
 | 
			
		||||
        : member()
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
    template< typename T1 >
 | 
			
		||||
    explicit base_from_member( T1 x1 )
 | 
			
		||||
        : member( x1 )
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
    template< typename T1, typename T2 >
 | 
			
		||||
    base_from_member( T1 x1, T2 x2 )
 | 
			
		||||
        : member( x1, x2 )
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
    template< typename T1, typename T2, typename T3 >
 | 
			
		||||
    base_from_member( T1 x1, T2 x2, T3 x3 )
 | 
			
		||||
        : member( x1, x2, x3 ) 
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
    template< typename T1, typename T2, typename T3, typename T4 >
 | 
			
		||||
    base_from_member( T1 x1, T2 x2, T3 x3, T4 x4 )
 | 
			
		||||
        : member( x1, x2, x3, x4 ) 
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
    template< typename T1, typename T2, typename T3, typename T4, typename T5 >
 | 
			
		||||
    base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5 )
 | 
			
		||||
        : member( x1, x2, x3, x4, x5 ) 
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
    template< typename T1, typename T2, typename T3, typename T4, typename T5,
 | 
			
		||||
     typename T6 >
 | 
			
		||||
    base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6 )
 | 
			
		||||
        : member( x1, x2, x3, x4, x5, x6 ) 
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
    template< typename T1, typename T2, typename T3, typename T4, typename T5,
 | 
			
		||||
     typename T6, typename T7 >
 | 
			
		||||
    base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7 )
 | 
			
		||||
        : member( x1, x2, x3, x4, x5, x6, x7 ) 
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
    template< typename T1, typename T2, typename T3, typename T4, typename T5,
 | 
			
		||||
     typename T6, typename T7, typename T8 >
 | 
			
		||||
    base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, T8 x8 )
 | 
			
		||||
        : member( x1, x2, x3, x4, x5, x6, x7, x8 ) 
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
    template< typename T1, typename T2, typename T3, typename T4, typename T5,
 | 
			
		||||
     typename T6, typename T7, typename T8, typename T9 >
 | 
			
		||||
    base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7, T8 x8,
 | 
			
		||||
     T9 x9 )
 | 
			
		||||
        : member( x1, x2, x3, x4, x5, x6, x7, x8, x9 ) 
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
    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 )
 | 
			
		||||
        : member( x1, x2, x3, x4, x5, x6, x7, x8, x9, x10 ) 
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
};  // boost::base_from_member
 | 
			
		||||
 | 
			
		||||
}  // namespace boost
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif  // BOOST_UTILITY_BASE_FROM_MEMBER_HPP
 | 
			
		||||
							
								
								
									
										68
									
								
								include/boost/utility/compare_pointees.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								include/boost/utility/compare_pointees.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
// Copyright (C) 2003, Fernando Luis Cacciola Carballal.
 | 
			
		||||
//
 | 
			
		||||
// 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)
 | 
			
		||||
//
 | 
			
		||||
// See http://www.boost.org/lib/optional for documentation.
 | 
			
		||||
//
 | 
			
		||||
// You are welcome to contact the author at:
 | 
			
		||||
//  fernando_cacciola@hotmail.com
 | 
			
		||||
//
 | 
			
		||||
#ifndef BOOST_UTILITY_COMPARE_POINTEES_25AGO2003_HPP
 | 
			
		||||
#define BOOST_UTILITY_COMPARE_POINTEES_25AGO2003_HPP
 | 
			
		||||
 | 
			
		||||
#include<functional>
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
// template<class OP> bool equal_pointees(OP const& x, OP const& y);
 | 
			
		||||
// template<class OP> struct equal_pointees_t;
 | 
			
		||||
//
 | 
			
		||||
// Being OP a model of OptionalPointee (either a pointer or an optional):
 | 
			
		||||
//
 | 
			
		||||
// If both x and y have valid pointees, returns the result of (*x == *y)
 | 
			
		||||
// If only one has a valid pointee, returns false.
 | 
			
		||||
// If none have valid pointees, returns true.
 | 
			
		||||
// No-throw
 | 
			
		||||
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) ; }
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
// template<class OP> bool less_pointees(OP const& x, OP const& y);
 | 
			
		||||
// template<class OP> struct less_pointees_t;
 | 
			
		||||
//
 | 
			
		||||
// Being OP a model of OptionalPointee (either a pointer or an optional):
 | 
			
		||||
//
 | 
			
		||||
// If y has not a valid pointee, returns false.
 | 
			
		||||
// ElseIf x has not a valid pointee, returns true.
 | 
			
		||||
// ElseIf both x and y have valid pointees, returns the result of (*x < *y)
 | 
			
		||||
// No-throw
 | 
			
		||||
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) ; }
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										119
									
								
								include/boost/utility/enable_if.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								include/boost/utility/enable_if.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
// 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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_UTILITY_ENABLE_IF_HPP
 | 
			
		||||
#define BOOST_UTILITY_ENABLE_IF_HPP
 | 
			
		||||
 | 
			
		||||
#include "boost/config.hpp"
 | 
			
		||||
 | 
			
		||||
// Even the definition of enable_if causes problems on some compilers,
 | 
			
		||||
// so it's macroed out for all compilers that do not support SFINAE
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_SFINAE
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
  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> {};
 | 
			
		||||
 | 
			
		||||
  template <bool B, class T>
 | 
			
		||||
  struct lazy_enable_if_c {
 | 
			
		||||
    typedef typename T::type type;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template <class T>
 | 
			
		||||
  struct lazy_enable_if_c<false, T> {};
 | 
			
		||||
 | 
			
		||||
  template <class Cond, class T> 
 | 
			
		||||
  struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  template <bool B, class T = void>
 | 
			
		||||
  struct disable_if_c {
 | 
			
		||||
    typedef T type;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template <class T>
 | 
			
		||||
  struct disable_if_c<true, T> {};
 | 
			
		||||
 | 
			
		||||
  template <class Cond, class T = void> 
 | 
			
		||||
  struct disable_if : public disable_if_c<Cond::value, T> {};
 | 
			
		||||
 | 
			
		||||
  template <bool B, class T>
 | 
			
		||||
  struct lazy_disable_if_c {
 | 
			
		||||
    typedef typename T::type type;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template <class T>
 | 
			
		||||
  struct lazy_disable_if_c<true, T> {};
 | 
			
		||||
 | 
			
		||||
  template <class Cond, class T> 
 | 
			
		||||
  struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
  namespace detail { typedef void enable_if_default_T; }
 | 
			
		||||
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  struct enable_if_does_not_work_on_this_compiler;
 | 
			
		||||
 | 
			
		||||
  template <bool B, class T = detail::enable_if_default_T>
 | 
			
		||||
  struct enable_if_c : enable_if_does_not_work_on_this_compiler<T>
 | 
			
		||||
  { };
 | 
			
		||||
 | 
			
		||||
  template <bool B, class T = detail::enable_if_default_T> 
 | 
			
		||||
  struct disable_if_c : enable_if_does_not_work_on_this_compiler<T>
 | 
			
		||||
  { };
 | 
			
		||||
 | 
			
		||||
  template <bool B, class T = detail::enable_if_default_T> 
 | 
			
		||||
  struct lazy_enable_if_c : enable_if_does_not_work_on_this_compiler<T>
 | 
			
		||||
  { };
 | 
			
		||||
 | 
			
		||||
  template <bool B, class T = detail::enable_if_default_T> 
 | 
			
		||||
  struct lazy_disable_if_c : enable_if_does_not_work_on_this_compiler<T>
 | 
			
		||||
  { };
 | 
			
		||||
 | 
			
		||||
  template <class Cond, class T = detail::enable_if_default_T> 
 | 
			
		||||
  struct enable_if : enable_if_does_not_work_on_this_compiler<T>
 | 
			
		||||
  { };
 | 
			
		||||
 | 
			
		||||
  template <class Cond, class T = detail::enable_if_default_T> 
 | 
			
		||||
  struct disable_if : enable_if_does_not_work_on_this_compiler<T>
 | 
			
		||||
  { };
 | 
			
		||||
 | 
			
		||||
  template <class Cond, class T = detail::enable_if_default_T> 
 | 
			
		||||
  struct lazy_enable_if : enable_if_does_not_work_on_this_compiler<T>
 | 
			
		||||
  { };
 | 
			
		||||
 | 
			
		||||
  template <class Cond, class T = detail::enable_if_default_T> 
 | 
			
		||||
  struct lazy_disable_if : enable_if_does_not_work_on_this_compiler<T>
 | 
			
		||||
  { };
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif // BOOST_NO_SFINAE
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										82
									
								
								include/boost/utility/value_init.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								include/boost/utility/value_init.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,82 @@
 | 
			
		||||
// (C) 2002, Fernando Luis Cacciola Carballal.
 | 
			
		||||
//
 | 
			
		||||
// This material is provided "as is", with absolutely no warranty expressed
 | 
			
		||||
// or implied. Any use is at your own risk.
 | 
			
		||||
//
 | 
			
		||||
// Permission to use or copy this software for any purpose is hereby granted
 | 
			
		||||
// without fee, provided the above notices are retained on all copies.
 | 
			
		||||
// Permission to modify the code and to distribute modified code is granted,
 | 
			
		||||
// provided the above notices are retained, and a notice that the code was
 | 
			
		||||
// modified is included with the above copyright notice.
 | 
			
		||||
//
 | 
			
		||||
// 21 Ago 2002 (Created) Fernando Cacciola
 | 
			
		||||
//
 | 
			
		||||
#ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
 | 
			
		||||
#define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP
 | 
			
		||||
 | 
			
		||||
#include "boost/detail/select_type.hpp"
 | 
			
		||||
#include "boost/type_traits/cv_traits.hpp"
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
namespace vinit_detail {
 | 
			
		||||
 | 
			
		||||
template<class T>
 | 
			
		||||
class const_T_base
 | 
			
		||||
{
 | 
			
		||||
  protected :
 | 
			
		||||
 | 
			
		||||
   const_T_base() : x() {}
 | 
			
		||||
 | 
			
		||||
   T x ;
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
template<class T>
 | 
			
		||||
struct non_const_T_base
 | 
			
		||||
{
 | 
			
		||||
  protected :
 | 
			
		||||
 | 
			
		||||
   non_const_T_base() : x() {}
 | 
			
		||||
 | 
			
		||||
   mutable T x ;
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
template<class T>
 | 
			
		||||
struct select_base
 | 
			
		||||
{
 | 
			
		||||
  typedef typename
 | 
			
		||||
    detail::if_true< ::boost::is_const<T>::value >
 | 
			
		||||
      ::template then< const_T_base<T>, non_const_T_base<T> >::type type ;
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
} // namespace vinit_detail
 | 
			
		||||
 | 
			
		||||
template<class T>
 | 
			
		||||
class value_initialized : private vinit_detail::select_base<T>::type
 | 
			
		||||
{
 | 
			
		||||
  public :
 | 
			
		||||
 | 
			
		||||
    value_initialized() {}
 | 
			
		||||
 | 
			
		||||
    operator T&() const { return this->x ; }
 | 
			
		||||
 | 
			
		||||
    T& data() const { return this->x ; }
 | 
			
		||||
 | 
			
		||||
} ;
 | 
			
		||||
 | 
			
		||||
template<class T>
 | 
			
		||||
T const& get ( value_initialized<T> const& x )
 | 
			
		||||
{
 | 
			
		||||
  return x.data() ;
 | 
			
		||||
}
 | 
			
		||||
template<class T>
 | 
			
		||||
T& get ( value_initialized<T>& x )
 | 
			
		||||
{
 | 
			
		||||
  return x.data() ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										33
									
								
								include/boost/utility_fwd.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								include/boost/utility_fwd.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
//  Boost utility_fwd.hpp header file  ---------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  Copyright 2001, 2003 Boost.org.  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.
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_UTILITY_FWD_HPP
 | 
			
		||||
#define BOOST_UTILITY_FWD_HPP
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
namespace boost
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//  From <boost/utility/base_from_member.hpp>  -------------------------------//
 | 
			
		||||
 | 
			
		||||
template < typename MemberType, int UniqueID = 0 >
 | 
			
		||||
    class base_from_member;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//  From <boost/noncopyable.hpp>  --------------------------------------------//
 | 
			
		||||
 | 
			
		||||
class noncopyable;
 | 
			
		||||
 | 
			
		||||
// Also has a few function templates
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}  // namespace boost
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif  // BOOST_UTILITY_FWD_HPP
 | 
			
		||||
							
								
								
									
										34
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								index.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
			
		||||
<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="../../c++boost.gif" 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>
 | 
			
		||||
							
								
								
									
										59
									
								
								indirect_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								indirect_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <boost/iterator/indirect_iterator.hpp>
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  char characters[] = "abcdefg";
 | 
			
		||||
  const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
 | 
			
		||||
  char* pointers_to_chars[N];                        // at the end.
 | 
			
		||||
  for (int i = 0; i < N; ++i)
 | 
			
		||||
    pointers_to_chars[i] = &characters[i];
 | 
			
		||||
 | 
			
		||||
  // Example of using indirect_iterator_generator
 | 
			
		||||
  
 | 
			
		||||
  boost::indirect_iterator<char**, char>
 | 
			
		||||
    indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
 | 
			
		||||
 | 
			
		||||
  std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  // Example of using indirect_iterator_pair_generator
 | 
			
		||||
 | 
			
		||||
  char mutable_characters[N];
 | 
			
		||||
  char* pointers_to_mutable_chars[N];
 | 
			
		||||
  for (int j = 0; j < N; ++j)
 | 
			
		||||
    pointers_to_mutable_chars[j] = &mutable_characters[j];
 | 
			
		||||
 | 
			
		||||
  boost::indirect_iterator<char* const*> mutable_indirect_first(pointers_to_mutable_chars),
 | 
			
		||||
    mutable_indirect_last(pointers_to_mutable_chars + N);
 | 
			
		||||
  boost::indirect_iterator<char* const*, char const> const_indirect_first(pointers_to_chars),
 | 
			
		||||
    const_indirect_last(pointers_to_chars + N);
 | 
			
		||||
 | 
			
		||||
  std::transform(const_indirect_first, const_indirect_last,
 | 
			
		||||
                 mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
 | 
			
		||||
 | 
			
		||||
  std::copy(mutable_indirect_first, mutable_indirect_last,
 | 
			
		||||
            std::ostream_iterator<char>(std::cout, ","));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  // Example of using make_indirect_iterator()
 | 
			
		||||
 | 
			
		||||
  std::copy(boost::make_indirect_iterator(pointers_to_chars), 
 | 
			
		||||
            boost::make_indirect_iterator(pointers_to_chars + N),
 | 
			
		||||
            std::ostream_iterator<char>(std::cout, ","));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										46
									
								
								iterator_adaptor_examples.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								iterator_adaptor_examples.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <boost/iterator/transform_iterator.hpp>
 | 
			
		||||
#include <boost/pending/integer_range.hpp>
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  // This is a simple example of using the transform_iterators class to
 | 
			
		||||
  // generate iterators that multiply the value returned by dereferencing
 | 
			
		||||
  // the iterator. In this case we are multiplying by 2.
 | 
			
		||||
  // Would be cooler to use lambda library in this example.
 | 
			
		||||
 | 
			
		||||
  int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
 | 
			
		||||
 | 
			
		||||
  typedef std::binder1st< std::multiplies<int> > Function;
 | 
			
		||||
  
 | 
			
		||||
  typedef boost::transform_iterator<Function, int*> doubling_iterator;
 | 
			
		||||
 | 
			
		||||
  doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),
 | 
			
		||||
    i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2));
 | 
			
		||||
 | 
			
		||||
  std::cout << "multiplying the array by 2:" << std::endl;
 | 
			
		||||
  while (i != i_end)
 | 
			
		||||
    std::cout << *i++ << " ";
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Here is an example of counting from 0 to 5 using the integer_range class.
 | 
			
		||||
 | 
			
		||||
  boost::integer_range<int> r(0,5);
 | 
			
		||||
 | 
			
		||||
  std::cout << "counting to from 0 to 4:" << std::endl;
 | 
			
		||||
  std::copy(r.begin(), r.end(), std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -1,463 +0,0 @@
 | 
			
		||||
//  Demonstrate and test boost/operators.hpp on std::iterators  -------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  19 Feb 01 Take adavantage of improved iterator_traits to do more tests
 | 
			
		||||
//            on MSVC. Hack around an MSVC-with-STLport internal compiler
 | 
			
		||||
//            error. (David Abrahams)
 | 
			
		||||
//  11 Feb 01 Added test of operator-> for forward and input iterators.
 | 
			
		||||
//            (Jeremy Siek)
 | 
			
		||||
//  11 Feb 01 Borland fixes (David Abrahams)
 | 
			
		||||
//  10 Feb 01 Use new adaptors interface. (David Abrahams)
 | 
			
		||||
//  10 Feb 01 Use new filter_ interface. (David Abrahams)
 | 
			
		||||
//  09 Feb 01 Use new reverse_ and indirect_ interfaces. Replace
 | 
			
		||||
//            BOOST_NO_STD_ITERATOR_TRAITS with
 | 
			
		||||
//            BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION to prove we've
 | 
			
		||||
//            normalized to core compiler capabilities (David Abrahams)
 | 
			
		||||
//  08 Feb 01 Use Jeremy's new make_reverse_iterator form; add more
 | 
			
		||||
//            comprehensive testing. Force-decay array function arguments to
 | 
			
		||||
//            pointers.
 | 
			
		||||
//  07 Feb 01 Added tests for the make_xxx_iterator() helper functions.
 | 
			
		||||
//            (Jeremy Siek)
 | 
			
		||||
//  07 Feb 01 Replaced use of xxx_pair_generator with xxx_generator where
 | 
			
		||||
//            possible (which was all but the projection iterator).
 | 
			
		||||
//            (Jeremy Siek)
 | 
			
		||||
//  06 Feb 01 Removed now-defaulted template arguments where possible
 | 
			
		||||
//            Updated names to correspond to new generator naming convention.
 | 
			
		||||
//            Added a trivial test for make_transform_iterator().
 | 
			
		||||
//            Gave traits for const iterators a mutable value_type, per std.
 | 
			
		||||
//            Resurrected my original tests for indirect iterators.
 | 
			
		||||
//            (David Abrahams)
 | 
			
		||||
//  04 Feb 01 Fix for compilers without standard iterator_traits
 | 
			
		||||
//            (David Abrahams)
 | 
			
		||||
//  13 Jun 00 Added const version of the iterator tests (Jeremy Siek)
 | 
			
		||||
//  12 Dec 99 Initial version with iterator operators (Jeremy Siek)
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <functional>
 | 
			
		||||
 | 
			
		||||
#include <boost/iterator_adaptors.hpp>
 | 
			
		||||
#include <boost/pending/iterator_tests.hpp>
 | 
			
		||||
#include <boost/pending/integer_range.hpp>
 | 
			
		||||
#include <boost/concept_archetype.hpp>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <deque>
 | 
			
		||||
#include <set>
 | 
			
		||||
 | 
			
		||||
struct my_iterator_tag : public std::random_access_iterator_tag { };
 | 
			
		||||
 | 
			
		||||
using boost::dummyT;
 | 
			
		||||
 | 
			
		||||
struct my_iter_traits {
 | 
			
		||||
  typedef dummyT value_type;
 | 
			
		||||
  typedef dummyT* pointer;
 | 
			
		||||
  typedef dummyT& reference;
 | 
			
		||||
  typedef my_iterator_tag iterator_category;
 | 
			
		||||
  typedef std::ptrdiff_t difference_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct my_const_iter_traits {
 | 
			
		||||
  typedef dummyT value_type;
 | 
			
		||||
  typedef const dummyT* pointer;
 | 
			
		||||
  typedef const dummyT& reference;
 | 
			
		||||
  typedef my_iterator_tag iterator_category;
 | 
			
		||||
  typedef std::ptrdiff_t difference_type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef boost::iterator_adaptor<dummyT*, 
 | 
			
		||||
  boost::default_iterator_policies, dummyT> my_iterator;
 | 
			
		||||
 | 
			
		||||
typedef boost::iterator_adaptor<const dummyT*, 
 | 
			
		||||
  boost::default_iterator_policies, const dummyT> const_my_iterator;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct mult_functor {
 | 
			
		||||
  typedef int result_type;
 | 
			
		||||
  typedef int argument_type;
 | 
			
		||||
  // Functors used with transform_iterator must be
 | 
			
		||||
  // DefaultConstructible, as the transform_iterator must be
 | 
			
		||||
  // DefaultConstructible to satisfy the requirements for
 | 
			
		||||
  // TrivialIterator.
 | 
			
		||||
  mult_functor() { }
 | 
			
		||||
  mult_functor(int aa) : a(aa) { }
 | 
			
		||||
  int operator()(int b) const { return a * b; }
 | 
			
		||||
  int a;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Pair>
 | 
			
		||||
struct select1st_ 
 | 
			
		||||
  : public std::unary_function<Pair, typename Pair::first_type>
 | 
			
		||||
{
 | 
			
		||||
  const typename Pair::first_type& operator()(const Pair& x) const {
 | 
			
		||||
    return x.first;
 | 
			
		||||
  }
 | 
			
		||||
  typename Pair::first_type& operator()(Pair& x) const {
 | 
			
		||||
    return x.first;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct one_or_four {
 | 
			
		||||
  bool operator()(dummyT x) const {
 | 
			
		||||
    return x.foo() == 1 || x.foo() == 4;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef std::deque<int> storage;
 | 
			
		||||
typedef std::deque<int*> pointer_deque;
 | 
			
		||||
typedef std::set<storage::iterator> iterator_set;
 | 
			
		||||
 | 
			
		||||
void more_indirect_iterator_tests()
 | 
			
		||||
{
 | 
			
		||||
// For some reason all heck breaks loose in the compiler under these conditions.
 | 
			
		||||
#if !defined(BOOST_MSVC) || !defined(__STL_DEBUG)
 | 
			
		||||
    storage store(1000);
 | 
			
		||||
    std::generate(store.begin(), store.end(), rand);
 | 
			
		||||
    
 | 
			
		||||
    pointer_deque ptr_deque;
 | 
			
		||||
    iterator_set iter_set;
 | 
			
		||||
 | 
			
		||||
    for (storage::iterator p = store.begin(); p != store.end(); ++p)
 | 
			
		||||
    {
 | 
			
		||||
        ptr_deque.push_back(&*p);
 | 
			
		||||
        iter_set.insert(p);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    typedef boost::indirect_iterator_pair_generator<
 | 
			
		||||
        pointer_deque::iterator
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , int
 | 
			
		||||
#endif
 | 
			
		||||
    > IndirectDeque;
 | 
			
		||||
 | 
			
		||||
    IndirectDeque::iterator db(ptr_deque.begin());
 | 
			
		||||
    IndirectDeque::iterator de(ptr_deque.end());
 | 
			
		||||
    assert(static_cast<std::size_t>(de - db) == store.size());
 | 
			
		||||
    assert(db + store.size() == de);
 | 
			
		||||
    IndirectDeque::const_iterator dci(db);
 | 
			
		||||
    assert(db == dci);
 | 
			
		||||
    assert(dci == db);
 | 
			
		||||
    assert(dci != de);
 | 
			
		||||
    assert(dci < de);
 | 
			
		||||
    assert(dci <= de);
 | 
			
		||||
    assert(de >= dci);
 | 
			
		||||
    assert(de > dci);
 | 
			
		||||
    dci = de;
 | 
			
		||||
    assert(dci == de);
 | 
			
		||||
 | 
			
		||||
    boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin()));
 | 
			
		||||
    
 | 
			
		||||
    *db = 999;
 | 
			
		||||
    assert(store.front() == 999);
 | 
			
		||||
 | 
			
		||||
    typedef boost::indirect_iterator_generator<
 | 
			
		||||
        iterator_set::iterator
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , int
 | 
			
		||||
#endif
 | 
			
		||||
        >::type indirect_set_iterator;
 | 
			
		||||
 | 
			
		||||
    typedef boost::indirect_iterator_generator<
 | 
			
		||||
        iterator_set::iterator,
 | 
			
		||||
        const int
 | 
			
		||||
        >::type const_indirect_set_iterator;
 | 
			
		||||
 | 
			
		||||
    indirect_set_iterator sb(iter_set.begin());
 | 
			
		||||
    indirect_set_iterator se(iter_set.end());
 | 
			
		||||
    const_indirect_set_iterator sci(iter_set.begin());
 | 
			
		||||
    assert(sci == sb);
 | 
			
		||||
    assert(sci != se);
 | 
			
		||||
    sci = se;
 | 
			
		||||
    assert(sci == se);
 | 
			
		||||
    
 | 
			
		||||
    *boost::prior(se) = 888;
 | 
			
		||||
    assert(store.back() == 888);
 | 
			
		||||
    assert(std::equal(sb, se, store.begin()));
 | 
			
		||||
 | 
			
		||||
    boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]);
 | 
			
		||||
    assert(std::equal(db, de, store.begin()));
 | 
			
		||||
#endif    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main()
 | 
			
		||||
{
 | 
			
		||||
  dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), 
 | 
			
		||||
                     dummyT(3), dummyT(4), dummyT(5) };
 | 
			
		||||
  const int N = sizeof(array)/sizeof(dummyT);
 | 
			
		||||
 | 
			
		||||
  // sanity check, if this doesn't pass the test is buggy
 | 
			
		||||
  boost::random_access_iterator_test(array,N,array);
 | 
			
		||||
 | 
			
		||||
  // Check that the policy concept checks and the default policy
 | 
			
		||||
  // implementation match up.
 | 
			
		||||
  boost::function_requires< 
 | 
			
		||||
     boost::RandomAccessIteratorPoliciesConcept<
 | 
			
		||||
       boost::default_iterator_policies, int*,
 | 
			
		||||
       boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
 | 
			
		||||
                      int*, int&>
 | 
			
		||||
      > >();
 | 
			
		||||
 | 
			
		||||
  // Test the iterator_adaptor
 | 
			
		||||
  {
 | 
			
		||||
    my_iterator i(array);
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
    
 | 
			
		||||
    const_my_iterator j(array);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Test transform_iterator
 | 
			
		||||
  {
 | 
			
		||||
    int x[N], y[N];
 | 
			
		||||
    for (int k = 0; k < N; ++k)
 | 
			
		||||
      x[k] = k;
 | 
			
		||||
    std::copy(x, x + N, y);
 | 
			
		||||
 | 
			
		||||
    for (int k2 = 0; k2 < N; ++k2)
 | 
			
		||||
      x[k2] = x[k2] * 2;
 | 
			
		||||
 | 
			
		||||
    boost::transform_iterator_generator<mult_functor, int*>::type
 | 
			
		||||
      i(y, mult_functor(2));
 | 
			
		||||
    boost::input_iterator_test(i, x[0], x[1]);
 | 
			
		||||
    boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_functor(2)), x[0], x[1]);
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Test indirect_iterator_generator
 | 
			
		||||
  {
 | 
			
		||||
    dummyT* ptr[N];
 | 
			
		||||
    for (int k = 0; k < N; ++k)
 | 
			
		||||
      ptr[k] = array + k;
 | 
			
		||||
 | 
			
		||||
    typedef boost::indirect_iterator_generator<dummyT**
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , dummyT
 | 
			
		||||
#endif
 | 
			
		||||
      >::type indirect_iterator;
 | 
			
		||||
 | 
			
		||||
    typedef boost::indirect_iterator_generator<dummyT**, const dummyT>::type const_indirect_iterator;
 | 
			
		||||
 | 
			
		||||
    indirect_iterator i(ptr);
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
    // check operator->
 | 
			
		||||
    assert((*i).m_x == i->foo());
 | 
			
		||||
 | 
			
		||||
    const_indirect_iterator j(ptr);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
 | 
			
		||||
    dummyT*const* const_ptr = ptr;
 | 
			
		||||
    
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
 | 
			
		||||
#endif
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);
 | 
			
		||||
 | 
			
		||||
    more_indirect_iterator_tests();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Test projection_iterator_pair_generator
 | 
			
		||||
  {    
 | 
			
		||||
    typedef std::pair<dummyT,dummyT> Pair;
 | 
			
		||||
    Pair pair_array[N];
 | 
			
		||||
    for (int k = 0; k < N; ++k)
 | 
			
		||||
      pair_array[k].first = array[k];
 | 
			
		||||
 | 
			
		||||
    typedef boost::projection_iterator_pair_generator<select1st_<Pair>,
 | 
			
		||||
      Pair*, const Pair*
 | 
			
		||||
      > Projection;
 | 
			
		||||
    
 | 
			
		||||
    Projection::iterator i(pair_array);
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_projection_iterator(pair_array, select1st_<Pair>()), N, array);    
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_projection_iterator< select1st_<Pair> >(pair_array), N, array);    
 | 
			
		||||
 | 
			
		||||
    Projection::const_iterator j(pair_array);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_const_projection_iterator(pair_array, select1st_<Pair>()), N, array);
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_const_projection_iterator<select1st_<Pair> >(pair_array), N, array);
 | 
			
		||||
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Test reverse_iterator_generator
 | 
			
		||||
  {
 | 
			
		||||
    dummyT reversed[N];
 | 
			
		||||
    std::copy(array, array + N, reversed);
 | 
			
		||||
    std::reverse(reversed, reversed + N);
 | 
			
		||||
    
 | 
			
		||||
    typedef boost::reverse_iterator_generator<dummyT*
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , dummyT
 | 
			
		||||
#endif
 | 
			
		||||
      >::type reverse_iterator;
 | 
			
		||||
    
 | 
			
		||||
    reverse_iterator i(reversed + N);
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    typedef boost::reverse_iterator_generator<const dummyT*
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , const dummyT
 | 
			
		||||
#endif
 | 
			
		||||
      >::type const_reverse_iterator;
 | 
			
		||||
    
 | 
			
		||||
    const_reverse_iterator j(reversed + N);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
 | 
			
		||||
    const dummyT* const_reversed = reversed;
 | 
			
		||||
    
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);    
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Test reverse_iterator_generator again, with traits fully deducible on all platforms
 | 
			
		||||
  {
 | 
			
		||||
    std::deque<dummyT> reversed_container;
 | 
			
		||||
    std::reverse_copy(array, array + N, std::back_inserter(reversed_container));
 | 
			
		||||
    const std::deque<dummyT>::iterator reversed = reversed_container.begin();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    typedef boost::reverse_iterator_generator<
 | 
			
		||||
        std::deque<dummyT>::iterator>::type reverse_iterator;
 | 
			
		||||
    typedef boost::reverse_iterator_generator<
 | 
			
		||||
        std::deque<dummyT>::const_iterator, const dummyT>::type const_reverse_iterator;
 | 
			
		||||
 | 
			
		||||
    // MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation
 | 
			
		||||
    // (e.g. "reversed + N") is used in the constructor below.
 | 
			
		||||
    const std::deque<dummyT>::iterator finish = reversed_container.end();
 | 
			
		||||
    reverse_iterator i(finish);
 | 
			
		||||
    
 | 
			
		||||
    boost::random_access_iterator_test(i, N, array);
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
 | 
			
		||||
 | 
			
		||||
    const_reverse_iterator j = reverse_iterator(finish);
 | 
			
		||||
    boost::random_access_iterator_test(j, N, array);
 | 
			
		||||
 | 
			
		||||
    const std::deque<dummyT>::const_iterator const_reversed = reversed;
 | 
			
		||||
    boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
 | 
			
		||||
    
 | 
			
		||||
    // Many compilers' builtin deque iterators don't interoperate well, though
 | 
			
		||||
    // STLport fixes that problem.
 | 
			
		||||
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && !defined(BOOST_MSVC)
 | 
			
		||||
    boost::const_nonconst_iterator_test(i, ++j);
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Test integer_range's iterators
 | 
			
		||||
  {
 | 
			
		||||
    int int_array[] = { 0, 1, 2, 3, 4, 5 };
 | 
			
		||||
    boost::integer_range<int> r(0, 5);
 | 
			
		||||
    boost::random_access_iterator_test(r.begin(), r.size(), int_array);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Test filter iterator
 | 
			
		||||
  {
 | 
			
		||||
    // Using typedefs for filter_gen::type and filter_gen::policies_type
 | 
			
		||||
    // confused Borland terribly.
 | 
			
		||||
    typedef boost::detail::non_bidirectional_category<dummyT*>::type category;
 | 
			
		||||
    
 | 
			
		||||
    typedef ::boost::filter_iterator_generator<one_or_four, dummyT*
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
        , dummyT
 | 
			
		||||
#endif
 | 
			
		||||
        > filter_iter_gen;
 | 
			
		||||
 | 
			
		||||
#ifndef __BORLANDC__
 | 
			
		||||
    typedef filter_iter_gen::type filter_iter;
 | 
			
		||||
#else
 | 
			
		||||
# define filter_iter filter_iter_gen::type // Borland has a problem with the above
 | 
			
		||||
#endif
 | 
			
		||||
    filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N));
 | 
			
		||||
    boost::forward_iterator_test(i, dummyT(1), dummyT(4));
 | 
			
		||||
 | 
			
		||||
    enum { is_forward = boost::is_same<
 | 
			
		||||
           filter_iter::iterator_category,
 | 
			
		||||
           std::forward_iterator_tag>::value };
 | 
			
		||||
    BOOST_STATIC_ASSERT(is_forward);
 | 
			
		||||
 | 
			
		||||
    // On compilers not supporting partial specialization, we can do more type
 | 
			
		||||
    // deduction with deque iterators than with pointers... unless the library
 | 
			
		||||
    // is broken ;-(
 | 
			
		||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
 | 
			
		||||
    std::deque<dummyT> array2;
 | 
			
		||||
    std::copy(array+0, array+N, std::back_inserter(array2));
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator(array2.begin(), array2.end(), one_or_four()),
 | 
			
		||||
        dummyT(1), dummyT(4));
 | 
			
		||||
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator<one_or_four>(array2.begin(), array2.end()),
 | 
			
		||||
        dummyT(1), dummyT(4));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(BOOST_MSVC) // This just freaks MSVC out completely
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator<one_or_four>(
 | 
			
		||||
            boost::make_reverse_iterator(array2.end()),
 | 
			
		||||
            boost::make_reverse_iterator(array2.begin())
 | 
			
		||||
            ),
 | 
			
		||||
        dummyT(4), dummyT(1));
 | 
			
		||||
#endif
 | 
			
		||||
    
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator(array+0, array+N, one_or_four()),
 | 
			
		||||
        dummyT(1), dummyT(4));
 | 
			
		||||
 | 
			
		||||
    boost::forward_iterator_test(
 | 
			
		||||
        boost::make_filter_iterator<one_or_four>(array, array + N),
 | 
			
		||||
        dummyT(1), dummyT(4));
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // check operator-> with a forward iterator
 | 
			
		||||
  {
 | 
			
		||||
    boost::forward_iterator_archetype<dummyT> forward_iter;
 | 
			
		||||
    typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
 | 
			
		||||
      boost::default_iterator_policies,
 | 
			
		||||
      dummyT, const dummyT&, 
 | 
			
		||||
      std::forward_iterator_tag, std::ptrdiff_t, const dummyT*> adaptor_type;
 | 
			
		||||
    adaptor_type i(forward_iter);
 | 
			
		||||
    if (0) // don't do this, just make sure it compiles
 | 
			
		||||
      assert((*i).m_x == i->foo());      
 | 
			
		||||
  }
 | 
			
		||||
  // check operator-> with an input iterator
 | 
			
		||||
  {
 | 
			
		||||
    boost::input_iterator_archetype<dummyT> input_iter;
 | 
			
		||||
    typedef boost::iterator_adaptor<boost::input_iterator_archetype<dummyT>,
 | 
			
		||||
      boost::default_iterator_policies,
 | 
			
		||||
      dummyT, const dummyT&, 
 | 
			
		||||
      std::input_iterator_tag, std::ptrdiff_t, const dummyT*> adaptor_type;
 | 
			
		||||
    adaptor_type i(input_iter);
 | 
			
		||||
    if (0) // don't do this, just make sure it compiles
 | 
			
		||||
      assert((*i).m_x == i->foo());      
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  std::cout << "test successful " << std::endl;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										215
									
								
								iterator_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								iterator_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,215 @@
 | 
			
		||||
//  (C) Copyright David Abrahams 2002. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  04 Mar 2001 Patches for Intel C++ (Dave Abrahams)
 | 
			
		||||
//  19 Feb 2001 Take advantage of improved iterator_traits to do more tests
 | 
			
		||||
//              on MSVC. Reordered some #ifdefs for coherency.
 | 
			
		||||
//              (David Abrahams)
 | 
			
		||||
//  13 Feb 2001 Test new VC6 workarounds (David Abrahams)
 | 
			
		||||
//  11 Feb 2001 Final fixes for Borland (David Abrahams)
 | 
			
		||||
//  11 Feb 2001 Some fixes for Borland get it closer on that compiler
 | 
			
		||||
//              (David Abrahams)
 | 
			
		||||
//  07 Feb 2001 More comprehensive testing; factored out static tests for
 | 
			
		||||
//              better reuse (David Abrahams)
 | 
			
		||||
//  21 Jan 2001 Quick fix to my_iterator, which wasn't returning a
 | 
			
		||||
//              reference type from operator* (David Abrahams)
 | 
			
		||||
//  19 Jan 2001 Initial version with iterator operators (David Abrahams)
 | 
			
		||||
 | 
			
		||||
#include <boost/detail/iterator.hpp>
 | 
			
		||||
#include <boost/type_traits/is_same.hpp>
 | 
			
		||||
#include <boost/operators.hpp>
 | 
			
		||||
#include <boost/static_assert.hpp>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
 | 
			
		||||
// A UDT for which we can specialize std::iterator_traits<element*> on
 | 
			
		||||
// compilers which don't support partial specialization. There's no
 | 
			
		||||
// other reasonable way to test pointers on those compilers.
 | 
			
		||||
struct element {};
 | 
			
		||||
 | 
			
		||||
// An iterator for which we can get traits.
 | 
			
		||||
struct my_iterator1
 | 
			
		||||
    : boost::forward_iterator_helper<my_iterator1, char, long, const char*, const char&>
 | 
			
		||||
{
 | 
			
		||||
    my_iterator1(const char* p) : m_p(p) {}
 | 
			
		||||
    
 | 
			
		||||
    bool operator==(const my_iterator1& rhs) const
 | 
			
		||||
        { return this->m_p == rhs.m_p; }
 | 
			
		||||
 | 
			
		||||
    my_iterator1& operator++() { ++this->m_p; return *this; }
 | 
			
		||||
    const char& operator*() { return *m_p; }
 | 
			
		||||
 private:
 | 
			
		||||
    const char* m_p;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Used to prove that we don't require std::iterator<> in the hierarchy under
 | 
			
		||||
// MSVC6, and that we can compute all the traits for a standard-conforming UDT
 | 
			
		||||
// iterator.
 | 
			
		||||
struct my_iterator2
 | 
			
		||||
    : boost::equality_comparable<my_iterator2
 | 
			
		||||
    , boost::incrementable<my_iterator2
 | 
			
		||||
    , boost::dereferenceable<my_iterator2,const char*> > >
 | 
			
		||||
{
 | 
			
		||||
    typedef char value_type;
 | 
			
		||||
    typedef long difference_type;
 | 
			
		||||
    typedef const char* pointer;
 | 
			
		||||
    typedef const char& reference;
 | 
			
		||||
    typedef std::forward_iterator_tag iterator_category;
 | 
			
		||||
    
 | 
			
		||||
    my_iterator2(const char* p) : m_p(p) {}
 | 
			
		||||
    
 | 
			
		||||
    bool operator==(const my_iterator2& rhs) const
 | 
			
		||||
        { return this->m_p == rhs.m_p; }
 | 
			
		||||
 | 
			
		||||
    my_iterator2& operator++() { ++this->m_p; return *this; }
 | 
			
		||||
    const char& operator*() { return *m_p; }
 | 
			
		||||
 private:
 | 
			
		||||
    const char* m_p;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Used to prove that we're not overly confused by the existence of
 | 
			
		||||
// std::iterator<> in the hierarchy under MSVC6 - we should find that
 | 
			
		||||
// boost::detail::iterator_traits<my_iterator3>::difference_type is int.
 | 
			
		||||
struct my_iterator3 : my_iterator1
 | 
			
		||||
{
 | 
			
		||||
    typedef int difference_type;
 | 
			
		||||
    my_iterator3(const char* p)
 | 
			
		||||
        : my_iterator1(p) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Assertion tools.  Used instead of BOOST_STATIC_ASSERT because that
 | 
			
		||||
// doesn't give us a nice stack backtrace
 | 
			
		||||
//
 | 
			
		||||
template <bool = false> struct assertion;
 | 
			
		||||
 | 
			
		||||
template <> struct assertion<true>
 | 
			
		||||
{
 | 
			
		||||
    typedef char type;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T, class U>
 | 
			
		||||
struct assert_same
 | 
			
		||||
    : assertion<(::boost::is_same<T,U>::value)>
 | 
			
		||||
{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Iterator tests
 | 
			
		||||
template <class Iterator,
 | 
			
		||||
    class value_type, class difference_type, class pointer, class reference, class category>
 | 
			
		||||
struct non_portable_tests
 | 
			
		||||
{
 | 
			
		||||
    typedef typename boost::detail::iterator_traits<Iterator>::pointer test_pt;
 | 
			
		||||
    typedef typename boost::detail::iterator_traits<Iterator>::reference test_rt;
 | 
			
		||||
    typedef typename assert_same<test_pt, pointer>::type a1;
 | 
			
		||||
    typedef typename assert_same<test_rt, reference>::type a2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Iterator,
 | 
			
		||||
    class value_type, class difference_type, class pointer, class reference, class category>
 | 
			
		||||
struct portable_tests
 | 
			
		||||
{
 | 
			
		||||
    typedef typename boost::detail::iterator_traits<Iterator>::difference_type test_dt;
 | 
			
		||||
    typedef typename boost::detail::iterator_traits<Iterator>::iterator_category test_cat;
 | 
			
		||||
    typedef typename assert_same<test_dt, difference_type>::type a1;
 | 
			
		||||
    typedef typename assert_same<test_cat, category>::type a2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Test iterator_traits
 | 
			
		||||
template <class Iterator,
 | 
			
		||||
    class value_type, class difference_type, class pointer, class reference, class category>
 | 
			
		||||
struct input_iterator_test
 | 
			
		||||
    : portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
 | 
			
		||||
{
 | 
			
		||||
    typedef typename boost::detail::iterator_traits<Iterator>::value_type test_vt;
 | 
			
		||||
    typedef typename assert_same<test_vt, value_type>::type a1;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Iterator,
 | 
			
		||||
    class value_type, class difference_type, class pointer, class reference, class category>
 | 
			
		||||
struct non_pointer_test
 | 
			
		||||
    : input_iterator_test<Iterator,value_type,difference_type,pointer,reference,category>
 | 
			
		||||
      , non_portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
 | 
			
		||||
{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class Iterator,
 | 
			
		||||
    class value_type, class difference_type, class pointer, class reference, class category>
 | 
			
		||||
struct maybe_pointer_test
 | 
			
		||||
    : portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
 | 
			
		||||
      , non_portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
 | 
			
		||||
{
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
input_iterator_test<std::istream_iterator<int>, int, std::ptrdiff_t, int*, int&, std::input_iterator_tag>
 | 
			
		||||
        istream_iterator_test;
 | 
			
		||||
 | 
			
		||||
#if defined(__BORLANDC__) && !defined(__SGI_STL_PORT)
 | 
			
		||||
typedef ::std::char_traits<char>::off_type distance;
 | 
			
		||||
non_pointer_test<std::ostream_iterator<int>,int,
 | 
			
		||||
    distance,int*,int&,std::output_iterator_tag> ostream_iterator_test;
 | 
			
		||||
#elif defined(BOOST_MSVC_STD_ITERATOR)
 | 
			
		||||
non_pointer_test<std::ostream_iterator<int>,
 | 
			
		||||
    int, void, int*, int&, std::output_iterator_tag>
 | 
			
		||||
        ostream_iterator_test;
 | 
			
		||||
#else
 | 
			
		||||
non_pointer_test<std::ostream_iterator<int>,
 | 
			
		||||
    void, void, void, void, std::output_iterator_tag>
 | 
			
		||||
        ostream_iterator_test;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifdef __KCC
 | 
			
		||||
  typedef long std_list_diff_type;
 | 
			
		||||
#else
 | 
			
		||||
  typedef std::ptrdiff_t std_list_diff_type;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
non_pointer_test<std::list<int>::iterator, int, std_list_diff_type, int*, int&, std::bidirectional_iterator_tag>
 | 
			
		||||
        list_iterator_test;
 | 
			
		||||
 | 
			
		||||
maybe_pointer_test<std::vector<int>::iterator, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag>
 | 
			
		||||
        vector_iterator_test;
 | 
			
		||||
 | 
			
		||||
maybe_pointer_test<int*, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag>
 | 
			
		||||
        int_pointer_test;
 | 
			
		||||
 | 
			
		||||
non_pointer_test<my_iterator1, char, long, const char*, const char&, std::forward_iterator_tag>
 | 
			
		||||
       my_iterator1_test;
 | 
			
		||||
                    
 | 
			
		||||
non_pointer_test<my_iterator2, char, long, const char*, const char&, std::forward_iterator_tag>
 | 
			
		||||
       my_iterator2_test;
 | 
			
		||||
 | 
			
		||||
non_pointer_test<my_iterator3, char, int, const char*, const char&, std::forward_iterator_tag>
 | 
			
		||||
       my_iterator3_test;
 | 
			
		||||
 | 
			
		||||
int main()
 | 
			
		||||
{
 | 
			
		||||
    char chars[100];
 | 
			
		||||
    int ints[100];
 | 
			
		||||
 | 
			
		||||
    for (int length = 3; length < 100; length += length / 3)
 | 
			
		||||
    {
 | 
			
		||||
        std::list<int> l(length);
 | 
			
		||||
        assert(boost::detail::distance(l.begin(), l.end()) == length);
 | 
			
		||||
        
 | 
			
		||||
        std::vector<int> v(length);
 | 
			
		||||
        assert(boost::detail::distance(v.begin(), v.end()) == length);
 | 
			
		||||
 | 
			
		||||
        assert(boost::detail::distance(&ints[0], ints + length) == length);
 | 
			
		||||
        assert(boost::detail::distance(my_iterator1(chars), my_iterator1(chars + length)) == length);
 | 
			
		||||
        assert(boost::detail::distance(my_iterator2(chars), my_iterator2(chars + length)) == length);
 | 
			
		||||
        assert(boost::detail::distance(my_iterator3(chars), my_iterator3(chars + length)) == length);
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										342
									
								
								iterators_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										342
									
								
								iterators_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,342 @@
 | 
			
		||||
//  Demonstrate and test boost/operators.hpp on std::iterators  --------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  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 <strstream>  // for std::ostrstream
 | 
			
		||||
 | 
			
		||||
# ifdef BOOST_NO_STDC_NAMESPACE
 | 
			
		||||
    namespace std { using ::strcmp; }
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// Iterator test class
 | 
			
		||||
template <class T, class R, class P>
 | 
			
		||||
struct test_iter
 | 
			
		||||
  : public boost::random_access_iterator_helper<
 | 
			
		||||
     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 );
 | 
			
		||||
    BOOST_STATIC_CONSTANT( std::size_t, scratch_length = 40u );
 | 
			
		||||
 | 
			
		||||
    typedef std::string  fruit_array_type[ fruit_length ];
 | 
			
		||||
    typedef char         scratch_array_type[ scratch_length ];
 | 
			
		||||
 | 
			
		||||
    static  fruit_array_type    fruit;
 | 
			
		||||
    static  scratch_array_type  scratch;
 | 
			
		||||
 | 
			
		||||
};  // 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;
 | 
			
		||||
const std::size_t test_opr_base::scratch_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" };
 | 
			
		||||
 | 
			
		||||
test_opr_base::scratch_array_type
 | 
			
		||||
 test_opr_base::scratch = "";
 | 
			
		||||
 | 
			
		||||
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::ostrstream  oss( scratch, scratch_length );
 | 
			
		||||
    for ( iter_type i = fruit_begin ; i != fruit_end ; )
 | 
			
		||||
    {
 | 
			
		||||
        oss << *i++ << ' ';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ")
 | 
			
		||||
     == 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test post-decrement
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::post_decrement_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing post-decrement test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ostrstream  oss( scratch, scratch_length );
 | 
			
		||||
    for ( iter_type i = fruit_end ; i != fruit_begin ; )
 | 
			
		||||
    {
 | 
			
		||||
        i--;
 | 
			
		||||
        oss << *i << ' ';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "plum grape peach pear orange apple ")
 | 
			
		||||
     == 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test indirect structure referral
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::indirect_referral_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing indirect reference test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ostrstream  oss( scratch, scratch_length );
 | 
			
		||||
    for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
 | 
			
		||||
    {
 | 
			
		||||
        oss << i->size() << ' ';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "5 6 4 5 5 4 ") == 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test offset addition
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::offset_addition_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing offset addition test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ptrdiff_t const  two = 2;
 | 
			
		||||
    std::ostrstream       oss( scratch, scratch_length );
 | 
			
		||||
    for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two )
 | 
			
		||||
    {
 | 
			
		||||
        oss << *i << ' ';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test offset addition, in reverse order
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::reverse_offset_addition_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing reverse offset addition test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ptrdiff_t const  two = 2;
 | 
			
		||||
    std::ostrstream       oss( scratch, scratch_length );
 | 
			
		||||
    for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i )
 | 
			
		||||
    {
 | 
			
		||||
        oss << *i << ' ';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test offset subtraction
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::offset_subtraction_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing offset subtraction test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ptrdiff_t const  two = 2;
 | 
			
		||||
    std::ostrstream       oss( scratch, scratch_length );
 | 
			
		||||
    for ( iter_type i = fruit_end ; fruit_begin < i ; )
 | 
			
		||||
    {
 | 
			
		||||
        i = i - two;
 | 
			
		||||
        if ( (fruit_begin < i) || (fruit_begin == i) )
 | 
			
		||||
        {
 | 
			
		||||
            oss << *i << ' ';
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "grape pear apple ") == 0 );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test comparisons
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::comparison_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    using std::cout;
 | 
			
		||||
    using std::ptrdiff_t;
 | 
			
		||||
 | 
			
		||||
    cout << "\tDoing comparison tests.\n\t\tPass:";
 | 
			
		||||
 | 
			
		||||
    for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
 | 
			
		||||
    {
 | 
			
		||||
        ptrdiff_t const  i_offset = i - fruit_begin;
 | 
			
		||||
 | 
			
		||||
        cout << ' ' << *i << std::flush;
 | 
			
		||||
        for ( iter_type j = fruit_begin ; j != fruit_end ; ++j )
 | 
			
		||||
        {
 | 
			
		||||
            ptrdiff_t const  j_offset = j - fruit_begin;
 | 
			
		||||
 | 
			
		||||
            BOOST_TEST( (i != j) == (i_offset != j_offset) );
 | 
			
		||||
            BOOST_TEST( (i > j) == (i_offset > j_offset) );
 | 
			
		||||
            BOOST_TEST( (i <= j) == (i_offset <= j_offset) );
 | 
			
		||||
            BOOST_TEST( (i >= j) == (i_offset >= j_offset) );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    cout << std::endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Test indexing
 | 
			
		||||
template <typename T, typename R, typename P>
 | 
			
		||||
void
 | 
			
		||||
test_opr<T, R, P>::indexing_test
 | 
			
		||||
(
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
    std::cout << "\tDoing indexing test." << std::endl;
 | 
			
		||||
 | 
			
		||||
    std::ostrstream  oss( scratch, scratch_length );
 | 
			
		||||
    for ( std::size_t k = 0u ; k < fruit_length ; ++k )
 | 
			
		||||
    {
 | 
			
		||||
        oss << fruit_begin[ k ] << ' ';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    oss << std::ends;
 | 
			
		||||
    BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ")
 | 
			
		||||
     == 0 );
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										38
									
								
								noncopyable_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								noncopyable_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
//  boost class noncopyable test program  ------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright boost.org 1999. Permission to copy, use, modify, sell
 | 
			
		||||
//  and distribute this software is granted provided this copyright
 | 
			
		||||
//  notice appears in all copies. This software is provided "as is" without
 | 
			
		||||
//  express or implied warranty, and with no claim as to its suitability for
 | 
			
		||||
//  any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//   9 Jun 99  Add unnamed namespace
 | 
			
		||||
//   2 Jun 99  Initial Version
 | 
			
		||||
 | 
			
		||||
#include <boost/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
 | 
			
		||||
  
 | 
			
		||||
							
								
								
									
										387
									
								
								numeric_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										387
									
								
								numeric_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,387 @@
 | 
			
		||||
//  (C) Copyright David Abrahams 2001. Permission to copy, use, modify,
 | 
			
		||||
//  sell and distribute this software is granted provided this
 | 
			
		||||
//  copyright notice appears in all copies. This software is provided
 | 
			
		||||
//  "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
//  to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  1  Apr 2001 Fixes for ICL; use BOOST_STATIC_CONSTANT
 | 
			
		||||
//  11 Feb 2001 Fixes for Borland (David Abrahams)
 | 
			
		||||
//  23 Jan 2001 Added test for wchar_t (David Abrahams)
 | 
			
		||||
//  23 Jan 2001 Now statically selecting a test for signed numbers to avoid
 | 
			
		||||
//              warnings with fancy compilers. Added commentary and
 | 
			
		||||
//              additional dumping of traits data for tested types (David
 | 
			
		||||
//              Abrahams).
 | 
			
		||||
//  21 Jan 2001 Initial version (David Abrahams)
 | 
			
		||||
 | 
			
		||||
#include <boost/detail/numeric_traits.hpp>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
#include <boost/type_traits.hpp>
 | 
			
		||||
#include <boost/static_assert.hpp>
 | 
			
		||||
#include <boost/cstdint.hpp>
 | 
			
		||||
#include <boost/utility.hpp>
 | 
			
		||||
#include <boost/lexical_cast.hpp>
 | 
			
		||||
#include <climits>
 | 
			
		||||
#include <typeinfo>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <string>
 | 
			
		||||
#ifndef BOOST_NO_LIMITS
 | 
			
		||||
# include <limits>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// =================================================================================
 | 
			
		||||
// template class complement_traits<Number> --
 | 
			
		||||
//
 | 
			
		||||
//    statically computes the max and min for 1s and 2s-complement binary
 | 
			
		||||
//    numbers. This helps on platforms without <limits> support. It also shows
 | 
			
		||||
//    an example of a recursive template that works with MSVC!
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
template <unsigned size> struct complement; // forward
 | 
			
		||||
 | 
			
		||||
// The template complement, below, does all the real work, using "poor man's
 | 
			
		||||
// partial specialization". We need complement_traits_aux<> so that MSVC doesn't
 | 
			
		||||
// complain about undefined min/max as we're trying to recursively define them. 
 | 
			
		||||
template <class Number, unsigned size>
 | 
			
		||||
struct complement_traits_aux
 | 
			
		||||
{
 | 
			
		||||
    BOOST_STATIC_CONSTANT(Number, max = complement<size>::template traits<Number>::max);
 | 
			
		||||
    BOOST_STATIC_CONSTANT(Number, min = complement<size>::template traits<Number>::min);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <unsigned size>
 | 
			
		||||
struct complement
 | 
			
		||||
{
 | 
			
		||||
    template <class Number>
 | 
			
		||||
    struct traits
 | 
			
		||||
    {
 | 
			
		||||
     private:
 | 
			
		||||
        // indirection through complement_traits_aux neccessary to keep MSVC happy
 | 
			
		||||
        typedef complement_traits_aux<Number, size - 1> prev;
 | 
			
		||||
     public:
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, max =
 | 
			
		||||
                            Number(Number(prev::max) << CHAR_BIT)
 | 
			
		||||
                            + Number(UCHAR_MAX));
 | 
			
		||||
        
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, min = Number(Number(prev::min) << CHAR_BIT));
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Template class complement_base<> -- defines values for min and max for
 | 
			
		||||
// complement<1>, at the deepest level of recursion. Uses "poor man's partial
 | 
			
		||||
// specialization" again.
 | 
			
		||||
template <bool is_signed> struct complement_base;
 | 
			
		||||
 | 
			
		||||
template <> struct complement_base<false>
 | 
			
		||||
{
 | 
			
		||||
    template <class Number>
 | 
			
		||||
    struct values
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, min = 0);
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, max = UCHAR_MAX);
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <> struct complement_base<true>
 | 
			
		||||
{
 | 
			
		||||
    template <class Number>
 | 
			
		||||
    struct values
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, min = SCHAR_MIN);
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, max = SCHAR_MAX);
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Base specialization of complement, puts an end to the recursion.
 | 
			
		||||
template <>
 | 
			
		||||
struct complement<1>
 | 
			
		||||
{
 | 
			
		||||
    template <class Number>
 | 
			
		||||
    struct traits
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_STATIC_CONSTANT(bool, is_signed = boost::detail::is_signed<Number>::value);
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, min =
 | 
			
		||||
                            complement_base<is_signed>::template values<Number>::min);
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, max =
 | 
			
		||||
                            complement_base<is_signed>::template values<Number>::max);
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Now here's the "pretty" template you're intended to actually use.
 | 
			
		||||
//   complement_traits<Number>::min, complement_traits<Number>::max are the
 | 
			
		||||
//   minimum and maximum values of Number if Number is a built-in integer type.
 | 
			
		||||
template <class Number>
 | 
			
		||||
struct complement_traits
 | 
			
		||||
{
 | 
			
		||||
    BOOST_STATIC_CONSTANT(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max));
 | 
			
		||||
    BOOST_STATIC_CONSTANT(Number, min = (complement_traits_aux<Number, sizeof(Number)>::min));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// =================================================================================
 | 
			
		||||
 | 
			
		||||
// Support for streaming various numeric types in exactly the format I want. I
 | 
			
		||||
// needed this in addition to all the assertions so that I could see exactly
 | 
			
		||||
// what was going on.
 | 
			
		||||
//
 | 
			
		||||
// Numbers go through a 2-stage conversion process (by default, though, no real
 | 
			
		||||
// conversion).
 | 
			
		||||
//
 | 
			
		||||
template <class T> struct stream_as {
 | 
			
		||||
    typedef T t1;
 | 
			
		||||
    typedef T t2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// char types first get converted to unsigned char, then to unsigned.
 | 
			
		||||
template <> struct stream_as<char> {
 | 
			
		||||
    typedef unsigned char t1;
 | 
			
		||||
    typedef unsigned t2;
 | 
			
		||||
};
 | 
			
		||||
template <> struct stream_as<unsigned char> {
 | 
			
		||||
    typedef unsigned char t1; typedef unsigned t2;
 | 
			
		||||
};
 | 
			
		||||
template <> struct stream_as<signed char>  {
 | 
			
		||||
    typedef unsigned char t1; typedef unsigned t2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in
 | 
			
		||||
 | 
			
		||||
// With this library implementation, __int64 and __uint64 get streamed as strings
 | 
			
		||||
template <> struct stream_as<boost::uintmax_t> {
 | 
			
		||||
    typedef std::string t1;
 | 
			
		||||
    typedef std::string t2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <> struct stream_as<boost::intmax_t>  {
 | 
			
		||||
    typedef std::string t1;
 | 
			
		||||
    typedef std::string t2;
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Standard promotion process for streaming
 | 
			
		||||
template <class T> struct promote
 | 
			
		||||
{
 | 
			
		||||
    static typename stream_as<T>::t1 from(T x) {
 | 
			
		||||
        typedef typename stream_as<T>::t1 t1;
 | 
			
		||||
        return t1(x);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in
 | 
			
		||||
 | 
			
		||||
// On this platform, stream them as long/unsigned long if they fit.
 | 
			
		||||
// Otherwise, write a string.
 | 
			
		||||
template <> struct promote<boost::uintmax_t> {
 | 
			
		||||
    std::string static from(const boost::uintmax_t x) {
 | 
			
		||||
        if (x > ULONG_MAX)
 | 
			
		||||
            return std::string("large unsigned value");
 | 
			
		||||
        else
 | 
			
		||||
            return boost::lexical_cast<std::string>((unsigned long)x);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
template <> struct promote<boost::intmax_t> {
 | 
			
		||||
    std::string static from(const boost::intmax_t x) {
 | 
			
		||||
        if (x > boost::intmax_t(ULONG_MAX))
 | 
			
		||||
            return std::string("large positive signed value");
 | 
			
		||||
        else if (x >= 0)
 | 
			
		||||
            return boost::lexical_cast<std::string>((unsigned long)x);
 | 
			
		||||
        
 | 
			
		||||
        if (x < boost::intmax_t(LONG_MIN))
 | 
			
		||||
            return std::string("large negative signed value");
 | 
			
		||||
        else
 | 
			
		||||
            return boost::lexical_cast<std::string>((long)x);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// This is the function which converts types to the form I want to stream them in.
 | 
			
		||||
template <class T>
 | 
			
		||||
typename stream_as<T>::t2 stream_number(T x)
 | 
			
		||||
{
 | 
			
		||||
    return promote<T>::from(x);
 | 
			
		||||
}
 | 
			
		||||
// =================================================================================
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Tests for built-in signed and unsigned types
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// Tag types for selecting tests
 | 
			
		||||
struct unsigned_tag {};
 | 
			
		||||
struct signed_tag {};
 | 
			
		||||
 | 
			
		||||
// Tests for unsigned numbers. The extra default Number parameter works around
 | 
			
		||||
// an MSVC bug.
 | 
			
		||||
template <class Number>
 | 
			
		||||
void test_aux(unsigned_tag, Number*)
 | 
			
		||||
{
 | 
			
		||||
    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<long long>();
 | 
			
		||||
    test<unsigned long long>();
 | 
			
		||||
#elif defined(BOOST_MSVC)
 | 
			
		||||
    // The problem of not having compile-time static class constants other than
 | 
			
		||||
    // enums prevents this from working, since values get truncated.
 | 
			
		||||
    // test<boost::uintmax_t>();
 | 
			
		||||
    // test<boost::intmax_t>();
 | 
			
		||||
#endif
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2133
									
								
								operators.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2133
									
								
								operators.htm
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										896
									
								
								operators_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										896
									
								
								operators_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,896 @@
 | 
			
		||||
//  Demonstrate and test boost/operators.hpp  -------------------------------//
 | 
			
		||||
 | 
			
		||||
//  Copyright Beman Dawes 1999.
 | 
			
		||||
//  See accompanying license for terms and conditions of use.
 | 
			
		||||
 | 
			
		||||
//  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_TEST( true_value(y1) == true_value(y2) );
 | 
			
		||||
        BOOST_TEST( true_value(x1) == true_value(x2) );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_TEST( (x1 < y1) == (x2 < y2) );
 | 
			
		||||
        BOOST_TEST( (x1 <= y1) == (x2 <= y2) );
 | 
			
		||||
        BOOST_TEST( (x1 >= y1) == (x2 >= y2) );
 | 
			
		||||
        BOOST_TEST( (x1 > y1) == (x2 > y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        test_less_than_comparable_aux( x1, y1, x2, y2 );
 | 
			
		||||
        test_less_than_comparable_aux( y1, x1, y2, x2 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_TEST( (x1 == y1) == (x2 == y2) );
 | 
			
		||||
        BOOST_TEST( (x1 != y1) == (x2 != y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        test_equality_comparable_aux( x1, y1, x2, y2 );
 | 
			
		||||
        test_equality_comparable_aux( y1, x1, y2, x2 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        BOOST_TEST( (x1 * y1).value() == (x2 * y2) );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check( x1, y1, x2, y2 );
 | 
			
		||||
        test_multipliable_aux( x1, y1, x2, y2 );
 | 
			
		||||
        test_multipliable_aux( y1, x1, y2, x2 );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  template <class A, class B>
 | 
			
		||||
  void test_value_equality(A a, B b)
 | 
			
		||||
  {
 | 
			
		||||
      BOOST_TEST(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_TEST( (x1++).value() == x2++ );
 | 
			
		||||
        BOOST_TEST( x1.value() == x2 );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class X2>
 | 
			
		||||
    void test_decrementable(X1 x1, X2 x2)
 | 
			
		||||
    {
 | 
			
		||||
        sanity_check( x1, x1, x2, x2 );
 | 
			
		||||
        BOOST_TEST( (x1--).value() == x2-- );
 | 
			
		||||
        BOOST_TEST( x1.value() == x2 );
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template <class X1, class Y1, class X2, class Y2>
 | 
			
		||||
    void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2)
 | 
			
		||||
    {
 | 
			
		||||
        test_less_than_comparable( x1, y1, x2, y2 );
 | 
			
		||||
        test_equality_comparable( x1, y1, x2, y2 );
 | 
			
		||||
        test_multipliable( x1, y1, x2, y2 );
 | 
			
		||||
        test_addable( x1, y1, x2, y2 );
 | 
			
		||||
        test_subtractable( x1, y1, x2, y2 );
 | 
			
		||||
        test_dividable( x1, y1, x2, y2 );
 | 
			
		||||
        test_modable( x1, y1, x2, y2 );
 | 
			
		||||
        test_xorable( x1, y1, x2, y2 );
 | 
			
		||||
        test_andable( x1, y1, x2, y2 );
 | 
			
		||||
        test_orable( x1, y1, x2, y2 );
 | 
			
		||||
        test_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 <= 1200)
 | 
			
		||||
template Wrapped1<int>;
 | 
			
		||||
template Wrapped1<long>;
 | 
			
		||||
template Wrapped1<unsigned int>;
 | 
			
		||||
template Wrapped1<unsigned long>;
 | 
			
		||||
 | 
			
		||||
template Wrapped2<int, int>;
 | 
			
		||||
template Wrapped2<int, signed char>;
 | 
			
		||||
template Wrapped2<long, signed char>;
 | 
			
		||||
template Wrapped2<long, int>;
 | 
			
		||||
template Wrapped2<long, long>;
 | 
			
		||||
template Wrapped2<unsigned int, unsigned int>;
 | 
			
		||||
template Wrapped2<unsigned int, unsigned char>;
 | 
			
		||||
template Wrapped2<unsigned long, unsigned int>;
 | 
			
		||||
template Wrapped2<unsigned long, unsigned char>;
 | 
			
		||||
template Wrapped2<unsigned long, unsigned long>;
 | 
			
		||||
 | 
			
		||||
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_TEST( ((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_TEST( i1.value() == 1 );
 | 
			
		||||
    BOOST_TEST( i2.value() == 2 );
 | 
			
		||||
    BOOST_TEST( i.value() == 0 );
 | 
			
		||||
 | 
			
		||||
    cout << "Created MyInt objects.\n";
 | 
			
		||||
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) );
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( i2 == i );
 | 
			
		||||
    BOOST_TEST( i1 != i2 );
 | 
			
		||||
    BOOST_TEST( i1 <  i2 );
 | 
			
		||||
    BOOST_TEST( i1 <= i2 );
 | 
			
		||||
    BOOST_TEST( i <= i2 );
 | 
			
		||||
    BOOST_TEST( i2 >  i1 );
 | 
			
		||||
    BOOST_TEST( i2 >= i1 );
 | 
			
		||||
    BOOST_TEST( i2 >= i );
 | 
			
		||||
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) );
 | 
			
		||||
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) );
 | 
			
		||||
 | 
			
		||||
    cout << "Performed tests on MyInt objects.\n";
 | 
			
		||||
 | 
			
		||||
    MyLong j1(1);
 | 
			
		||||
    MyLong j2(2);
 | 
			
		||||
    MyLong j;
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( j1.value() == 1 );
 | 
			
		||||
    BOOST_TEST( j2.value() == 2 );
 | 
			
		||||
    BOOST_TEST( j.value() == 0 );
 | 
			
		||||
 | 
			
		||||
    cout << "Created MyLong objects.\n";
 | 
			
		||||
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( j2 == j );
 | 
			
		||||
    BOOST_TEST( 2 == j );
 | 
			
		||||
    BOOST_TEST( j2 == 2 );    
 | 
			
		||||
    BOOST_TEST( j == j2 );
 | 
			
		||||
    BOOST_TEST( j1 != j2 );
 | 
			
		||||
    BOOST_TEST( j1 != 2 );
 | 
			
		||||
    BOOST_TEST( 1 != j2 );
 | 
			
		||||
    BOOST_TEST( j1 <  j2 );
 | 
			
		||||
    BOOST_TEST( 1 <  j2 );
 | 
			
		||||
    BOOST_TEST( j1 <  2 );
 | 
			
		||||
    BOOST_TEST( j1 <= j2 );
 | 
			
		||||
    BOOST_TEST( 1 <= j2 );
 | 
			
		||||
    BOOST_TEST( j1 <= j );
 | 
			
		||||
    BOOST_TEST( j <= j2 );
 | 
			
		||||
    BOOST_TEST( 2 <= j2 );
 | 
			
		||||
    BOOST_TEST( j <= 2 );
 | 
			
		||||
    BOOST_TEST( j2 >  j1 );
 | 
			
		||||
    BOOST_TEST( 2 >  j1 );
 | 
			
		||||
    BOOST_TEST( j2 >  1 );
 | 
			
		||||
    BOOST_TEST( j2 >= j1 );
 | 
			
		||||
    BOOST_TEST( 2 >= j1 );
 | 
			
		||||
    BOOST_TEST( j2 >= 1 );
 | 
			
		||||
    BOOST_TEST( j2 >= j );
 | 
			
		||||
    BOOST_TEST( 2 >= j );
 | 
			
		||||
    BOOST_TEST( j2 >= 2 );
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( (j1 + 2) == 3 );
 | 
			
		||||
    BOOST_TEST( (1 + j2) == 3 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( (j + 2) == 5 );
 | 
			
		||||
    BOOST_TEST( (3 + j2) == 5 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( (j - 1) == 4 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( (j * 2) == 8 );
 | 
			
		||||
    BOOST_TEST( (4 * j2) == 8 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( (j / 2) == 4 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( (j % 3) == 1 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) );
 | 
			
		||||
    
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( (1 | j2 | j) == 7 );
 | 
			
		||||
    BOOST_TEST( (j1 | 2 | j) == 7 );
 | 
			
		||||
    BOOST_TEST( (j1 | j2 | 4) == 7 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( (7 & j2) == 2 );
 | 
			
		||||
    BOOST_TEST( (j & 2) == 2 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) );
 | 
			
		||||
    
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( (3 ^ j1) == 2 );
 | 
			
		||||
    BOOST_TEST( (j ^ 1) == 2 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) );
 | 
			
		||||
    
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) );
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( (j1 << 2) == 4 );
 | 
			
		||||
    BOOST_TEST( (j2 << 1) == 4 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) );
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( (j >> 2) == 1 );
 | 
			
		||||
    BOOST_TEST( (j2 >> 1) == 1 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) );
 | 
			
		||||
    
 | 
			
		||||
    cout << "Performed tests on MyLong objects.\n";
 | 
			
		||||
 | 
			
		||||
    MyChar k1(1);
 | 
			
		||||
    MyChar k2(2);
 | 
			
		||||
    MyChar k;
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( k1.value() == 1 );
 | 
			
		||||
    BOOST_TEST( k2.value() == 2 );
 | 
			
		||||
    BOOST_TEST( k.value() == 0 );
 | 
			
		||||
 | 
			
		||||
    cout << "Created MyChar objects.\n";
 | 
			
		||||
 | 
			
		||||
    PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) );
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( k2 == k );
 | 
			
		||||
    BOOST_TEST( k1 != k2 );
 | 
			
		||||
    BOOST_TEST( k1 <  k2 );
 | 
			
		||||
    BOOST_TEST( k1 <= k2 );
 | 
			
		||||
    BOOST_TEST( k <= k2 );
 | 
			
		||||
    BOOST_TEST( k2 >  k1 );
 | 
			
		||||
    BOOST_TEST( k2 >= k1 );
 | 
			
		||||
    BOOST_TEST( k2 >= k );
 | 
			
		||||
    
 | 
			
		||||
    cout << "Performed tests on MyChar objects.\n";
 | 
			
		||||
 | 
			
		||||
    MyShort l1(1);
 | 
			
		||||
    MyShort l2(2);
 | 
			
		||||
    MyShort l;
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( l1.value() == 1 );
 | 
			
		||||
    BOOST_TEST( l2.value() == 2 );
 | 
			
		||||
    BOOST_TEST( l.value() == 0 );
 | 
			
		||||
 | 
			
		||||
    cout << "Created MyShort objects.\n";
 | 
			
		||||
 | 
			
		||||
    PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( l2 == l );
 | 
			
		||||
    BOOST_TEST( 2 == l );
 | 
			
		||||
    BOOST_TEST( l2 == 2 );    
 | 
			
		||||
    BOOST_TEST( l == l2 );
 | 
			
		||||
    BOOST_TEST( l1 != l2 );
 | 
			
		||||
    BOOST_TEST( l1 != 2 );
 | 
			
		||||
    BOOST_TEST( 1 != l2 );
 | 
			
		||||
    BOOST_TEST( l1 <  l2 );
 | 
			
		||||
    BOOST_TEST( 1 <  l2 );
 | 
			
		||||
    BOOST_TEST( l1 <  2 );
 | 
			
		||||
    BOOST_TEST( l1 <= l2 );
 | 
			
		||||
    BOOST_TEST( 1 <= l2 );
 | 
			
		||||
    BOOST_TEST( l1 <= l );
 | 
			
		||||
    BOOST_TEST( l <= l2 );
 | 
			
		||||
    BOOST_TEST( 2 <= l2 );
 | 
			
		||||
    BOOST_TEST( l <= 2 );
 | 
			
		||||
    BOOST_TEST( l2 >  l1 );
 | 
			
		||||
    BOOST_TEST( 2 >  l1 );
 | 
			
		||||
    BOOST_TEST( l2 >  1 );
 | 
			
		||||
    BOOST_TEST( l2 >= l1 );
 | 
			
		||||
    BOOST_TEST( 2 >= l1 );
 | 
			
		||||
    BOOST_TEST( l2 >= 1 );
 | 
			
		||||
    BOOST_TEST( l2 >= l );
 | 
			
		||||
    BOOST_TEST( 2 >= l );
 | 
			
		||||
    BOOST_TEST( l2 >= 2 );
 | 
			
		||||
    
 | 
			
		||||
    cout << "Performed tests on MyShort objects.\n";
 | 
			
		||||
    
 | 
			
		||||
    MyDoubleInt di1(1);
 | 
			
		||||
    MyDoubleInt di2(2.);
 | 
			
		||||
    MyDoubleInt half(0.5);
 | 
			
		||||
    MyDoubleInt di;
 | 
			
		||||
    MyDoubleInt tmp;
 | 
			
		||||
 | 
			
		||||
    BOOST_TEST( di1.value() == 1 );
 | 
			
		||||
    BOOST_TEST( di2.value() == 2 );
 | 
			
		||||
    BOOST_TEST( di2.value() == 2 );
 | 
			
		||||
    BOOST_TEST( di.value() == 0 );
 | 
			
		||||
 | 
			
		||||
    cout << "Created MyDoubleInt objects.\n";
 | 
			
		||||
 | 
			
		||||
    PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( di2 == di );
 | 
			
		||||
    BOOST_TEST( 2 == di );
 | 
			
		||||
    BOOST_TEST( di == 2 );
 | 
			
		||||
    BOOST_TEST( di1 < di2 );
 | 
			
		||||
    BOOST_TEST( 1 < di2 );
 | 
			
		||||
    BOOST_TEST( di1 <= di2 );
 | 
			
		||||
    BOOST_TEST( 1 <= di2 );
 | 
			
		||||
    BOOST_TEST( di2 > di1 );
 | 
			
		||||
    BOOST_TEST( di2 > 1 );
 | 
			
		||||
    BOOST_TEST( di2 >= di1 );
 | 
			
		||||
    BOOST_TEST( di2 >= 1 );
 | 
			
		||||
    BOOST_TEST( di1 / di2 == half );
 | 
			
		||||
    BOOST_TEST( di1 / 2 == half );
 | 
			
		||||
    BOOST_TEST( 1 / di2 == half );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=2) == half) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=di2) == half) );
 | 
			
		||||
    BOOST_TEST( di1 * di2 == di2 );
 | 
			
		||||
    BOOST_TEST( di1 * 2 == di2 );
 | 
			
		||||
    BOOST_TEST( 1 * di2 == di2 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=2) == di2) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=di2) == di2) );
 | 
			
		||||
    BOOST_TEST( di2 - di1 == di1 );
 | 
			
		||||
    BOOST_TEST( di2 - 1 == di1 );
 | 
			
		||||
    BOOST_TEST( 2 - di1 == di1 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=1) == di1) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=di1) == di1) );
 | 
			
		||||
    BOOST_TEST( di1 + di1 == di2 );
 | 
			
		||||
    BOOST_TEST( di1 + 1 == di2 );
 | 
			
		||||
    BOOST_TEST( 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_TEST( li1.value() == 1 );
 | 
			
		||||
    BOOST_TEST( li2.value() == 2 );
 | 
			
		||||
    BOOST_TEST( li.value() == 0 );
 | 
			
		||||
 | 
			
		||||
    cout << "Created MyLongInt objects.\n";
 | 
			
		||||
 | 
			
		||||
    PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) );
 | 
			
		||||
    
 | 
			
		||||
    BOOST_TEST( li2 == li );
 | 
			
		||||
    BOOST_TEST( 2 == li );
 | 
			
		||||
    BOOST_TEST( li == 2 );
 | 
			
		||||
    BOOST_TEST( li1 < li2 );
 | 
			
		||||
    BOOST_TEST( 1 < li2 );
 | 
			
		||||
    BOOST_TEST( li1 <= li2 );
 | 
			
		||||
    BOOST_TEST( 1 <= li2 );
 | 
			
		||||
    BOOST_TEST( li2 > li1 );
 | 
			
		||||
    BOOST_TEST( li2 > 1 );
 | 
			
		||||
    BOOST_TEST( li2 >= li1 );
 | 
			
		||||
    BOOST_TEST( li2 >= 1 );
 | 
			
		||||
    BOOST_TEST( li1 % li2 == li1 );
 | 
			
		||||
    BOOST_TEST( li1 % 2 == li1 );
 | 
			
		||||
    BOOST_TEST( 1 % li2 == li1 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=2) == li1) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=li2) == li1) );
 | 
			
		||||
    BOOST_TEST( li1 / li2 == 0 );
 | 
			
		||||
    BOOST_TEST( li1 / 2 == 0 );
 | 
			
		||||
    BOOST_TEST( 1 / li2 == 0 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=2) == 0) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=li2) == 0) );
 | 
			
		||||
    BOOST_TEST( li1 * li2 == li2 );
 | 
			
		||||
    BOOST_TEST( li1 * 2 == li2 );
 | 
			
		||||
    BOOST_TEST( 1 * li2 == li2 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=2) == li2) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=li2) == li2) );
 | 
			
		||||
    BOOST_TEST( li2 - li1 == li1 );
 | 
			
		||||
    BOOST_TEST( li2 - 1 == li1 );
 | 
			
		||||
    BOOST_TEST( 2 - li1 == li1 );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=1) == li1) );
 | 
			
		||||
    PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=li1) == li1) );
 | 
			
		||||
    BOOST_TEST( li1 + li1 == li2 );
 | 
			
		||||
    BOOST_TEST( li1 + 1 == li2 );
 | 
			
		||||
    BOOST_TEST( 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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										103
									
								
								projection_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								projection_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,103 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <boost/iterator/transform_iterator.hpp>
 | 
			
		||||
 | 
			
		||||
struct personnel_record {
 | 
			
		||||
  personnel_record(std::string n, int id) : m_name(n), m_ID(id) { }
 | 
			
		||||
  std::string m_name;
 | 
			
		||||
  int m_ID;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct select_name {
 | 
			
		||||
  typedef personnel_record argument_type;
 | 
			
		||||
  typedef std::string const& result_type;
 | 
			
		||||
  const std::string& operator()(const personnel_record& r) const {
 | 
			
		||||
    return r.m_name;
 | 
			
		||||
  }
 | 
			
		||||
  std::string& operator()(personnel_record& r) const {
 | 
			
		||||
    return r.m_name;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct select_ID {
 | 
			
		||||
  typedef personnel_record argument_type;
 | 
			
		||||
  typedef int& result_type;
 | 
			
		||||
  const int& operator()(const personnel_record& r) const {
 | 
			
		||||
    return r.m_ID;
 | 
			
		||||
  }
 | 
			
		||||
  int& operator()(personnel_record& r) const {
 | 
			
		||||
    return r.m_ID;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  std::list<personnel_record> personnel_list;
 | 
			
		||||
 | 
			
		||||
  personnel_list.push_back(personnel_record("Barney", 13423));
 | 
			
		||||
  personnel_list.push_back(personnel_record("Fred", 12343));
 | 
			
		||||
  personnel_list.push_back(personnel_record("Wilma", 62454));
 | 
			
		||||
  personnel_list.push_back(personnel_record("Betty", 20490));
 | 
			
		||||
 | 
			
		||||
  // Example of using transform_iterator to print out the names in the
 | 
			
		||||
  // personnel list using a projection.
 | 
			
		||||
 | 
			
		||||
  boost::transform_iterator<
 | 
			
		||||
      select_name
 | 
			
		||||
    , std::list<personnel_record>::iterator
 | 
			
		||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
    , std::string
 | 
			
		||||
#endif 
 | 
			
		||||
  >
 | 
			
		||||
    personnel_first(personnel_list.begin()),
 | 
			
		||||
    personnel_last(personnel_list.end());
 | 
			
		||||
 | 
			
		||||
  std::copy(personnel_first, personnel_last,
 | 
			
		||||
            std::ostream_iterator<std::string>(std::cout, "\n"));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  // Example of using transform_iterator with const_iterators to
 | 
			
		||||
  // assign new ID numbers to the personnel.
 | 
			
		||||
  
 | 
			
		||||
  boost::transform_iterator<
 | 
			
		||||
      select_ID, std::list<personnel_record>::iterator
 | 
			
		||||
 > ID_first(personnel_list.begin()),
 | 
			
		||||
    ID_last(personnel_list.end());
 | 
			
		||||
 | 
			
		||||
  int new_id = 0;
 | 
			
		||||
  while (ID_first != ID_last) {
 | 
			
		||||
    *ID_first = new_id++;
 | 
			
		||||
    ++ID_first;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    boost::transform_iterator<
 | 
			
		||||
      select_ID, std::list<personnel_record>::const_iterator, int const&
 | 
			
		||||
    >
 | 
			
		||||
    const_ID_first(personnel_list.begin()),
 | 
			
		||||
    const_ID_last(personnel_list.end());
 | 
			
		||||
 | 
			
		||||
  std::copy(const_ID_first, const_ID_last,
 | 
			
		||||
            std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
  // Example of using make_const_projection_iterator()
 | 
			
		||||
  // to print out the names in the personnel list again.
 | 
			
		||||
  std::copy(
 | 
			
		||||
      boost::make_transform_iterator<select_name>(personnel_list.begin())
 | 
			
		||||
    , boost::make_transform_iterator<select_name>(personnel_list.end())
 | 
			
		||||
    , std::ostream_iterator<std::string>(std::cout, "\n"));
 | 
			
		||||
#endif
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										115
									
								
								ref_ct_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								ref_ct_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
			
		||||
// 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/same_traits.hpp>
 | 
			
		||||
#include <boost/static_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)
 | 
			
		||||
{
 | 
			
		||||
    BOOST_STATIC_ASSERT((boost::is_same<R,Ref>::value));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template< typename R, typename Ref >
 | 
			
		||||
void unwrap_reference_test(Ref)
 | 
			
		||||
{
 | 
			
		||||
    typedef typename boost::unwrap_reference<Ref>::type type;
 | 
			
		||||
    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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										74
									
								
								ref_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								ref_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
			
		||||
 | 
			
		||||
// 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_TEST(passthru(ref(x)) == &x);
 | 
			
		||||
        BOOST_TEST(&ref(x).get() == &x);
 | 
			
		||||
 | 
			
		||||
        BOOST_TEST(cref_passthru(cref(x)) == &x);
 | 
			
		||||
        BOOST_TEST(&cref(x).get() == &x);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace unnamed
 | 
			
		||||
 | 
			
		||||
int test_main(int, char * [])
 | 
			
		||||
{
 | 
			
		||||
    ref_wrapper<int>::test(1);
 | 
			
		||||
    ref_wrapper<int const>::test(1);
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										47
									
								
								reverse_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								reverse_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,47 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <boost/iterator/reverse_iterator.hpp>
 | 
			
		||||
#include <boost/detail/iterator.hpp>
 | 
			
		||||
 | 
			
		||||
//boost::detail::iterator_traits
 | 
			
		||||
int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  char letters_[] = "hello world!";
 | 
			
		||||
  const int N = sizeof(letters_)/sizeof(char) - 1;
 | 
			
		||||
  typedef char* base_iterator;
 | 
			
		||||
  base_iterator letters(letters_);
 | 
			
		||||
  
 | 
			
		||||
  std::cout << "original sequence of letters:\t"
 | 
			
		||||
            << letters_ << std::endl;
 | 
			
		||||
 | 
			
		||||
  std::sort(letters, letters + N);
 | 
			
		||||
 | 
			
		||||
  // Use reverse_iterator_generator to print a sequence
 | 
			
		||||
  // of letters in reverse order.
 | 
			
		||||
  
 | 
			
		||||
  boost::reverse_iterator<base_iterator>
 | 
			
		||||
    reverse_letters_first(letters + N),
 | 
			
		||||
    reverse_letters_last(letters);
 | 
			
		||||
 | 
			
		||||
  std::cout << "letters in descending order:\t";
 | 
			
		||||
  std::copy(reverse_letters_first, reverse_letters_last,
 | 
			
		||||
            std::ostream_iterator<char>(std::cout));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  // Use make_reverse_iterator() to print the sequence
 | 
			
		||||
  // of letters in reverse-reverse order.
 | 
			
		||||
 | 
			
		||||
  std::cout << "letters in ascending order:\t";
 | 
			
		||||
  std::copy(boost::make_reverse_iterator(reverse_letters_last),
 | 
			
		||||
            boost::make_reverse_iterator(reverse_letters_first),
 | 
			
		||||
            std::ostream_iterator<char>(std::cout));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										323
									
								
								shared_container_iterator.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										323
									
								
								shared_container_iterator.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,323 @@
 | 
			
		||||
<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="../../c++boost.gif" alt="c++boost.gif (8819 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 Ronald Garcia 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>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										41
									
								
								shared_iterator_example1.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								shared_iterator_example1.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
// (C) Copyright Ronald Garcia 2002. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include "boost/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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								shared_iterator_example2.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								shared_iterator_example2.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
// (C) Copyright Ronald Garcia 2002. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include "boost/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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										40
									
								
								shared_iterator_example3.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								shared_iterator_example3.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
			
		||||
// (C) Copyright Ronald Garcia 2002. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
#include "boost/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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								shared_iterator_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								shared_iterator_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
			
		||||
// (C) Copyright Ronald Garcia 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.
 | 
			
		||||
 | 
			
		||||
#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
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										43
									
								
								test/Jamfile
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
# 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/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Testing Jamfile autogenerated from XML source
 | 
			
		||||
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 ;
 | 
			
		||||
 | 
			
		||||
test-suite utility
 | 
			
		||||
    : 
 | 
			
		||||
        [ run ../iterator_traits_test.cpp ]
 | 
			
		||||
        [ run ../iterators_test.cpp $(test_monitor) ]
 | 
			
		||||
        [ compile-fail ../noncopyable_test.cpp ]
 | 
			
		||||
        [ run ../numeric_traits_test.cpp ]
 | 
			
		||||
        [ run ../operators_test.cpp $(test_monitor) ]
 | 
			
		||||
        [ run ../binary_search_test.cpp $(test_monitor) ]
 | 
			
		||||
        [ run ../call_traits_test.cpp : -u ]
 | 
			
		||||
        [ compile-fail ../checked_delete_test.cpp ]
 | 
			
		||||
        [ run ../compressed_pair_test.cpp $(test_monitor) : -u ]
 | 
			
		||||
        [ run ../addressof_test.cpp $(test_monitor) ]
 | 
			
		||||
        [ run ../ref_test.cpp $(test_monitor) ]
 | 
			
		||||
        [ run ../enable_if_constructors.cpp $(test_monitor) ]
 | 
			
		||||
        [ run ../enable_if_dummy_arg_disambiguation.cpp $(test_monitor) ]
 | 
			
		||||
        [ run ../enable_if_lazy.cpp $(test_monitor) ]
 | 
			
		||||
        [ run ../enable_if_lazy_test.cpp $(test_monitor) ]
 | 
			
		||||
        [ run ../enable_if_member_templates.cpp $(test_monitor) ]
 | 
			
		||||
        [ run ../enable_if_namespace_disambiguation.cpp $(test_monitor) ]
 | 
			
		||||
        [ run ../enable_if_no_disambiguation.cpp $(test_monitor) ]
 | 
			
		||||
        [ run ../enable_if_partial_specializations.cpp $(test_monitor) ]
 | 
			
		||||
        [ run next_prior_test.cpp $(test_monitor) ]          
 | 
			
		||||
    ;
 | 
			
		||||
							
								
								
									
										33
									
								
								test/Jamfile.v2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								test/Jamfile.v2
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,33 @@
 | 
			
		||||
# 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 ;
 | 
			
		||||
 | 
			
		||||
test-suite utility
 | 
			
		||||
    : 
 | 
			
		||||
        [ run ../iterator_traits_test.cpp ]
 | 
			
		||||
        [ run ../iterators_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 ]
 | 
			
		||||
        [ run ../binary_search_test.cpp ../../test/build//boost_test_exec_monitor ]
 | 
			
		||||
        [ 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 ../addressof_test.cpp ../../test/build//boost_test_exec_monitor ]
 | 
			
		||||
        [ run ../ref_test.cpp ../../test/build//boost_test_exec_monitor ]
 | 
			
		||||
        [ run ../enable_if_constructors.cpp ../../test/build/boost_test_exec_monitor ]
 | 
			
		||||
        [ run ../enable_if_dummy_arg_disambiguation.cpp ../../test/build/boost_test_exec_monitor ]
 | 
			
		||||
        [ run ../enable_if_lazy.cpp ../../test/build/boost_test_exec_monitor ]
 | 
			
		||||
        [ run ../enable_if_lazy_test.cpp ../../test/build/boost_test_exec_monitor ]
 | 
			
		||||
        [ run ../enable_if_member_templates.cpp ../../test/build/boost_test_exec_monitor ]
 | 
			
		||||
        [ run ../enable_if_namespace_disambiguation.cpp ../../test/build/boost_test_exec_monitor ]
 | 
			
		||||
        [ run ../enable_if_no_disambiguation.cpp ../../test/build/boost_test_exec_monitor ]
 | 
			
		||||
        [ run ../enable_if_partial_specializations.cpp ../../test/build/boost_test_exec_monitor ]
 | 
			
		||||
    ;
 | 
			
		||||
							
								
								
									
										79
									
								
								test/next_prior_test.cpp
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										79
									
								
								test/next_prior_test.cpp
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,79 @@
 | 
			
		||||
// 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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										60
									
								
								throw_exception.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								throw_exception.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
			
		||||
<!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="../../c++boost.gif" alt="c++boost.gif (8819 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>
 | 
			
		||||
							
								
								
									
										76
									
								
								transform_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								transform_iterator_example.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and
 | 
			
		||||
// distribute this software is granted provided this copyright notice appears
 | 
			
		||||
// in all copies. This software is provided "as is" without express or implied
 | 
			
		||||
// warranty, and with no claim as to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include <functional>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <boost/iterator/transform_iterator.hpp>
 | 
			
		||||
 | 
			
		||||
// What a bummer. We can't use std::binder1st with transform iterator
 | 
			
		||||
// because it does not have a default constructor. Here's a version
 | 
			
		||||
// that does.
 | 
			
		||||
 | 
			
		||||
namespace boost {
 | 
			
		||||
 | 
			
		||||
  template <class Operation> 
 | 
			
		||||
  class binder1st
 | 
			
		||||
    : public std::unary_function<typename Operation::second_argument_type,
 | 
			
		||||
                                 typename Operation::result_type> {
 | 
			
		||||
  protected:
 | 
			
		||||
    Operation op;
 | 
			
		||||
    typename Operation::first_argument_type value;
 | 
			
		||||
  public:
 | 
			
		||||
    binder1st() { } // this had to be added!
 | 
			
		||||
    binder1st(const Operation& x,
 | 
			
		||||
              const typename Operation::first_argument_type& y)
 | 
			
		||||
        : op(x), value(y) {}
 | 
			
		||||
    typename Operation::result_type
 | 
			
		||||
    operator()(const typename Operation::second_argument_type& x) const {
 | 
			
		||||
      return op(value, x); 
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  template <class Operation, class T>
 | 
			
		||||
  inline binder1st<Operation> bind1st(const Operation& op, const T& x) {
 | 
			
		||||
    typedef typename Operation::first_argument_type arg1_type;
 | 
			
		||||
    return binder1st<Operation>(op, arg1_type(x));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  // This is a simple example of using the transform_iterators class to
 | 
			
		||||
  // generate iterators that multiply the value returned by dereferencing
 | 
			
		||||
  // the iterator. In this case we are multiplying by 2.
 | 
			
		||||
  // Would be cooler to use lambda library in this example.
 | 
			
		||||
 | 
			
		||||
  int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
 | 
			
		||||
  const int N = sizeof(x)/sizeof(int);
 | 
			
		||||
 | 
			
		||||
  typedef boost::binder1st< std::multiplies<int> > Function;
 | 
			
		||||
  typedef boost::transform_iterator<Function, int*> doubling_iterator;
 | 
			
		||||
 | 
			
		||||
  doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)),
 | 
			
		||||
    i_end(x + N, boost::bind1st(std::multiplies<int>(), 2));
 | 
			
		||||
 | 
			
		||||
  std::cout << "multiplying the array by 2:" << std::endl;
 | 
			
		||||
  while (i != i_end)
 | 
			
		||||
    std::cout << *i++ << " ";
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
 | 
			
		||||
  std::cout << "adding 4 to each element in the array:" << std::endl;
 | 
			
		||||
 | 
			
		||||
  std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)),
 | 
			
		||||
            boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
 | 
			
		||||
            std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										151
									
								
								utility.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								utility.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,151 @@
 | 
			
		||||
<html>
 | 
			
		||||
	<head>
 | 
			
		||||
		<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
 | 
			
		||||
		<title>Header boost/utility.hpp Documentation</title>
 | 
			
		||||
	</head>
 | 
			
		||||
	<body bgcolor="#FFFFFF" text="#000000">
 | 
			
		||||
		<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" WIDTH="277" HEIGHT="86">Header
 | 
			
		||||
			<a href="../../boost/utility.hpp">boost/utility.hpp</a></h1>
 | 
			
		||||
		<p>The entire contents of the header <code><a href="../../boost/utility.hpp"><boost/utility.hpp></a></code>
 | 
			
		||||
			are in <code>namespace boost</code>.</p>
 | 
			
		||||
		<h2>Contents</h2>
 | 
			
		||||
		<ul>
 | 
			
		||||
			<li>
 | 
			
		||||
				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>
 | 
			
		||||
		</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>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
 | 
			
		||||
-->23 December, 2003<!--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
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								value_init.htm
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,219 @@
 | 
			
		||||
<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="../../c++boost.gif" 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="#intro">Rationale</a></dt>
 | 
			
		||||
  <dt><a href="#rationale">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="into"></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>impll-defined</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>
 | 
			
		||||
							
								
								
									
										119
									
								
								value_init_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								value_init_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,119 @@
 | 
			
		||||
// (C) 2002, Fernando Luis Cacciola Carballal.
 | 
			
		||||
//
 | 
			
		||||
// This material is provided "as is", with absolutely no warranty expressed
 | 
			
		||||
// or implied. Any use is at your own risk.
 | 
			
		||||
//
 | 
			
		||||
// Permission to use or copy this software for any purpose is hereby granted
 | 
			
		||||
// without fee, provided the above notices are retained on all copies.
 | 
			
		||||
// Permission to modify the code and to distribute modified code is granted,
 | 
			
		||||
// provided the above notices are retained, and a notice that the code was
 | 
			
		||||
// modified is included with the above copyright notice.
 | 
			
		||||
//
 | 
			
		||||
// 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
 | 
			
		||||
 | 
			
		||||
#define BOOST_INCLUDE_MAIN
 | 
			
		||||
#include "boost/test/test_tools.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_TEST ( y == x ) ;
 | 
			
		||||
  BOOST_TEST ( y == get(x) ) ;
 | 
			
		||||
  static_cast<T&>(x) = z ;
 | 
			
		||||
  get(x) = z ;
 | 
			
		||||
  BOOST_TEST ( x == z ) ;
 | 
			
		||||
 | 
			
		||||
  boost::value_initialized<T> const x_c ;
 | 
			
		||||
  BOOST_TEST ( y == x_c ) ;
 | 
			
		||||
  BOOST_TEST ( y == get(x_c) ) ;
 | 
			
		||||
  static_cast<T&>(x_c) = z ;
 | 
			
		||||
  BOOST_TEST ( x_c == z ) ;
 | 
			
		||||
  #ifdef PRODUCE_ERROR_1
 | 
			
		||||
  get(x_c) = z ; // this should produce an ERROR
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  boost::value_initialized<T const> cx ;
 | 
			
		||||
  BOOST_TEST ( y == cx ) ;
 | 
			
		||||
  BOOST_TEST ( y == get(cx) ) ;
 | 
			
		||||
  #ifdef PRODUCE_ERROR_2
 | 
			
		||||
  get(cx) = z ; // this should produce an ERROR
 | 
			
		||||
  #endif
 | 
			
		||||
 | 
			
		||||
  boost::value_initialized<T const> const cx_c ;
 | 
			
		||||
  BOOST_TEST ( y == cx_c ) ;
 | 
			
		||||
  BOOST_TEST ( y == get(cx_c) ) ;
 | 
			
		||||
  #ifdef PRODUCE_ERROR_3
 | 
			
		||||
  get(cx_c) = z ; // this should produce an ERROR
 | 
			
		||||
  #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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user