mirror of
				https://github.com/boostorg/utility.git
				synced 2025-11-04 02:11:45 +01:00 
			
		
		
		
	Compare commits
	
		
			29 Commits
		
	
	
		
			svn-branch
			...
			boost-1.25
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					4d452a1170 | ||
| 
						 | 
					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 | 
@@ -85,7 +85,7 @@ Once that is done we can drop Multi-Pass Input Iterator.
 | 
			
		||||
<TABLE>
 | 
			
		||||
<TR valign=top>
 | 
			
		||||
<TD nowrap>Copyright © 2000</TD><TD>
 | 
			
		||||
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
 | 
			
		||||
<a HREF="../../people/jeremy_siek.htm">Jeremy Siek</a>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
 | 
			
		||||
</TD></TR></TABLE>
 | 
			
		||||
 | 
			
		||||
</BODY>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										341
									
								
								base_from_member.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										341
									
								
								base_from_member.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,341 @@
 | 
			
		||||
<!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.  Ron Klatchko
 | 
			
		||||
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;
 | 
			
		||||
 | 
			
		||||
    explicit  base_from_member();
 | 
			
		||||
 | 
			
		||||
    template< typename T1 >
 | 
			
		||||
    explicit  base_from_member( T1 x1 );
 | 
			
		||||
 | 
			
		||||
    //...
 | 
			
		||||
 | 
			
		||||
    template< typename T1, typename T2, typename T3 >
 | 
			
		||||
    explicit  base_from_member( T1 x1, T2 x2, T3 x3 );
 | 
			
		||||
};
 | 
			
		||||
</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 three) 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>Ron Klatchko (<a href="mailto:ron@crl.com">ron@crl.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: 22 August 2001</p>
 | 
			
		||||
 | 
			
		||||
<p>Copyright © boost.org 2001.  Permission to copy, use, modify,
 | 
			
		||||
sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies.  This document is provided "as
 | 
			
		||||
is" without express or implied warranty, and with no claim as to
 | 
			
		||||
its suitability for any purpose.</p>
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										597
									
								
								base_from_member_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										597
									
								
								base_from_member_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,597 @@
 | 
			
		||||
//  Boost test program for base-from-member class templates  -----------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Daryle Walker 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
 | 
			
		||||
//  29 Aug 2001  Initial Version (Daryle Walker)
 | 
			
		||||
 | 
			
		||||
#define  BOOST_INCLUDE_MAIN
 | 
			
		||||
#include <boost/test/test_tools.hpp>  // for BOOST_TEST, main
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>   // for BOOST_NO_MEMBER_TEMPLATES
 | 
			
		||||
#include <boost/cstdlib.hpp>  // for boost::exit_success
 | 
			
		||||
#include <boost/utility.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
 | 
			
		||||
    : 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_TEST( obj_reg.db_.empty() );
 | 
			
		||||
    BOOST_TEST( obj_reg.defrauders_in_.empty() );
 | 
			
		||||
    BOOST_TEST( obj_reg.defrauders_out_.empty() );
 | 
			
		||||
    BOOST_TEST( obj_reg.overeager_.empty() );
 | 
			
		||||
    BOOST_TEST( obj_reg.overkilled_.empty() );
 | 
			
		||||
 | 
			
		||||
    // Make a separate block to examine pre- and post-effects
 | 
			
		||||
    {
 | 
			
		||||
        using std::cout;
 | 
			
		||||
        using std::endl;
 | 
			
		||||
 | 
			
		||||
        bad_class  bc;
 | 
			
		||||
        BOOST_TEST( obj_reg.db_.size() == 3 );
 | 
			
		||||
        BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
 | 
			
		||||
 | 
			
		||||
        good_class_1  gc1;
 | 
			
		||||
        BOOST_TEST( obj_reg.db_.size() == 6 );
 | 
			
		||||
        BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
 | 
			
		||||
 | 
			
		||||
        good_class_2  gc2;
 | 
			
		||||
        BOOST_TEST( obj_reg.db_.size() == 11 );
 | 
			
		||||
        BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
 | 
			
		||||
 | 
			
		||||
        BOOST_TEST( obj_reg.defrauders_out_.empty() );
 | 
			
		||||
        BOOST_TEST( obj_reg.overeager_.empty() );
 | 
			
		||||
        BOOST_TEST( 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_TEST( obj_reg.db_.empty() );
 | 
			
		||||
    BOOST_TEST( obj_reg.defrauders_in_.size() == 1 );
 | 
			
		||||
    BOOST_TEST( obj_reg.defrauders_out_.size() == 1 );
 | 
			
		||||
    BOOST_TEST( obj_reg.overeager_.empty() );
 | 
			
		||||
    BOOST_TEST( 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
 | 
			
		||||
}
 | 
			
		||||
@@ -17,6 +17,10 @@
 | 
			
		||||
#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:
 | 
			
		||||
@@ -44,7 +48,7 @@ struct contained
 | 
			
		||||
   reference get() { return v_; }
 | 
			
		||||
   const_reference const_get()const { return v_; }
 | 
			
		||||
   // pass value:
 | 
			
		||||
   void call(param_type p){}
 | 
			
		||||
   void call(param_type){}
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -69,7 +73,7 @@ struct contained<T[N]>
 | 
			
		||||
   // return by_ref:
 | 
			
		||||
   reference get() { return v_; }
 | 
			
		||||
   const_reference const_get()const { return v_; }
 | 
			
		||||
   void call(param_type p){}
 | 
			
		||||
   void call(param_type){}
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -181,6 +185,12 @@ 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_; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -193,6 +203,7 @@ int main(int argc, char *argv[ ])
 | 
			
		||||
   int i = 2;
 | 
			
		||||
   c2(i);
 | 
			
		||||
   int* pi = &i;
 | 
			
		||||
   int a[2] = {1,2};
 | 
			
		||||
#if (defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)) && !defined(__ICL)
 | 
			
		||||
   call_traits_checker<int*> c3;
 | 
			
		||||
   c3(pi);
 | 
			
		||||
@@ -201,15 +212,14 @@ int main(int argc, char *argv[ ])
 | 
			
		||||
   call_traits_checker<const int&> c5;
 | 
			
		||||
   c5(i);
 | 
			
		||||
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__)
 | 
			
		||||
   int a[2] = {1,2};
 | 
			
		||||
   call_traits_checker<int[2]> c6;
 | 
			
		||||
   c6(a);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
   check_wrap(wrap(2), 2);
 | 
			
		||||
   const char ca[4] = "abc";
 | 
			
		||||
   // compiler can't deduce this for some reason:
 | 
			
		||||
   //const char ca[4] = "abc";
 | 
			
		||||
   //check_wrap(wrap(ca), ca);
 | 
			
		||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
   check_wrap(wrap(a), a);
 | 
			
		||||
@@ -312,6 +322,19 @@ void call_traits_test<T, isarray>::assert_construct(typename call_traits_test<T,
 | 
			
		||||
   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>
 | 
			
		||||
@@ -348,6 +371,17 @@ void call_traits_test<T, true>::assert_construct(typename boost::call_traits<T>:
 | 
			
		||||
   param_type p2(v);
 | 
			
		||||
   param_type p3(r);
 | 
			
		||||
   param_type p4(p);
 | 
			
		||||
   
 | 
			
		||||
   unused_variable(v2);
 | 
			
		||||
   unused_variable(v3);
 | 
			
		||||
   unused_variable(v4);
 | 
			
		||||
   unused_variable(v5);
 | 
			
		||||
   unused_variable(r2);
 | 
			
		||||
   unused_variable(cr2);
 | 
			
		||||
   unused_variable(cr3);
 | 
			
		||||
   unused_variable(p2);
 | 
			
		||||
   unused_variable(p3);
 | 
			
		||||
   unused_variable(p4);
 | 
			
		||||
}
 | 
			
		||||
#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
 | 
			
		||||
//
 | 
			
		||||
 
 | 
			
		||||
@@ -21,8 +21,8 @@ defined inside namespace boost.</p>
 | 
			
		||||
 | 
			
		||||
<p>The class compressed pair is very similar to std::pair, but if
 | 
			
		||||
either of the template arguments are empty classes, then the
 | 
			
		||||
"empty member optimisation" is applied to compress the
 | 
			
		||||
size of the pair.</p>
 | 
			
		||||
"empty base-class optimisation" is applied to compress
 | 
			
		||||
the size of the pair.</p>
 | 
			
		||||
 | 
			
		||||
<pre>template <class T1, class T2>
 | 
			
		||||
class compressed_pair
 | 
			
		||||
 
 | 
			
		||||
@@ -199,7 +199,7 @@ struct compressed_pair_reference1_tester
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_reference1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
 | 
			
		||||
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:
 | 
			
		||||
@@ -225,7 +225,7 @@ struct compressed_pair_reference2_tester
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_reference2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
 | 
			
		||||
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:
 | 
			
		||||
@@ -252,7 +252,7 @@ struct compressed_pair_array1_tester
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_array1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
 | 
			
		||||
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;
 | 
			
		||||
@@ -282,7 +282,7 @@ struct compressed_pair_array2_tester
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_array2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
 | 
			
		||||
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;
 | 
			
		||||
@@ -312,7 +312,7 @@ struct compressed_pair_array_tester
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T1, class T2>
 | 
			
		||||
void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
 | 
			
		||||
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;
 | 
			
		||||
@@ -329,7 +329,7 @@ void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_para
 | 
			
		||||
   BOOST_TEST(sizeof(T2) == sizeof(cp1.second()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int test_main(int argc, char *argv[ ])
 | 
			
		||||
int test_main(int, char **)
 | 
			
		||||
{
 | 
			
		||||
   // declare some variables to pass to the tester:
 | 
			
		||||
   non_empty1 ne1(2);
 | 
			
		||||
 
 | 
			
		||||
@@ -308,7 +308,7 @@ implementation, the <tt>difference_type</tt> for any variable-length signed
 | 
			
		||||
integer type <tt>T</tt> is <tt>T</tt> itself.
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --></p>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" --></p>
 | 
			
		||||
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,7 @@
 | 
			
		||||
#include <climits>
 | 
			
		||||
#include <iterator>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <boost/utility.hpp>
 | 
			
		||||
#include <boost/tuple/tuple.hpp>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <cassert>
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,9 @@
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  25 Jun 01 output_iterator_helper changes: removed default template 
 | 
			
		||||
//            parameters, added support for self-proxying, additional 
 | 
			
		||||
//            documentation and tests (Aleksey Gurtovoy)
 | 
			
		||||
//  29 May 01 Added operator classes for << and >>.  Added input and output
 | 
			
		||||
//            iterator helper classes.  Added classes to connect equality and
 | 
			
		||||
//            relational operators.  Added classes for groups of related
 | 
			
		||||
@@ -701,17 +704,17 @@ struct input_iterator_helper
 | 
			
		||||
  , dereferenceable<T, P
 | 
			
		||||
  , boost::iterator<std::input_iterator_tag, V, D, P, R
 | 
			
		||||
    > > > > {};
 | 
			
		||||
#ifndef BOOST_MSVC
 | 
			
		||||
template <class T,
 | 
			
		||||
          class V = void,
 | 
			
		||||
          class D = void,
 | 
			
		||||
          class P = void,
 | 
			
		||||
          class R = void>
 | 
			
		||||
 | 
			
		||||
template<class Derived>
 | 
			
		||||
struct output_iterator_helper
 | 
			
		||||
  : incrementable<T
 | 
			
		||||
  , boost::iterator<std::output_iterator_tag, V, D, P, R
 | 
			
		||||
    > > {};
 | 
			
		||||
#endif
 | 
			
		||||
  : boost::incrementable<Derived
 | 
			
		||||
  , boost::iterator<std::output_iterator_tag, void, void, void, void
 | 
			
		||||
  > >
 | 
			
		||||
{
 | 
			
		||||
  Derived& operator*()  { return static_cast<Derived&>(*this); }
 | 
			
		||||
  Derived& operator++() { return static_cast<Derived&>(*this); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <class T,
 | 
			
		||||
          class V,
 | 
			
		||||
          class D = std::ptrdiff_t,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										55
									
								
								include/boost/ref.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								include/boost/ref.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
			
		||||
#ifndef BOOST_REF_HPP_INCLUDED
 | 
			
		||||
#define BOOST_REF_HPP_INCLUDED
 | 
			
		||||
 | 
			
		||||
#if _MSC_VER >= 1020
 | 
			
		||||
#pragma once
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
//  ref.hpp - ref/cref, useful helper functions
 | 
			
		||||
//
 | 
			
		||||
//  Version 1.00.0003 (2001-08-22)
 | 
			
		||||
//
 | 
			
		||||
//  Copyright (C) 1999, 2000 Jaakko J<>rvi (jaakko.jarvi@cs.utu.fi)
 | 
			
		||||
//
 | 
			
		||||
//  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:
 | 
			
		||||
 | 
			
		||||
    explicit reference_wrapper(T & t): t_(t) {}
 | 
			
		||||
 | 
			
		||||
    operator T & () const { return t_; }
 | 
			
		||||
 | 
			
		||||
    T & get() const { return t_; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
 | 
			
		||||
    T & t_;
 | 
			
		||||
 | 
			
		||||
    reference_wrapper & operator= (reference_wrapper const &);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template<class T> inline reference_wrapper<T> ref(T & t)
 | 
			
		||||
{ 
 | 
			
		||||
    return reference_wrapper<T>(t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<class T> inline reference_wrapper<T const> cref(T const & t)
 | 
			
		||||
{
 | 
			
		||||
    return reference_wrapper<T const>(t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
#endif // #ifndef BOOST_REF_HPP_INCLUDED
 | 
			
		||||
@@ -10,23 +10,15 @@
 | 
			
		||||
 | 
			
		||||
//  Classes appear in alphabetical order
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  21 May 01  checked_delete() and checked_array_delete() added (Beman Dawes,
 | 
			
		||||
//             suggested by Dave Abrahams, generalizing idea from Vladimir Prus)
 | 
			
		||||
//  21 May 01  made next() and prior() inline (Beman Dawes)  
 | 
			
		||||
//  26 Jan 00  protected noncopyable destructor added (Miki Jovanovic)
 | 
			
		||||
//  10 Dec 99  next() and prior() templates added (Dave Abrahams)
 | 
			
		||||
//  30 Aug 99  moved cast templates to cast.hpp (Beman Dawes)
 | 
			
		||||
//   3 Aug 99  cast templates added
 | 
			
		||||
//  20 Jul 99  name changed to utility.hpp 
 | 
			
		||||
//   9 Jun 99  protected noncopyable default ctor
 | 
			
		||||
//   2 Jun 99  Initial Version. Class noncopyable only contents (Dave Abrahams)
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_UTILITY_HPP
 | 
			
		||||
#define BOOST_UTILITY_HPP
 | 
			
		||||
 | 
			
		||||
#include <boost/config.hpp>        // broken compiler workarounds 
 | 
			
		||||
#include <boost/static_assert.hpp> 
 | 
			
		||||
#include <boost/config.hpp>        // broken compiler workarounds
 | 
			
		||||
#include <boost/static_assert.hpp>
 | 
			
		||||
 | 
			
		||||
// certain headers are part of the <utility.hpp> interface
 | 
			
		||||
#include <boost/utility/base_from_member.hpp>  
 | 
			
		||||
 
 | 
			
		||||
#include <cstddef>                 // for size_t
 | 
			
		||||
#include <utility>                 // for std::pair
 | 
			
		||||
 | 
			
		||||
@@ -87,31 +79,6 @@ namespace boost
 | 
			
		||||
        const noncopyable& operator=( const noncopyable& );
 | 
			
		||||
    }; // noncopyable
 | 
			
		||||
 | 
			
		||||
//  class tied  -------------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
    // A helper for conveniently assigning the two values from a pair
 | 
			
		||||
    // into separate variables. The idea for this comes from Jaakko J<>rvi's
 | 
			
		||||
    // Binder/Lambda Library.
 | 
			
		||||
 | 
			
		||||
    // Constributed by Jeremy Siek
 | 
			
		||||
 | 
			
		||||
    template <class A, class B>
 | 
			
		||||
    class tied {
 | 
			
		||||
    public:
 | 
			
		||||
      inline tied(A& a, B& b) : _a(a), _b(b) { }
 | 
			
		||||
      template <class U, class V>
 | 
			
		||||
      inline tied& operator=(const std::pair<U,V>& p) {
 | 
			
		||||
        _a = p.first;
 | 
			
		||||
        _b = p.second;
 | 
			
		||||
        return *this;
 | 
			
		||||
      }
 | 
			
		||||
    protected:
 | 
			
		||||
      A& _a;
 | 
			
		||||
      B& _b;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    template <class A, class B>
 | 
			
		||||
    inline tied<A,B> tie(A& a, B& b) { return tied<A,B>(a, b); }
 | 
			
		||||
 | 
			
		||||
} // namespace boost
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										59
									
								
								include/boost/utility/base_from_member.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								include/boost/utility/base_from_member.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,59 @@
 | 
			
		||||
//  boost utility/base_from_member.hpp header file  --------------------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright Daryle Walker 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.
 | 
			
		||||
 | 
			
		||||
#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;
 | 
			
		||||
 | 
			
		||||
    explicit  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 ) 
 | 
			
		||||
        {}
 | 
			
		||||
 | 
			
		||||
};  // boost::base_from_member
 | 
			
		||||
 | 
			
		||||
}  // namespace boost
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif  // BOOST_UTILITY_BASE_FROM_MEMBER_HPP
 | 
			
		||||
							
								
								
									
										38
									
								
								include/boost/utility_fwd.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								include/boost/utility_fwd.hpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
//  Boost utility_fwd.hpp header file  ---------------------------------------//
 | 
			
		||||
 | 
			
		||||
//  (C) Copyright boost.org 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.
 | 
			
		||||
 | 
			
		||||
#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/utility.hpp>  ------------------------------------------------//
 | 
			
		||||
 | 
			
		||||
class noncopyable;
 | 
			
		||||
 | 
			
		||||
template < class A, class B >
 | 
			
		||||
    class tied;
 | 
			
		||||
 | 
			
		||||
// Also has a few function templates
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}  // namespace boost
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif  // BOOST_UTILITY_FWD_HPP
 | 
			
		||||
@@ -203,10 +203,10 @@ explicit indirect_iterator_generator::type(const BaseIterator& it)
 | 
			
		||||
 | 
			
		||||
    <blockquote>
 | 
			
		||||
<pre>
 | 
			
		||||
template <class BaseIterator,
 | 
			
		||||
          class Value, class Pointer, class Reference,
 | 
			
		||||
          class ConstPointer, class ConstReference>
 | 
			
		||||
class indirect_iterator_pair_generator
 | 
			
		||||
  template <class BaseIterator,
 | 
			
		||||
            class Value, class Reference, class ConstReference, 
 | 
			
		||||
            class Category, class Pointer, class ConstPointer>
 | 
			
		||||
  struct indirect_iterator_pair_generator;
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
  typedef <tt><a href=
 | 
			
		||||
@@ -292,13 +292,6 @@ b,c,d,e,f,g,h,
 | 
			
		||||
        in particular, the result type of its <tt>operator*()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> <tt>Value&</tt> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Pointer</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>pointer</tt> type of the resulting <tt>iterator</tt>, and
 | 
			
		||||
        in particular, the result type of its <tt>operator->()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> <tt>Value*</tt> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>ConstReference</tt> 
 | 
			
		||||
 | 
			
		||||
@@ -307,6 +300,19 @@ b,c,d,e,f,g,h,
 | 
			
		||||
        <tt>operator*()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> <tt>const Value&</tt> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Category</tt> 
 | 
			
		||||
        <td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
 | 
			
		||||
         <b>Default:</b>
 | 
			
		||||
        <tt>std::iterator_traits<BaseIterator>::iterator_category</tt> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Pointer</tt> 
 | 
			
		||||
 | 
			
		||||
        <td>The <tt>pointer</tt> type of the resulting <tt>iterator</tt>, and
 | 
			
		||||
        in particular, the result type of its <tt>operator->()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> <tt>Value*</tt> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>ConstPointer</tt> 
 | 
			
		||||
 | 
			
		||||
@@ -314,11 +320,6 @@ b,c,d,e,f,g,h,
 | 
			
		||||
        and in particular, the result type of its <tt>operator->()</tt>.<br>
 | 
			
		||||
         <b>Default:</b> <tt>const Value*</tt> 
 | 
			
		||||
 | 
			
		||||
      <tr>
 | 
			
		||||
        <td><tt>Category</tt> 
 | 
			
		||||
        <td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
 | 
			
		||||
         <b>Default:</b>
 | 
			
		||||
        <tt>std::iterator_traits<BaseIterator>::iterator_category</tt> 
 | 
			
		||||
    </table>
 | 
			
		||||
 | 
			
		||||
    <h3>Concept Model</h3>
 | 
			
		||||
@@ -422,7 +423,7 @@ a,b,c,d,e,f,g,
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <p>Revised 
 | 
			
		||||
    <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" -->
 | 
			
		||||
    <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->18 Sep 2001<!--webbot bot="Timestamp" endspan i-checksum="14941" -->
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <p>© Copyright Jeremy Siek and David Abrahams 2001. Permission to
 | 
			
		||||
 
 | 
			
		||||
@@ -4,8 +4,6 @@
 | 
			
		||||
// "as is" without express or implied warranty, and with no claim as
 | 
			
		||||
// to its suitability for any purpose.
 | 
			
		||||
 | 
			
		||||
// 27 June 2001 Jeremy Siek
 | 
			
		||||
//     Upated for change in named params.
 | 
			
		||||
// 8 Mar 2001   Jeremy Siek
 | 
			
		||||
//     Initial checkin.
 | 
			
		||||
 | 
			
		||||
@@ -13,6 +11,9 @@
 | 
			
		||||
#include <boost/pending/iterator_tests.hpp>
 | 
			
		||||
#include <boost/static_assert.hpp>
 | 
			
		||||
 | 
			
		||||
class bar { };
 | 
			
		||||
void foo(bar) { }
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main()
 | 
			
		||||
{
 | 
			
		||||
@@ -25,8 +26,9 @@ main()
 | 
			
		||||
 | 
			
		||||
  {
 | 
			
		||||
    typedef boost::iterator_adaptor<my_iter, boost::default_iterator_policies,
 | 
			
		||||
      boost::reference_is<dummyT>,
 | 
			
		||||
      boost::iterator_category_is<std::input_iterator_tag> > iter_type;
 | 
			
		||||
      boost::iterator_traits_generator
 | 
			
		||||
      ::reference<dummyT>
 | 
			
		||||
      ::iterator_category<std::input_iterator_tag> > iter_type;
 | 
			
		||||
 | 
			
		||||
    BOOST_STATIC_ASSERT((boost::is_same<iter_type::iterator_category*,
 | 
			
		||||
       std::input_iterator_tag*>::value));
 | 
			
		||||
@@ -40,11 +42,12 @@ main()
 | 
			
		||||
  {
 | 
			
		||||
    typedef boost::iterator_adaptor<dummyT*,
 | 
			
		||||
      boost::default_iterator_policies,
 | 
			
		||||
      boost::value_type_is<dummyT>,
 | 
			
		||||
      boost::reference_is<const dummyT&>,
 | 
			
		||||
      boost::pointer_is<const dummyT*>,
 | 
			
		||||
      boost::iterator_category_is<std::forward_iterator_tag>,
 | 
			
		||||
      boost::difference_type_is<std::ptrdiff_t> > adaptor_type;
 | 
			
		||||
      boost::iterator_traits_generator
 | 
			
		||||
        ::value_type<dummyT>
 | 
			
		||||
        ::reference<const dummyT&>
 | 
			
		||||
        ::pointer<const dummyT*> 
 | 
			
		||||
        ::iterator_category<std::forward_iterator_tag>
 | 
			
		||||
        ::difference_type<std::ptrdiff_t> > adaptor_type;
 | 
			
		||||
 | 
			
		||||
    adaptor_type i(array);
 | 
			
		||||
 | 
			
		||||
@@ -21,8 +21,9 @@ main(int, char*[])
 | 
			
		||||
  int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
 | 
			
		||||
 | 
			
		||||
  typedef std::binder1st< std::multiplies<int> > Function;
 | 
			
		||||
  typedef boost::transform_iterator_generator<Function, int*
 | 
			
		||||
    >::type doubling_iterator;
 | 
			
		||||
  typedef boost::transform_iterator<Function, int*, 
 | 
			
		||||
    boost::iterator<std::random_access_iterator_tag, int>
 | 
			
		||||
  >::type doubling_iterator;
 | 
			
		||||
 | 
			
		||||
  doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),
 | 
			
		||||
    i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2));
 | 
			
		||||
 
 | 
			
		||||
@@ -9,7 +9,6 @@
 | 
			
		||||
//  See http://www.boost.org for most recent version including documentation.
 | 
			
		||||
 | 
			
		||||
//  Revision History
 | 
			
		||||
//  27 June 01 Updated to changes in named parameters.
 | 
			
		||||
//  08 Mar 01 Moved indirect and transform tests to separate files.
 | 
			
		||||
//            (Jeremy Siek)
 | 
			
		||||
//  19 Feb 01 Take adavantage of improved iterator_traits to do more tests
 | 
			
		||||
@@ -53,7 +52,8 @@
 | 
			
		||||
#include <boost/pending/iterator_tests.hpp>
 | 
			
		||||
#include <boost/pending/integer_range.hpp>
 | 
			
		||||
#include <boost/concept_archetype.hpp>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <deque>
 | 
			
		||||
#include <set>
 | 
			
		||||
 | 
			
		||||
@@ -97,9 +97,6 @@ typedef std::deque<int> storage;
 | 
			
		||||
typedef std::deque<int*> pointer_deque;
 | 
			
		||||
typedef std::set<storage::iterator> iterator_set;
 | 
			
		||||
 | 
			
		||||
struct bar { };
 | 
			
		||||
void foo(bar) { }
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main()
 | 
			
		||||
{
 | 
			
		||||
@@ -309,11 +306,12 @@ main()
 | 
			
		||||
#else
 | 
			
		||||
    typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
 | 
			
		||||
      boost::default_iterator_policies,
 | 
			
		||||
      boost::value_type_is<dummyT>,
 | 
			
		||||
      boost::reference_is<const dummyT&>,
 | 
			
		||||
      boost::pointer_is<const dummyT*>,
 | 
			
		||||
      boost::iterator_category_is<std::forward_iterator_tag>,
 | 
			
		||||
      boost::difference_type_is<std::ptrdiff_t> > adaptor_type;
 | 
			
		||||
      boost::iterator_traits_generator
 | 
			
		||||
        ::value_type<dummyT>
 | 
			
		||||
        ::reference<const dummyT&>
 | 
			
		||||
        ::pointer<const dummyT*> 
 | 
			
		||||
        ::iterator_category<std::forward_iterator_tag>
 | 
			
		||||
        ::difference_type<std::ptrdiff_t> > adaptor_type;
 | 
			
		||||
#endif
 | 
			
		||||
    adaptor_type i(forward_iter);
 | 
			
		||||
    int zero = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -93,7 +93,7 @@
 | 
			
		||||
       <a href="function_output_iterator.htm">Function Output Iterator Adaptor</a>
 | 
			
		||||
    </ul>
 | 
			
		||||
 | 
			
		||||
    <p><b><a href="http://www.boost.org/people/dave_abrahams.htm">Dave
 | 
			
		||||
    <p><b><a href="../../people/dave_abrahams.htm">Dave
 | 
			
		||||
    Abrahams</a></b> started the library, applying <a href=
 | 
			
		||||
    "../../more/generic_programming.html#policy">policy class</a> technique and
 | 
			
		||||
    handling const/non-const iterator interactions. He also contributed the
 | 
			
		||||
@@ -102,7 +102,7 @@
 | 
			
		||||
    <tt><a href="counting_iterator.htm">counting_iterator_generator</a></tt> to
 | 
			
		||||
    cover all incrementable types. He edited most of the documentation,
 | 
			
		||||
    sometimes heavily.<br>
 | 
			
		||||
     <b><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy
 | 
			
		||||
     <b><a href="../../people/jeremy_siek.htm">Jeremy
 | 
			
		||||
    Siek</a></b> contributed the <a href="transform_iterator.htm">transform
 | 
			
		||||
    iterator</a> adaptor, the integer-only version of <tt><a href=
 | 
			
		||||
    "counting_iterator.htm">counting_iterator_generator</a></tt>, 
 | 
			
		||||
@@ -423,27 +423,27 @@ struct <a name="default_iterator_policies">default_iterator_policies</a>
 | 
			
		||||
    { return *x; }
 | 
			
		||||
 | 
			
		||||
  template <class BaseType>
 | 
			
		||||
  static void increment(BaseType& x)
 | 
			
		||||
  void increment(BaseType& x)
 | 
			
		||||
    { ++x; }
 | 
			
		||||
 | 
			
		||||
  template <class BaseType1, class BaseType2>
 | 
			
		||||
  bool equal(BaseType1& x, BaseType2& y) const
 | 
			
		||||
  bool equal(const BaseType1& x, const BaseType2& y) const
 | 
			
		||||
    { return x == y; }
 | 
			
		||||
 | 
			
		||||
  template <class BaseType>
 | 
			
		||||
  static void decrement(BaseType& x)
 | 
			
		||||
  void decrement(BaseType& x)
 | 
			
		||||
    { --x; }
 | 
			
		||||
 | 
			
		||||
  template <class BaseType, class DifferenceType>
 | 
			
		||||
  static void advance(BaseType& x, DifferenceType n)
 | 
			
		||||
  void advance(BaseType& x, DifferenceType n)
 | 
			
		||||
    { x += n; }
 | 
			
		||||
 | 
			
		||||
  template <class Difference, class BaseType1, class BaseType2>
 | 
			
		||||
  Difference distance(type<Difference>, BaseType1& x, BaseType2& y) const
 | 
			
		||||
  Difference distance(type<Difference>, const BaseType1& x, const BaseType2& y) const
 | 
			
		||||
    { return y - x; }
 | 
			
		||||
 | 
			
		||||
  template <class BaseType1, class BaseType2>
 | 
			
		||||
  bool less(BaseType1& x, BaseType2& y) const
 | 
			
		||||
  bool less(const BaseType1& x, const BaseType2& y) const
 | 
			
		||||
    { return x < y; }
 | 
			
		||||
};
 | 
			
		||||
</pre>
 | 
			
		||||
@@ -611,10 +611,10 @@ int main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
 | 
			
		||||
  const int N = sizeof(x)/sizeof(int);
 | 
			
		||||
  std::cout << "multiplying the array by 2:" << std::endl;
 | 
			
		||||
  std::cout << "multiplying the array by 2:" << std::endl;
 | 
			
		||||
  std::copy(boost::make_transform_iterator(x, std::bind1st(std::multiplies<int>(), 2)),
 | 
			
		||||
      boost::make_transform_iterator(x + N, std::bind1st(std::multiplies<int>(), 2)),
 | 
			
		||||
      std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
      std::ostream_iterator<int>(std::cout, " "));
 | 
			
		||||
  std::cout << std::endl;
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -767,10 +767,10 @@ struct iterator_adaptor
 | 
			
		||||
    iterator_adaptor(
 | 
			
		||||
        const iterator_adaptor<B,Policies,V,R,P,Category,Distance>&);
 | 
			
		||||
 | 
			
		||||
    reference operator*() const;
 | 
			
		||||
    reference operator*() const; <a href="#6">[6]</a>
 | 
			
		||||
    <i>operator_arrow_result_type</i> operator->() const; <a href=
 | 
			
		||||
"#3">[3]</a>
 | 
			
		||||
    <i>value_type</i> operator[](difference_type n) const; <a href="#3">[4]</a>
 | 
			
		||||
    <i>value_type</i> operator[](difference_type n) const; <a href="#3">[4]</a>, <a href="#6">[6]</a>
 | 
			
		||||
 | 
			
		||||
    iterator_adaptor& operator++();
 | 
			
		||||
    iterator_adaptor& operator++(int);
 | 
			
		||||
@@ -857,10 +857,38 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
 | 
			
		||||
    Forward Iterator</a>, so you will need to use a less restrictive
 | 
			
		||||
    iterator category such as <tt>std::input_iterator_tag</tt>.
 | 
			
		||||
 | 
			
		||||
    <p><a name="6">[6]</a>
 | 
			
		||||
    There is a common misconception that an iterator should have two
 | 
			
		||||
    versions of <tt>operator*</tt> and of <tt>operator[]</tt>, one
 | 
			
		||||
    version that is a <tt>const</tt> member function and one version
 | 
			
		||||
    that is non-<tt>const</tt>. Perhaps the source of this
 | 
			
		||||
    misconception is that containers typically have const and
 | 
			
		||||
    non-const versions of many of their member functions.  Iterators,
 | 
			
		||||
    however, are different. A particular iterator type can be either
 | 
			
		||||
    <i>mutable</i> or <i>constant</i> (but not both).  One can assign
 | 
			
		||||
    to and change the object pointed to by a mutable iterator whereas a
 | 
			
		||||
    constant iterator returns constant objects when dereferenced. Whether
 | 
			
		||||
    the iterator object itself is <tt>const</tt> has nothing to do with
 | 
			
		||||
    whether the iterator is mutable or constant.  This is analogous to
 | 
			
		||||
    the way built-in pointer types behave.  For example, one can
 | 
			
		||||
    modify objects pointed to by a <tt>const</tt> pointer
 | 
			
		||||
<pre>
 | 
			
		||||
    int* const x = new int;
 | 
			
		||||
    int i = 3;
 | 
			
		||||
    *x = i;
 | 
			
		||||
</pre>
 | 
			
		||||
    but one cannot modify objects pointed to by a pointer
 | 
			
		||||
    to <tt>const</tt>
 | 
			
		||||
<pre>
 | 
			
		||||
    int const* x = new int;
 | 
			
		||||
    int i = 3;
 | 
			
		||||
    *x = i;
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
    <hr>
 | 
			
		||||
 | 
			
		||||
    <p>Revised 
 | 
			
		||||
    <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14895" -->
 | 
			
		||||
    <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->18 Sep 2001<!--webbot bot="Timestamp" endspan i-checksum="14941" -->
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <p>© Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy,
 | 
			
		||||
@@ -871,7 +899,7 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
 | 
			
		||||
 | 
			
		||||
</body>
 | 
			
		||||
 | 
			
		||||
    <!--  LocalWords:  HTML html charset alt gif abrahams htm const
 | 
			
		||||
    <!--  LocalWords:  HTML html charset alt gif abrahams htm const iterator
 | 
			
		||||
        incrementable david abrahams
 | 
			
		||||
         -->
 | 
			
		||||
     
 | 
			
		||||
@@ -887,5 +915,7 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
 | 
			
		||||
    <!--  LocalWords:  iostream hpp sizeof InputIterator constness ConstIterator
 | 
			
		||||
         David Abrahams
 | 
			
		||||
         -->
 | 
			
		||||
<!--  LocalWords:  Iterators dereferenced
 | 
			
		||||
 -->
 | 
			
		||||
</html>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,10 @@
 | 
			
		||||
#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>
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
//  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
 | 
			
		||||
@@ -30,13 +31,6 @@
 | 
			
		||||
# include <limits>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// A macro for declaring class compile-time constants.
 | 
			
		||||
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
 | 
			
		||||
# define DECLARE_CLASS_CONST(type, init) static const type init
 | 
			
		||||
#else
 | 
			
		||||
# define DECLARE_CLASS_CONST(type, init) enum { init }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// =================================================================================
 | 
			
		||||
// template class complement_traits<Number> --
 | 
			
		||||
//
 | 
			
		||||
@@ -53,8 +47,8 @@ template <unsigned size> struct complement; // forward
 | 
			
		||||
template <class Number, unsigned size>
 | 
			
		||||
struct complement_traits_aux
 | 
			
		||||
{
 | 
			
		||||
    DECLARE_CLASS_CONST(Number, max = complement<size>::template traits<Number>::max);
 | 
			
		||||
    DECLARE_CLASS_CONST(Number, min = complement<size>::template traits<Number>::min);
 | 
			
		||||
    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>
 | 
			
		||||
@@ -67,11 +61,11 @@ struct complement
 | 
			
		||||
        // indirection through complement_traits_aux neccessary to keep MSVC happy
 | 
			
		||||
        typedef complement_traits_aux<Number, size - 1> prev;
 | 
			
		||||
     public:
 | 
			
		||||
        DECLARE_CLASS_CONST(Number, max =
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, max =
 | 
			
		||||
                            Number(Number(prev::max) << CHAR_BIT)
 | 
			
		||||
                            + Number(UCHAR_MAX));
 | 
			
		||||
        
 | 
			
		||||
        DECLARE_CLASS_CONST(Number, min = Number(Number(prev::min) << CHAR_BIT));
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, min = Number(Number(prev::min) << CHAR_BIT));
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -85,8 +79,8 @@ template <> struct complement_base<false>
 | 
			
		||||
    template <class Number>
 | 
			
		||||
    struct values
 | 
			
		||||
    {
 | 
			
		||||
        DECLARE_CLASS_CONST(Number, min = 0);
 | 
			
		||||
        DECLARE_CLASS_CONST(Number, max = UCHAR_MAX);
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, min = 0);
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, max = UCHAR_MAX);
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -95,8 +89,8 @@ template <> struct complement_base<true>
 | 
			
		||||
    template <class Number>
 | 
			
		||||
    struct values
 | 
			
		||||
    {
 | 
			
		||||
        DECLARE_CLASS_CONST(Number, min = SCHAR_MIN);
 | 
			
		||||
        DECLARE_CLASS_CONST(Number, max = SCHAR_MAX);
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, min = SCHAR_MIN);
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, max = SCHAR_MAX);
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -107,10 +101,10 @@ struct complement<1>
 | 
			
		||||
    template <class Number>
 | 
			
		||||
    struct traits
 | 
			
		||||
    {
 | 
			
		||||
        DECLARE_CLASS_CONST(bool, is_signed = boost::detail::is_signed<Number>::value);
 | 
			
		||||
        DECLARE_CLASS_CONST(Number, min =
 | 
			
		||||
        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);
 | 
			
		||||
        DECLARE_CLASS_CONST(Number, max =
 | 
			
		||||
        BOOST_STATIC_CONSTANT(Number, max =
 | 
			
		||||
                            complement_base<is_signed>::template values<Number>::max);
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
@@ -121,8 +115,8 @@ struct complement<1>
 | 
			
		||||
template <class Number>
 | 
			
		||||
struct complement_traits
 | 
			
		||||
{
 | 
			
		||||
    DECLARE_CLASS_CONST(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max));
 | 
			
		||||
    DECLARE_CLASS_CONST(Number, min = (complement_traits_aux<Number, sizeof(Number)>::min));
 | 
			
		||||
    BOOST_STATIC_CONSTANT(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max));
 | 
			
		||||
    BOOST_STATIC_CONSTANT(Number, min = (complement_traits_aux<Number, sizeof(Number)>::min));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// =================================================================================
 | 
			
		||||
@@ -151,9 +145,9 @@ template <> struct stream_as<signed char>  {
 | 
			
		||||
    typedef unsigned char t1; typedef unsigned t2;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC) // No intmax streaming built-in
 | 
			
		||||
#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in
 | 
			
		||||
 | 
			
		||||
// On this platform, __int64 and __uint64 get streamed as strings
 | 
			
		||||
// 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;
 | 
			
		||||
@@ -174,7 +168,7 @@ template <class T> struct promote
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if defined(BOOST_MSVC) // No intmax streaming built-in
 | 
			
		||||
#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.
 | 
			
		||||
 
 | 
			
		||||
@@ -50,6 +50,7 @@ provided by the class.</p>
 | 
			
		||||
	<ul>
 | 
			
		||||
		<li><a href="#dereference">Dereference operators</a></li>
 | 
			
		||||
		<li><a href="#iterator">Iterator Helpers</a></li>
 | 
			
		||||
		<li><a href="#iterator_helpers_notes">Iterator Helper Notes</a></li>
 | 
			
		||||
		<li><a href="#i_demo">Iterator Demonstration and Test
 | 
			
		||||
			Program</a></li>
 | 
			
		||||
	</ul></li>
 | 
			
		||||
@@ -821,7 +822,7 @@ from previous versions of the header, cannot be used for
 | 
			
		||||
<p>The <cite><a href="operators_test.cpp">operators_test.cpp</a></cite>
 | 
			
		||||
program demonstrates the use of the arithmetic operator templates, and
 | 
			
		||||
can also be used to verify correct operation.  Check the <a
 | 
			
		||||
href="../compiler_status.htm">compiler status report</a> for the test results
 | 
			
		||||
href="../../status/compiler_status.html">compiler status report</a> for the test results
 | 
			
		||||
with selected platforms.</p>
 | 
			
		||||
 | 
			
		||||
<h2><a name="deref">Dereference</a> Operators and Iterator Helpers</h2>
 | 
			
		||||
@@ -889,7 +890,7 @@ href="#chaining">base class chaining</a>.</p>
 | 
			
		||||
 | 
			
		||||
<h3><a name="iterator">Iterator</a> Helpers</h3>
 | 
			
		||||
 | 
			
		||||
<p>There are three separate iterator helper classes, each for a
 | 
			
		||||
<p>There are five separate iterator helper classes, each for a
 | 
			
		||||
different category of iterator.  Here is a summary of the core set of
 | 
			
		||||
operators that the custom iterator must define, and the extra operators
 | 
			
		||||
that are created by the helper classes.  These classes cannot be used for <a
 | 
			
		||||
@@ -931,11 +932,13 @@ C++ standard (<code>iterator_category</code>, <code>value_type</code>,
 | 
			
		||||
		    </ul></td>
 | 
			
		||||
	</tr>
 | 
			
		||||
	<tr valign="baseline">
 | 
			
		||||
		<td><code><a name="output_iterator_helper">output_iterator_helper<T, V, D, P, R></a></code></td>
 | 
			
		||||
		<td><code><a name="output_iterator_helper">output_iterator_helper<T></a></code></td>
 | 
			
		||||
		<td>Supports the operations and has the requirements of
 | 
			
		||||
		    <ul>
 | 
			
		||||
			   <li><code><a href="#incrementable">incrementable<T></a></code></li>
 | 
			
		||||
		    </ul></td>
 | 
			
		||||
		    </ul>
 | 
			
		||||
        See also [<a href="#1">1</a>], [<a href="#2">2</a>].
 | 
			
		||||
        </td>
 | 
			
		||||
	</tr>
 | 
			
		||||
	<tr valign="baseline">
 | 
			
		||||
		<td><code><a name="forward_iterator_helper">forward_iterator_helper<T, V, D, P, R></a></code></td>
 | 
			
		||||
@@ -975,6 +978,53 @@ C++ standard (<code>iterator_category</code>, <code>value_type</code>,
 | 
			
		||||
	</tr>
 | 
			
		||||
</table>
 | 
			
		||||
 | 
			
		||||
<h3><a name="iterator_helpers_notes">Iterator Helper Notes</a></h3>
 | 
			
		||||
 | 
			
		||||
<p><a name="1">[1]</a> Unlike other iterator helpers templates,
 | 
			
		||||
<code>output_iterator_helper</code> takes only one template parameter - the type of
 | 
			
		||||
its target class. Although to some it might seem like an unnecessary
 | 
			
		||||
restriction, the standard requires <code>difference_type</code> and
 | 
			
		||||
<code>value_type</code> of any output iterator to be 
 | 
			
		||||
<code>void</code> (24.3.1 [lib.iterator.traits]), and
 | 
			
		||||
<code>output_iterator_helper</code> template respects this
 | 
			
		||||
requirement. Also, output iterators in the standard have void <tt>pointer</tt> and
 | 
			
		||||
<tt>reference</tt> types, so the <tt>output_iterator_helper</tt> does the
 | 
			
		||||
same.
 | 
			
		||||
 | 
			
		||||
<p><a name="2">[2]</a> As self-proxying is the easiest and most common way to 
 | 
			
		||||
implement output iterators (see, for example, insert [24.4.2] and stream 
 | 
			
		||||
iterators [24.5] in the standard library), <code>output_iterator_helper</code>
 | 
			
		||||
supports the idiom by defining <code>operator*</code> 
 | 
			
		||||
and <code>operator++</code> member functions which just return a 
 | 
			
		||||
non-const reference to the iterator itself. Support for 
 | 
			
		||||
self-proxying allows us, in many cases, to reduce the task of writing an output 
 | 
			
		||||
iterator to writing just two member functions - an appropriate 
 | 
			
		||||
constructor and a copy-assignment operator. For example, here is a possible
 | 
			
		||||
implementation of <code><a href="function_output_iterator.htm">boost::function_output_iterator</a></code>
 | 
			
		||||
adaptor:</p>
 | 
			
		||||
 | 
			
		||||
<pre>
 | 
			
		||||
template<class UnaryFunction>
 | 
			
		||||
struct function_output_iterator
 | 
			
		||||
    : boost::output_iterator_helper< function_output_iterator<UnaryFunction> >
 | 
			
		||||
{
 | 
			
		||||
    explicit function_output_iterator(UnaryFunction const& f = UnaryFunction())
 | 
			
		||||
        : func(f) {}
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    function_output_iterator& operator=(T const& value)
 | 
			
		||||
    {
 | 
			
		||||
        this->func(value); 
 | 
			
		||||
        return *this; 
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
    UnaryFunction func;
 | 
			
		||||
};
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<p>Note that support for self-proxying does not prevent you from using <code>output_iterator_helper</code> to ease any other, different kind of output iterator's implementation. If <code>output_iterator_helper</code>'s target type provides its own definition of <code>operator*</code> or/and <code>operator++</code>, then these operators will get used and the ones supplied by <code>output_iterator_helper</code> will never be instantiated.</p>
 | 
			
		||||
 | 
			
		||||
<h3><a name="i_demo">Iterator Demonstration</a> and Test Program</h3>
 | 
			
		||||
 | 
			
		||||
<p>The <cite><a href="iterators_test.cpp">iterators_test.cpp</a></cite>
 | 
			
		||||
@@ -1010,7 +1060,7 @@ public:
 | 
			
		||||
};</pre>
 | 
			
		||||
</blockquote>
 | 
			
		||||
 | 
			
		||||
<p>Check the <a href="../compiler_status.htm">compiler status report</a> for
 | 
			
		||||
<p>Check the <a href="../../status/compiler_status.html">compiler status report</a> for
 | 
			
		||||
the test results with selected platforms.</p>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
@@ -1092,7 +1142,7 @@ the library remain backward-compatible.</p>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
 | 
			
		||||
<p>Revised: 20 May 2001</p>
 | 
			
		||||
<p>Revised: 25 Jun 2001</p>
 | 
			
		||||
 | 
			
		||||
<p>Copyright © David Abrahams and Beman Dawes 1999-2001. 
 | 
			
		||||
Permission to copy, use, modify, sell and distribute this document is
 | 
			
		||||
 
 | 
			
		||||
@@ -371,7 +371,7 @@ Betty
 | 
			
		||||
</pre>
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" --></p>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" --></p>
 | 
			
		||||
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
 
 | 
			
		||||
@@ -312,7 +312,7 @@ simply use <tt>reverse_iterator_generator</tt> twice!<br><br>
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    <p>Revised 
 | 
			
		||||
    <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" -->
 | 
			
		||||
    <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" -->
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <p>© Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								tie.html
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								tie.html
									
									
									
									
									
								
							@@ -23,7 +23,13 @@
 | 
			
		||||
<TT>tie</TT>
 | 
			
		||||
</H1>
 | 
			
		||||
 | 
			
		||||
<P>
 | 
			
		||||
<h3>
 | 
			
		||||
[This version of tie has been removed from the utility.hpp
 | 
			
		||||
header.  There is a new, more general version of <a
 | 
			
		||||
href="../tuple/doc/tuple_users_guide.html#tiers">tie</a> in the Boost
 | 
			
		||||
Tuples Library. The more general version handles an (almost) arbitrary
 | 
			
		||||
number of arguments, instead of just two. The version in utility.hpp
 | 
			
		||||
had to be removed to avoid name clashes.]</h3>
 | 
			
		||||
<PRE>
 | 
			
		||||
template <class A, class B>
 | 
			
		||||
tied<A,B> tie(A& a, B& b);
 | 
			
		||||
@@ -124,7 +130,7 @@ The output is:
 | 
			
		||||
<TABLE>
 | 
			
		||||
<TR valign=top>
 | 
			
		||||
<TD nowrap>Copyright © 2000</TD><TD>
 | 
			
		||||
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>,
 | 
			
		||||
<a HREF="../../people/jeremy_siek.htm">Jeremy Siek</a>,
 | 
			
		||||
Univ.of Notre Dame (<A
 | 
			
		||||
HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)<br>
 | 
			
		||||
<A HREF=http://www.lsc.nd.edu/~llee1>Lie-Quan Lee</A>, Univ.of Notre Dame (<A HREF="mailto:llee1@lsc.nd.edu">llee1@lsc.nd.edu</A>)<br>
 | 
			
		||||
 
 | 
			
		||||
@@ -19,14 +19,16 @@
 | 
			
		||||
#include <set>
 | 
			
		||||
#include <algorithm>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <boost/utility.hpp>
 | 
			
		||||
// Note: tie() use to live in boost/utility.hpp, but
 | 
			
		||||
// not it is part of the more general Boost Tuple Library.
 | 
			
		||||
#include <boost/tuple/tuple.hpp>
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main(int, char*[])
 | 
			
		||||
{
 | 
			
		||||
  {
 | 
			
		||||
    typedef std::set<int> SetT;
 | 
			
		||||
    SetT::iterator i, end;
 | 
			
		||||
    SetT::iterator i;
 | 
			
		||||
    bool inserted;
 | 
			
		||||
    
 | 
			
		||||
    int vals[5] = { 5, 2, 4, 9, 1 };
 | 
			
		||||
 
 | 
			
		||||
@@ -211,7 +211,7 @@ iterator always returns by-value.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->29 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14896" --></p>
 | 
			
		||||
<p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" --></p>
 | 
			
		||||
<p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use,
 | 
			
		||||
modify, sell and distribute this document is granted provided this copyright
 | 
			
		||||
notice appears in all copies. This document is provided "as is"
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,8 @@
 | 
			
		||||
<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">next() and prior()</a></li>
 | 
			
		||||
@@ -131,11 +133,13 @@ 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>Class templates for the Base-from-Member Idiom</h2>
 | 
			
		||||
<p>See <a href="base_from_member.html">separate documentation</a>.</p>
 | 
			
		||||
<h2>Function template tie()</h2>
 | 
			
		||||
<p>See <a href="tie.html">separate documentation</a>.</p>
 | 
			
		||||
<hr>
 | 
			
		||||
<p>Revised  <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan
 | 
			
		||||
-->22 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13960"
 | 
			
		||||
-->10 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39328"
 | 
			
		||||
-->
 | 
			
		||||
</p>
 | 
			
		||||
<p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user