mirror of
https://github.com/boostorg/utility.git
synced 2025-06-26 12:31:37 +02:00
Compare commits
36 Commits
svn-branch
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
7cfd6f756d | |||
4e1b693ee2 | |||
e7592e5f83 | |||
d41013d9dc | |||
c3c8871f87 | |||
7b2f7a5ab4 | |||
bef6ec31f0 | |||
7657f5f343 | |||
1a31e19cfe | |||
82377d5130 | |||
4fe8f1505f | |||
c11ba92add | |||
c3cb4753f5 | |||
80eb3699d7 | |||
0e40c56a87 | |||
4a79874032 | |||
4e07a06b94 | |||
884c36772a | |||
506334c120 | |||
89107738b3 | |||
397946a114 | |||
ddbc514208 | |||
2cef48d02a | |||
96a079e30a | |||
4a3f6877e2 | |||
c593a27a51 | |||
f94db51996 | |||
3e5b447aa3 | |||
2f9bd13902 | |||
c59a5e8783 | |||
5b716a8b19 | |||
c243d693e2 | |||
b950b3afed | |||
1c555eae91 | |||
f04178d055 | |||
b38bc8d848 |
@ -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="../../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=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>, Univ.of Notre Dame (<A HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)
|
||||
</TD></TR></TABLE>
|
||||
|
||||
</BODY>
|
||||
|
@ -1,46 +0,0 @@
|
||||
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
|
||||
// Doug Gregor (gregod@cs.rpi.edu)
|
||||
//
|
||||
// Permission to copy, use, sell and distribute this software is granted
|
||||
// provided this copyright notice appears in all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted
|
||||
// provided this copyright notice appears in all copies, and a notice
|
||||
// that the code was modified is included with the copyright notice.
|
||||
//
|
||||
// This software is provided "as is" without express or implied warranty,
|
||||
// and with no claim as to its suitability for any purpose.
|
||||
|
||||
// For more information, see http://www.boost.org
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
struct useless_type {};
|
||||
|
||||
class nonaddressable {
|
||||
public:
|
||||
void dummy(); // Silence GCC warning: all member of class are private
|
||||
|
||||
private:
|
||||
useless_type operator&() const;
|
||||
};
|
||||
|
||||
int test_main(int, char*[])
|
||||
{
|
||||
nonaddressable* px = new nonaddressable();
|
||||
|
||||
nonaddressable& x = *px;
|
||||
BOOST_TEST(boost::addressof(x) == px);
|
||||
|
||||
const nonaddressable& cx = *px;
|
||||
BOOST_TEST(boost::addressof(cx) == static_cast<const nonaddressable*>(px));
|
||||
|
||||
volatile nonaddressable& vx = *px;
|
||||
BOOST_TEST(boost::addressof(vx) == static_cast<volatile nonaddressable*>(px));
|
||||
|
||||
const volatile nonaddressable& cvx = *px;
|
||||
BOOST_TEST(boost::addressof(cvx) == static_cast<const volatile nonaddressable*>(px));
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
#if defined(_MSC_VER) && !defined(__ICL)
|
||||
#pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
#pragma warning(disable: 4710) // function not inlined
|
||||
#pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
//
|
||||
// assert_test.cpp - a test for boost/assert.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
|
||||
#define BOOST_DEBUG 1
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <cstdio>
|
||||
|
||||
bool boost_error(char const * expr, char const * func, char const * file, long line)
|
||||
{
|
||||
std::printf("%s(%ld): Assertion '%s' failed in function '%s'\n", file, line, expr, func);
|
||||
return true; // fail w/ standard assert()
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
BOOST_ASSERT(0 == 1);
|
||||
}
|
@ -1,341 +0,0 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
<html>
|
||||
<head>
|
||||
<title>Boost: Base-from-Member Idiom Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="white" link="blue" text="black" vlink="purple" alink="red">
|
||||
<h1><img src="../../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>
|
@ -1,597 +0,0 @@
|
||||
// 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
|
||||
: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
#ifndef BOOST_NO_MEMBER_TEMPLATES
|
||||
template < typename T >
|
||||
void register_object( T &obj )
|
||||
{ this->register_object_imp( identify(obj) ); }
|
||||
template < typename T, typename U >
|
||||
void register_use( T &owner, U &owned )
|
||||
{ this->register_use_imp( identify(owner), identify(owned) ); }
|
||||
template < typename T, typename U >
|
||||
void unregister_use( T &owner, U &owned )
|
||||
{ this->unregister_use_imp( identify(owner), identify(owned) ); }
|
||||
template < typename T >
|
||||
void unregister_object( T &obj )
|
||||
{ this->unregister_object_imp( identify(obj) ); }
|
||||
#endif
|
||||
|
||||
void register_object_imp( object_id obj );
|
||||
void register_use_imp( object_id owner, object_id owned );
|
||||
void unregister_use_imp( object_id owner, object_id owned );
|
||||
void unregister_object_imp( object_id obj );
|
||||
|
||||
typedef std::set<object_id, object_id_compare> set_type;
|
||||
|
||||
typedef std::vector<object_id> error_record_type;
|
||||
typedef std::vector< std::pair<object_id, object_id> > error_pair_type;
|
||||
|
||||
set_type db_;
|
||||
|
||||
error_pair_type defrauders_in_, defrauders_out_;
|
||||
error_record_type overeager_, overkilled_;
|
||||
|
||||
}; // object_registrar
|
||||
|
||||
// A sample type to be used by containing types
|
||||
class base_or_member
|
||||
{
|
||||
public:
|
||||
explicit base_or_member( int x = 1, double y = -0.25 );
|
||||
~base_or_member();
|
||||
|
||||
}; // base_or_member
|
||||
|
||||
// A sample type that uses base_or_member, used
|
||||
// as a base for the main demonstration classes
|
||||
class base_class
|
||||
{
|
||||
public:
|
||||
explicit base_class( base_or_member &x, base_or_member *y = 0,
|
||||
base_or_member *z = 0 );
|
||||
|
||||
~base_class();
|
||||
|
||||
private:
|
||||
base_or_member *x_, *y_, *z_;
|
||||
|
||||
}; // base_class
|
||||
|
||||
// This bad class demonstrates the direct method of a base class needing
|
||||
// to be initialized by a member. This is improper since the member
|
||||
// isn't initialized until after the base class.
|
||||
class bad_class
|
||||
: public base_class
|
||||
{
|
||||
public:
|
||||
bad_class();
|
||||
~bad_class();
|
||||
|
||||
private:
|
||||
base_or_member x_;
|
||||
|
||||
}; // bad_class
|
||||
|
||||
// The first good class demonstrates the correct way to initialize a
|
||||
// base class with a member. The member is changed to another base
|
||||
// class, one that is initialized before the base that needs it.
|
||||
class good_class_1
|
||||
: private boost::base_from_member<base_or_member>
|
||||
, public base_class
|
||||
{
|
||||
typedef boost::base_from_member<base_or_member> pbase_type;
|
||||
typedef base_class base_type;
|
||||
|
||||
public:
|
||||
good_class_1();
|
||||
~good_class_1();
|
||||
|
||||
}; // good_class_1
|
||||
|
||||
// The second good class also demonstrates the correct way to initialize
|
||||
// base classes with other subobjects. This class uses the other helpers
|
||||
// in the library, and shows the technique of using two base subobjects
|
||||
// of the "same" type.
|
||||
class good_class_2
|
||||
: private boost::base_from_member<base_or_member, 0>
|
||||
, private boost::base_from_member<base_or_member, 1>
|
||||
, private boost::base_from_member<base_or_member, 2>
|
||||
, public base_class
|
||||
{
|
||||
typedef boost::base_from_member<base_or_member, 0> pbase_type0;
|
||||
typedef boost::base_from_member<base_or_member, 1> pbase_type1;
|
||||
typedef boost::base_from_member<base_or_member, 2> pbase_type2;
|
||||
typedef base_class base_type;
|
||||
|
||||
public:
|
||||
good_class_2();
|
||||
~good_class_2();
|
||||
|
||||
}; // good_class_2
|
||||
|
||||
// Declare/define the single object registrar
|
||||
object_registrar obj_reg;
|
||||
|
||||
|
||||
// Main functionality
|
||||
int
|
||||
test_main( int , char * [] )
|
||||
{
|
||||
BOOST_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
|
||||
}
|
@ -1,249 +0,0 @@
|
||||
// (C) Copyright David Abrahams 2000. Permission to copy, use, modify,
|
||||
// sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <climits>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <stdlib.h> // for rand(). Would use cstdlib but VC6.4 doesn't put it in std::
|
||||
#include <list>
|
||||
#include <algorithm>
|
||||
#include <boost/detail/binary_search.hpp>
|
||||
|
||||
#if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
|
||||
# define USE_SSTREAM
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSTREAM
|
||||
# include <sstream>
|
||||
#else
|
||||
# include <strstream>
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
typedef std::vector<std::string> string_vector;
|
||||
|
||||
const std::size_t sequence_length = 1000;
|
||||
|
||||
unsigned random_number()
|
||||
{
|
||||
return static_cast<unsigned>(::rand()) % sequence_length;
|
||||
}
|
||||
|
||||
# ifndef USE_SSTREAM
|
||||
class unfreezer {
|
||||
public:
|
||||
unfreezer(std::ostrstream& s) : m_stream(s) {}
|
||||
~unfreezer() { m_stream.freeze(false); }
|
||||
private:
|
||||
std::ostrstream& m_stream;
|
||||
};
|
||||
# endif
|
||||
|
||||
template <class T>
|
||||
void push_back_random_number_string(T& seq)
|
||||
{
|
||||
unsigned value = random_number();
|
||||
# if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2)
|
||||
std::ostringstream s;
|
||||
s << value;
|
||||
seq.push_back(s.str());
|
||||
# else
|
||||
std::ostrstream s;
|
||||
auto unfreezer unfreeze(s);
|
||||
s << value << char(0);
|
||||
seq.push_back(std::string(s.str()));
|
||||
# endif
|
||||
}
|
||||
|
||||
inline unsigned to_int(unsigned x) { return x; }
|
||||
inline unsigned to_int(const std::string& x) { return atoi(x.c_str()); }
|
||||
|
||||
struct cmp
|
||||
{
|
||||
template <class A1, class A2>
|
||||
inline bool operator()(const A1& a1, const A2& a2) const
|
||||
{
|
||||
return to_int(a1) < to_int(a2);
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator<(const std::string& x, const unsigned y)
|
||||
{
|
||||
return to_int(x) < y;
|
||||
}
|
||||
|
||||
inline bool operator<(const unsigned y, const std::string& x)
|
||||
{
|
||||
return y < to_int(x);
|
||||
}
|
||||
|
||||
template <class T> void sort_by_value(T&);
|
||||
|
||||
template <>
|
||||
void sort_by_value(std::vector<std::string>& v)
|
||||
{
|
||||
std::sort(v.begin(), v.end(), cmp());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void random_sorted_sequence(T& seq)
|
||||
{
|
||||
seq.clear();
|
||||
for (std::size_t i = 0; i < sequence_length; ++i)
|
||||
{
|
||||
push_back_random_number_string(seq);
|
||||
}
|
||||
sort_by_value(seq);
|
||||
}
|
||||
|
||||
# if defined(BOOST_MSVC) && BOOST_MSVC < 1300 && !defined(__SGI_STL_PORT)
|
||||
// VC6's standard lib doesn't have a template member function for list::sort()
|
||||
template <>
|
||||
void random_sorted_sequence(std::list<std::string>& result)
|
||||
{
|
||||
std::vector<std::string> seq;
|
||||
seq.reserve(sequence_length);
|
||||
for (std::size_t i = 0; i < sequence_length; ++i)
|
||||
{
|
||||
push_back_random_number_string(seq);
|
||||
}
|
||||
sort_by_value(seq);
|
||||
result.resize(seq.size());
|
||||
std::copy(seq.begin(), seq.end(), result.begin());
|
||||
}
|
||||
#else
|
||||
template <>
|
||||
inline void sort_by_value(std::list<std::string>& l)
|
||||
{
|
||||
l.sort(cmp());
|
||||
}
|
||||
# endif
|
||||
|
||||
// A way to select the comparisons with/without a Compare parameter for testing.
|
||||
template <class Compare> struct searches
|
||||
{
|
||||
template <class Iterator, class Key>
|
||||
static Iterator lower_bound(Iterator start, Iterator finish, Key key, Compare cmp)
|
||||
{ return boost::detail::lower_bound(start, finish, key, cmp); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static Iterator upper_bound(Iterator start, Iterator finish, Key key, Compare cmp)
|
||||
{ return boost::detail::upper_bound(start, finish, key, cmp); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static std::pair<Iterator, Iterator> equal_range(Iterator start, Iterator finish, Key key, Compare cmp)
|
||||
{ return boost::detail::equal_range(start, finish, key, cmp); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static bool binary_search(Iterator start, Iterator finish, Key key, Compare cmp)
|
||||
{ return boost::detail::binary_search(start, finish, key, cmp); }
|
||||
};
|
||||
|
||||
struct no_compare {};
|
||||
|
||||
template <> struct searches<no_compare>
|
||||
{
|
||||
template <class Iterator, class Key>
|
||||
static Iterator lower_bound(Iterator start, Iterator finish, Key key, no_compare)
|
||||
{ return boost::detail::lower_bound(start, finish, key); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static Iterator upper_bound(Iterator start, Iterator finish, Key key, no_compare)
|
||||
{ return boost::detail::upper_bound(start, finish, key); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static std::pair<Iterator, Iterator> equal_range(Iterator start, Iterator finish, Key key, no_compare)
|
||||
{ return boost::detail::equal_range(start, finish, key); }
|
||||
|
||||
template <class Iterator, class Key>
|
||||
static bool binary_search(Iterator start, Iterator finish, Key key, no_compare)
|
||||
{ return boost::detail::binary_search(start, finish, key); }
|
||||
};
|
||||
|
||||
template <class Sequence, class Compare>
|
||||
void test_loop(Sequence& x, Compare cmp, unsigned long test_count)
|
||||
{
|
||||
typedef typename Sequence::const_iterator const_iterator;
|
||||
|
||||
for (unsigned long i = 0; i < test_count; ++i)
|
||||
{
|
||||
random_sorted_sequence(x);
|
||||
const const_iterator start = x.begin();
|
||||
const const_iterator finish = x.end();
|
||||
|
||||
unsigned key = random_number();
|
||||
const const_iterator l = searches<Compare>::lower_bound(start, finish, key, cmp);
|
||||
const const_iterator u = searches<Compare>::upper_bound(start, finish, key, cmp);
|
||||
|
||||
bool found_l = false;
|
||||
bool found_u = false;
|
||||
std::size_t index = 0;
|
||||
std::size_t count = 0;
|
||||
unsigned last_value = 0;
|
||||
for (const_iterator p = start; p != finish; ++p)
|
||||
{
|
||||
if (p == l)
|
||||
found_l = true;
|
||||
|
||||
if (p == u)
|
||||
{
|
||||
assert(found_l);
|
||||
found_u = true;
|
||||
}
|
||||
|
||||
unsigned value = to_int(*p);
|
||||
assert(value >= last_value);
|
||||
last_value = value;
|
||||
|
||||
if (!found_l)
|
||||
{
|
||||
++index;
|
||||
assert(to_int(*p) < key);
|
||||
}
|
||||
else if (!found_u)
|
||||
{
|
||||
++count;
|
||||
assert(to_int(*p) == key);
|
||||
}
|
||||
else
|
||||
assert(to_int(*p) > key);
|
||||
}
|
||||
assert(found_l || l == finish);
|
||||
assert(found_u || u == finish);
|
||||
|
||||
std::pair<const_iterator, const_iterator>
|
||||
range = searches<Compare>::equal_range(start, finish, key, cmp);
|
||||
assert(range.first == l);
|
||||
assert(range.second == u);
|
||||
|
||||
bool found = searches<Compare>::binary_search(start, finish, key, cmp);
|
||||
assert(found == (u != l));
|
||||
std::cout << "found " << count << " copies of " << key << " at index " << index << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
std::vector<std::string> x;
|
||||
std::cout << "=== testing random-access iterators with <: ===\n";
|
||||
test_loop(x, no_compare(), 25);
|
||||
std::cout << "=== testing random-access iterators with compare: ===\n";
|
||||
test_loop(x, cmp(), 25);
|
||||
|
||||
std::list<std::string> y;
|
||||
std::cout << "=== testing bidirectional iterators with <: ===\n";
|
||||
test_loop(y, no_compare(), 25);
|
||||
std::cout << "=== testing bidirectional iterators with compare: ===\n";
|
||||
test_loop(y, cmp(), 25);
|
||||
std::cerr << "******TEST PASSED******\n";
|
||||
return 0;
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
content="text/html; charset=iso-8859-1">
|
||||
<meta name="Template"
|
||||
content="C:\PROGRAM FILES\MICROSOFT OFFICE\OFFICE\html.dot">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage Express 2.0">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<title>Call Traits</title>
|
||||
</head>
|
||||
|
||||
@ -592,8 +592,7 @@ would prevent template argument deduction from functioning.</p>
|
||||
<p>The call_traits template will "optimize" the passing
|
||||
of a small built-in type as a function parameter, this mainly has
|
||||
an effect when the parameter is used within a loop body. In the
|
||||
following example (see <a
|
||||
href="../type_traits/examples/fill_example.cpp">fill_example.cpp</a>),
|
||||
following example (see <a href="algo_opt_examples.cpp">algo_opt_examples.cpp</a>),
|
||||
a version of std::fill is optimized in two ways: if the type
|
||||
passed is a single byte built-in type then std::memset is used to
|
||||
effect the fill, otherwise a conventional C++ implemention is
|
||||
@ -752,8 +751,7 @@ Hinnant and John Maddock.</p>
|
||||
<p>Maintained by <a href="mailto:John_Maddock@compuserve.com">John
|
||||
Maddock</a>, the latest version of this file can be found at <a
|
||||
href="http://www.boost.org/">www.boost.org</a>, and the boost
|
||||
discussion list at <a
|
||||
href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
|
||||
discussion list at <a href="http://www.yahoogroups.com/list/boost">www.yahoogroups.com/list/boost</a>.</p>
|
||||
|
||||
<p>.</p>
|
||||
|
||||
|
@ -6,8 +6,6 @@
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// standalone test program for <boost/call_traits.hpp>
|
||||
// 18 Mar 2002:
|
||||
// Changed some names to prevent conflicts with some new type_traits additions.
|
||||
// 03 Oct 2000:
|
||||
// Enabled extra tests for VC6.
|
||||
|
||||
@ -19,10 +17,6 @@
|
||||
#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:
|
||||
@ -50,7 +44,7 @@ struct contained
|
||||
reference get() { return v_; }
|
||||
const_reference const_get()const { return v_; }
|
||||
// pass value:
|
||||
void call(param_type){}
|
||||
void call(param_type p){}
|
||||
|
||||
};
|
||||
|
||||
@ -75,12 +69,12 @@ struct contained<T[N]>
|
||||
// return by_ref:
|
||||
reference get() { return v_; }
|
||||
const_reference const_get()const { return v_; }
|
||||
void call(param_type){}
|
||||
void call(param_type p){}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
contained<typename boost::call_traits<T>::value_type> test_wrap_type(const T& t)
|
||||
contained<typename boost::call_traits<T>::value_type> wrap(const T& t)
|
||||
{
|
||||
typedef typename boost::call_traits<T>::value_type ct;
|
||||
return contained<ct>(t);
|
||||
@ -162,10 +156,10 @@ struct call_traits_checker<T[N]>
|
||||
|
||||
//
|
||||
// check_wrap:
|
||||
template <class W, class U>
|
||||
void check_wrap(const W& w, const U& u)
|
||||
template <class T, class U>
|
||||
void check_wrap(const contained<T>& w, const U& u)
|
||||
{
|
||||
cout << "checking " << typeid(W).name() << "..." << endl;
|
||||
cout << "checking contained<" << typeid(T).name() << ">..." << endl;
|
||||
assert(w.value() == u);
|
||||
}
|
||||
|
||||
@ -187,12 +181,6 @@ 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_; }
|
||||
};
|
||||
|
||||
@ -205,23 +193,26 @@ 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(__ICL)
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
|
||||
call_traits_checker<int*> c3;
|
||||
c3(pi);
|
||||
call_traits_checker<int&> c4;
|
||||
c4(i);
|
||||
call_traits_checker<const int&> c5;
|
||||
c5(i);
|
||||
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__) && !defined(__SUNPRO_CC)
|
||||
#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
|
||||
int a[2] = {1,2};
|
||||
call_traits_checker<int[2]> c6;
|
||||
c6(a);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
check_wrap(test_wrap_type(2), 2);
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
|
||||
check_wrap(test_wrap_type(a), a);
|
||||
check_wrap(wrap(2), 2);
|
||||
const char ca[4] = "abc";
|
||||
// compiler can't deduce this for some reason:
|
||||
//check_wrap(wrap(ca), ca);
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
check_wrap(wrap(a), a);
|
||||
check_make_pair(test::make_pair(a, a), a, a);
|
||||
#endif
|
||||
|
||||
@ -242,12 +233,12 @@ int main(int argc, char *argv[ ])
|
||||
type_test(int*&, boost::call_traits<int*>::reference)
|
||||
type_test(int*const&, boost::call_traits<int*>::const_reference)
|
||||
type_test(int*const, boost::call_traits<int*>::param_type)
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
|
||||
type_test(int&, boost::call_traits<int&>::value_type)
|
||||
type_test(int&, boost::call_traits<int&>::reference)
|
||||
type_test(const int&, boost::call_traits<int&>::const_reference)
|
||||
type_test(int&, boost::call_traits<int&>::param_type)
|
||||
#if !(defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1)))
|
||||
#if !(defined(__GNUC__) && (__GNUC__ < 3))
|
||||
type_test(int&, boost::call_traits<cr_type>::value_type)
|
||||
type_test(int&, boost::call_traits<cr_type>::reference)
|
||||
type_test(const int&, boost::call_traits<cr_type>::const_reference)
|
||||
@ -270,26 +261,16 @@ int main(int argc, char *argv[ ])
|
||||
type_test(const int(&)[3], boost::call_traits<const int[3]>::reference)
|
||||
type_test(const int(&)[3], boost::call_traits<const int[3]>::const_reference)
|
||||
type_test(const int*const, boost::call_traits<const int[3]>::param_type)
|
||||
// test with abstract base class:
|
||||
type_test(test_abc1, boost::call_traits<test_abc1>::value_type)
|
||||
type_test(test_abc1&, boost::call_traits<test_abc1>::reference)
|
||||
type_test(const test_abc1&, boost::call_traits<test_abc1>::const_reference)
|
||||
type_test(const test_abc1&, boost::call_traits<test_abc1>::param_type)
|
||||
#else
|
||||
std::cout << "You're compiler does not support partial template specialiation, skipping 8 tests (8 errors)" << std::endl;
|
||||
failures += 12;
|
||||
test_count += 12;
|
||||
std::cout << "You're compiler does not support partial template instantiation, skipping 8 tests (8 errors)" << std::endl;
|
||||
failures += 8;
|
||||
test_count += 8;
|
||||
#endif
|
||||
#else
|
||||
std::cout << "You're compiler does not support partial template specialiation, skipping 20 tests (20 errors)" << std::endl;
|
||||
failures += 24;
|
||||
test_count += 24;
|
||||
std::cout << "You're compiler does not support partial template instantiation, skipping 20 tests (20 errors)" << std::endl;
|
||||
failures += 20;
|
||||
test_count += 20;
|
||||
#endif
|
||||
// test with an incomplete type:
|
||||
type_test(incomplete_type, boost::call_traits<incomplete_type>::value_type)
|
||||
type_test(incomplete_type&, boost::call_traits<incomplete_type>::reference)
|
||||
type_test(const incomplete_type&, boost::call_traits<incomplete_type>::const_reference)
|
||||
type_test(const incomplete_type&, boost::call_traits<incomplete_type>::param_type)
|
||||
|
||||
return check_result(argc, argv);
|
||||
}
|
||||
@ -331,19 +312,6 @@ 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>
|
||||
@ -380,19 +348,6 @@ 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);
|
||||
#ifndef __BORLANDC__
|
||||
unused_variable(r2);
|
||||
unused_variable(cr2);
|
||||
#endif
|
||||
unused_variable(cr3);
|
||||
unused_variable(p2);
|
||||
unused_variable(p3);
|
||||
unused_variable(p4);
|
||||
}
|
||||
#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
//
|
||||
@ -400,31 +355,26 @@ void call_traits_test<T, true>::assert_construct(typename boost::call_traits<T>:
|
||||
template struct call_traits_test<int>;
|
||||
template struct call_traits_test<const int>;
|
||||
template struct call_traits_test<int*>;
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES)
|
||||
#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES)
|
||||
template struct call_traits_test<int&>;
|
||||
template struct call_traits_test<const int&>;
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC)
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template struct call_traits_test<int[2], true>;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_MSVC
|
||||
unsigned int expected_failures = 14;
|
||||
unsigned int expected_failures = 10;
|
||||
#elif defined(__SUNPRO_CC)
|
||||
#if(__SUNPRO_CC <= 0x520)
|
||||
unsigned int expected_failures = 18;
|
||||
#elif(__SUNPRO_CC < 0x530)
|
||||
unsigned int expected_failures = 17;
|
||||
#else
|
||||
unsigned int expected_failures = 6;
|
||||
#endif
|
||||
unsigned int expected_failures = 11;
|
||||
#elif defined(__BORLANDC__)
|
||||
unsigned int expected_failures = 2;
|
||||
#elif (defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1)))
|
||||
#elif defined(__GNUC__)
|
||||
unsigned int expected_failures = 4;
|
||||
#elif defined(__HP_aCC)
|
||||
unsigned int expected_failures = 24;
|
||||
#else
|
||||
unsigned int expected_failures = 0;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -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 base-class optimisation" is applied to compress
|
||||
the size of the pair.</p>
|
||||
"empty member 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, second_param_type)
|
||||
void compressed_pair_reference1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
|
||||
{
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// 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, second_param_type)
|
||||
void compressed_pair_reference2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
|
||||
{
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
// second param construct:
|
||||
@ -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, second_param_type)
|
||||
void compressed_pair_array1_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
|
||||
{
|
||||
// default construct:
|
||||
boost::compressed_pair<T1,T2> cp1;
|
||||
@ -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, second_param_type)
|
||||
void compressed_pair_array2_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
|
||||
{
|
||||
// default construct:
|
||||
boost::compressed_pair<T1,T2> cp1;
|
||||
@ -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, second_param_type)
|
||||
void compressed_pair_array_tester<T1, T2>::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4)
|
||||
{
|
||||
// default construct:
|
||||
boost::compressed_pair<T1,T2> cp1;
|
||||
@ -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, char *[])
|
||||
int test_main(int argc, char *argv[ ])
|
||||
{
|
||||
// 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 -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" --></p>
|
||||
<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><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"
|
||||
|
@ -22,8 +22,8 @@ int main(int, char*[])
|
||||
// Example of using make_counting_iterator()
|
||||
std::cout << "counting from -5 to 4:" << std::endl;
|
||||
std::copy(boost::make_counting_iterator(-5),
|
||||
boost::make_counting_iterator(5),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
boost::make_counting_iterator(5),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example of using counting iterator to create an array of pointers.
|
||||
@ -31,27 +31,23 @@ int main(int, char*[])
|
||||
std::vector<int> numbers;
|
||||
// Fill "numbers" array with [0,N)
|
||||
std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N),
|
||||
std::back_inserter(numbers));
|
||||
std::back_inserter(numbers));
|
||||
|
||||
std::vector<std::vector<int>::iterator> pointers;
|
||||
|
||||
// Use counting iterator to fill in the array of pointers.
|
||||
// causes an ICE with MSVC6
|
||||
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
|
||||
std::copy(boost::make_counting_iterator(numbers.begin()),
|
||||
boost::make_counting_iterator(numbers.end()),
|
||||
std::back_inserter(pointers));
|
||||
#endif
|
||||
boost::make_counting_iterator(numbers.end()),
|
||||
std::back_inserter(pointers));
|
||||
|
||||
#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1300)
|
||||
// Use indirect iterator to print out numbers by accessing
|
||||
// them through the array of pointers.
|
||||
std::cout << "indirectly printing out the numbers from 0 to "
|
||||
<< N << std::endl;
|
||||
<< N << std::endl;
|
||||
std::copy(boost::make_indirect_iterator(pointers.begin()),
|
||||
boost::make_indirect_iterator(pointers.end()),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
boost::make_indirect_iterator(pointers.end()),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -27,9 +27,7 @@
|
||||
#include <climits>
|
||||
#include <iterator>
|
||||
#include <stdlib.h>
|
||||
#ifndef __BORLANDC__
|
||||
# include <boost/tuple/tuple.hpp>
|
||||
#endif
|
||||
#include <boost/utility.hpp>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <cassert>
|
||||
@ -74,12 +72,8 @@ void category_test(
|
||||
|
||||
// Try some binary searches on the range to show that it's ordered
|
||||
assert(std::binary_search(start, finish, *internal));
|
||||
|
||||
// #including tuple crashed borland, so I had to give up on tie().
|
||||
std::pair<CountingIterator,CountingIterator> xy(
|
||||
std::equal_range(start, finish, *internal));
|
||||
CountingIterator x = xy.first, y = xy.second;
|
||||
|
||||
CountingIterator x,y;
|
||||
boost::tie(x,y) = std::equal_range(start, finish, *internal);
|
||||
assert(boost::detail::distance(x, y) == 1);
|
||||
|
||||
// Show that values outside the range can't be found
|
||||
@ -240,14 +234,14 @@ int main()
|
||||
test_integer<unsigned int>();
|
||||
test_integer<long>();
|
||||
test_integer<unsigned long>();
|
||||
#if defined(BOOST_HAS_LONG_LONG)
|
||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
|
||||
test_integer<long long>();
|
||||
test_integer<unsigned long long>();
|
||||
#endif
|
||||
|
||||
// wrapping an iterator or non-built-in integer type causes an INTERNAL
|
||||
// COMPILER ERROR in MSVC without STLport. I'm clueless as to why.
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 || defined(__SGI_STL_PORT)
|
||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
|
||||
// Test user-defined type.
|
||||
test_integer<my_int1>();
|
||||
test_integer<my_int2>();
|
||||
@ -259,7 +253,7 @@ int main()
|
||||
# ifndef BOOST_NO_SLIST
|
||||
test_container<BOOST_STD_EXTENSION_NAMESPACE::slist<int> >();
|
||||
# endif
|
||||
|
||||
|
||||
// Also prove that we can handle raw pointers.
|
||||
int array[2000];
|
||||
test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1));
|
||||
|
@ -1,32 +0,0 @@
|
||||
#if defined(_MSC_VER) && !defined(__ICL)
|
||||
#pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
#pragma warning(disable: 4710) // function not inlined
|
||||
#pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
#pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
//
|
||||
// current_function_test.cpp - a test for boost/current_function.hpp
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
|
||||
#include <boost/current_function.hpp>
|
||||
#include <cstdio>
|
||||
|
||||
void message(char const * file, long line, char const * func, char const * msg)
|
||||
{
|
||||
std::printf("%s(%ld): %s in function '%s'\n", file, line, msg, func);
|
||||
}
|
||||
|
||||
#define MESSAGE(msg) message(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, msg)
|
||||
|
||||
int main()
|
||||
{
|
||||
MESSAGE("assertion failed");
|
||||
}
|
@ -195,7 +195,7 @@ The policies type has only one public function, which is its constructor:
|
||||
|
||||
<pre>
|
||||
template <class Predicate, class BaseIterator>
|
||||
typename filter_generator<Predicate, BaseIterator>::type
|
||||
typename detail::filter_generator<Predicate, BaseIterator>::type
|
||||
make_filter_iterator(BaseIterator first, BaseIterator last, const Predicate& p = Predicate())
|
||||
</pre>
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
@ -19,26 +20,17 @@ struct is_positive_number {
|
||||
|
||||
int main()
|
||||
{
|
||||
int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 };
|
||||
const int N = sizeof(numbers_)/sizeof(int);
|
||||
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
// Assume there won't be proper iterator traits for pointers. This
|
||||
// is just a wrapper for int* which has the right traits.
|
||||
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies, int> base_iterator;
|
||||
#else
|
||||
typedef int* base_iterator;
|
||||
#endif
|
||||
base_iterator numbers(numbers_);
|
||||
|
||||
int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
|
||||
const int N = sizeof(numbers)/sizeof(int);
|
||||
|
||||
// Example using make_filter_iterator()
|
||||
std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
|
||||
boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Example using filter_iterator_generator
|
||||
typedef boost::filter_iterator_generator<is_positive_number, base_iterator, int>::type
|
||||
typedef boost::filter_iterator_generator<is_positive_number, int*, int>::type
|
||||
FilterIter;
|
||||
is_positive_number predicate;
|
||||
FilterIter::policies_type policies(predicate, numbers + N);
|
||||
@ -50,10 +42,10 @@ int main()
|
||||
|
||||
// Another example using make_filter_iterator()
|
||||
std::copy(boost::make_filter_iterator(numbers, numbers + N,
|
||||
std::bind2nd(std::greater<int>(), -2)),
|
||||
boost::make_filter_iterator(numbers + N, numbers + N,
|
||||
std::bind2nd(std::greater<int>(), -2)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::bind2nd(std::greater<int>(), -2)),
|
||||
boost::make_filter_iterator(numbers + N, numbers + N,
|
||||
std::bind2nd(std::greater<int>(), -2)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
|
@ -33,7 +33,7 @@ int main(int, char*[])
|
||||
|
||||
std::string s = "";
|
||||
std::copy(x.begin(), x.end(),
|
||||
boost::make_function_output_iterator(string_appender(s)));
|
||||
boost::make_function_output_iterator(string_appender(s)));
|
||||
|
||||
std::cout << s << std::endl;
|
||||
|
||||
|
@ -1,150 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Generator Iterator Adaptor Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">
|
||||
|
||||
<h1>Generator Iterator Adaptor</h1>
|
||||
Defined in header <a href="../../boost/generator_iterator.hpp">boost/generator_iterator.hpp</a>
|
||||
<p>
|
||||
The generator iterator adaptor makes it easier to create custom input
|
||||
iterators from 0-ary functions and function objects. The adaptor
|
||||
takes a
|
||||
<a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>
|
||||
and creates a model of
|
||||
<a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>.
|
||||
Each increment retrieves an item from the generator and makes it
|
||||
available to be retrieved by dereferencing. The motivation for this
|
||||
iterator is that some concepts can be more naturally expressed as a
|
||||
generator, while most STL algorithms expect an iterator. An example
|
||||
is the <a href="../random/index.html">Random Number</a> library.
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <class Generator>
|
||||
class generator_iterator_policies;
|
||||
|
||||
template <class Generator>
|
||||
class generator_iterator_generator;
|
||||
|
||||
template <class Generator>
|
||||
typename generator_iterator_generator<Generator>::type
|
||||
make_generator_iterator(Generator & gen);
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
<h2>The Generator Iterator Generator Class</h2>
|
||||
|
||||
The class generator_iterator_generator is a helper class whose purpose
|
||||
is to construct a generator iterator type. The template parameter for
|
||||
this class is the Generator function object type that is being
|
||||
wrapped. The generator iterator adaptor only holds a reference (or
|
||||
pointer) to the function object, therefore the function object must
|
||||
outlive the generator iterator adaptor constructed from it.
|
||||
|
||||
<pre>
|
||||
template <class Generator>
|
||||
class generator_iterator_generator
|
||||
{
|
||||
public:
|
||||
typedef <a href="iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...> type; // the resulting generator iterator type
|
||||
}
|
||||
</pre>
|
||||
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<table border>
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><tt><a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a></tt>
|
||||
<td>The generator (0-ary function object) type being
|
||||
wrapped. The return type of the function must be defined as
|
||||
<tt>Generator::result_type</tt>. The function object must be a model
|
||||
of
|
||||
<a href="http://www.sgi.com/tech/stl/Generator.html">Generator</a>.
|
||||
</td>
|
||||
</table>
|
||||
|
||||
<h3>Concept Model</h3>
|
||||
The generator iterator class is a model of
|
||||
<a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>.
|
||||
|
||||
<h3>Members</h3>
|
||||
The generator iterator implements the member functions
|
||||
and operators required of the
|
||||
<a href="http://www.sgi.com/tech/stl/InputIterator.html">Input Iterator</a>
|
||||
concept.
|
||||
|
||||
<br>
|
||||
|
||||
<hr>
|
||||
<h2><a name="make_generator_iterator">The Generator Iterator Object Generator</a></h2>
|
||||
|
||||
The <tt>make_generator_iterator()</tt> function provides a
|
||||
convenient way to create generator iterator objects. The function
|
||||
saves the user the trouble of explicitly writing out the iterator
|
||||
types.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class Generator>
|
||||
typename generator_iterator_generator<Generator>::type
|
||||
make_function_output_iterator(Generator & gen);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
The following program shows how <code>generator_iterator</code>
|
||||
transforms a generator into an input iterator.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <iostream>
|
||||
#include <boost/generator_iterator.hpp>
|
||||
|
||||
class my_generator
|
||||
{
|
||||
public:
|
||||
typedef int result_type;
|
||||
my_generator() : state(0) { }
|
||||
int operator()() { return ++state; }
|
||||
private:
|
||||
int state;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
my_generator gen;
|
||||
boost::generator_iterator_generator<my_generator>::type it = boost::make_generator_iterator(gen);
|
||||
for(int i = 0; i < 10; ++i, ++it)
|
||||
std::cout << *it << std::endl;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<hr>
|
||||
|
||||
Written by Jens Maurer.
|
||||
|
||||
</body>
|
||||
</html>
|
@ -346,7 +346,7 @@ int main()
|
||||
test_integer<unsigned int>();
|
||||
test_integer<long>();
|
||||
test_integer<unsigned long>();
|
||||
#if defined(BOOST_HAS_LONG_LONG)
|
||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
|
||||
test_integer<long long>();
|
||||
test_integer<unsigned long long>();
|
||||
#endif
|
||||
|
@ -1,52 +0,0 @@
|
||||
#ifndef BOOST_ASSERT_HPP_INCLUDED
|
||||
#define BOOST_ASSERT_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/assert.hpp
|
||||
//
|
||||
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
|
||||
//
|
||||
// When BOOST_DEBUG is not defined, it defaults to 0 (off)
|
||||
// for compatibility with programs that do not expect asserts
|
||||
// in the smart pointer class templates.
|
||||
//
|
||||
// This default may be changed after an initial transition period.
|
||||
//
|
||||
|
||||
#ifndef BOOST_DEBUG
|
||||
#define BOOST_DEBUG 0
|
||||
#endif
|
||||
|
||||
#if BOOST_DEBUG
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef BOOST_ASSERT
|
||||
|
||||
#include <boost/current_function.hpp>
|
||||
|
||||
bool boost_error(char const * expr, char const * func, char const * file, long line);
|
||||
|
||||
# define BOOST_ASSERT(expr) ((expr) || !boost_error(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__) || (assert(expr), true))
|
||||
|
||||
#endif // #ifndef BOOST_ASSERT
|
||||
|
||||
#else // #if BOOST_DEBUG
|
||||
|
||||
#undef BOOST_ASSERT
|
||||
#define BOOST_ASSERT(expr) ((void)0)
|
||||
|
||||
#endif // #if BOOST_DEBUG
|
||||
|
||||
#endif // #ifndef BOOST_ASSERT_HPP_INCLUDED
|
@ -1,23 +0,0 @@
|
||||
// (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
// See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp
|
||||
// for full copyright notices.
|
||||
|
||||
#ifndef BOOST_CALL_TRAITS_HPP
|
||||
#define BOOST_CALL_TRAITS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#include <boost/detail/ob_call_traits.hpp>
|
||||
#else
|
||||
#include <boost/detail/call_traits.hpp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_CALL_TRAITS_HPP
|
@ -1,60 +0,0 @@
|
||||
#ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
|
||||
#define BOOST_CHECKED_DELETE_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/checked_delete.hpp
|
||||
//
|
||||
// Copyright (c) 1999, 2000, 2001, 2002 boost.org
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
// verify that types are complete for increased safety
|
||||
|
||||
template< typename T > inline void checked_delete(T * x)
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
delete x;
|
||||
}
|
||||
|
||||
template< typename T > inline void checked_array_delete(T * x)
|
||||
{
|
||||
typedef char type_must_be_complete[sizeof(T)];
|
||||
delete [] x;
|
||||
}
|
||||
|
||||
template<class T> struct checked_deleter
|
||||
{
|
||||
typedef void result_type;
|
||||
typedef T * argument_type;
|
||||
|
||||
void operator()(T * x)
|
||||
{
|
||||
checked_delete(x);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T> struct checked_array_deleter
|
||||
{
|
||||
typedef void result_type;
|
||||
typedef T * argument_type;
|
||||
|
||||
void operator()(T * x)
|
||||
{
|
||||
checked_array_delete(x);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_CHECKED_DELETE_HPP_INCLUDED
|
@ -1,23 +0,0 @@
|
||||
// (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
// See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp
|
||||
// for full copyright notices.
|
||||
|
||||
#ifndef BOOST_COMPRESSED_PAIR_HPP
|
||||
#define BOOST_COMPRESSED_PAIR_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
#include <boost/detail/ob_compressed_pair.hpp>
|
||||
#else
|
||||
#include <boost/detail/compressed_pair.hpp>
|
||||
#endif
|
||||
|
||||
#endif // BOOST_COMPRESSED_PAIR_HPP
|
@ -1,56 +0,0 @@
|
||||
#ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
||||
#define BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
||||
|
||||
#if _MSC_VER >= 1020
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
//
|
||||
// boost/current_function.hpp - BOOST_CURRENT_FUNCTION
|
||||
//
|
||||
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
inline void current_function_helper()
|
||||
{
|
||||
|
||||
#if defined(__GNUC__)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
|
||||
|
||||
#elif defined(__FUNCSIG__)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __FUNCSIG__
|
||||
|
||||
#elif defined(__BORLANDC__)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __FUNC__
|
||||
|
||||
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION __func__
|
||||
|
||||
#else
|
||||
|
||||
# define BOOST_CURRENT_FUNCTION "(unknown)"
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_CURRENT_FUNCTION_HPP_INCLUDED
|
@ -1,158 +0,0 @@
|
||||
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// call_traits: defines typedefs for function usage
|
||||
// (see libs/utility/call_traits.htm)
|
||||
|
||||
/* Release notes:
|
||||
23rd July 2000:
|
||||
Fixed array specialization. (JM)
|
||||
Added Borland specific fixes for reference types
|
||||
(issue raised by Steve Cleary).
|
||||
*/
|
||||
|
||||
#ifndef BOOST_DETAIL_CALL_TRAITS_HPP
|
||||
#define BOOST_DETAIL_CALL_TRAITS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/arithmetic_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/composite_traits.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <typename T, bool small_>
|
||||
struct ct_imp2
|
||||
{
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ct_imp2<T, true>
|
||||
{
|
||||
typedef const T param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool isp, bool b1>
|
||||
struct ct_imp
|
||||
{
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool isp>
|
||||
struct ct_imp<T, isp, true>
|
||||
{
|
||||
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool b1>
|
||||
struct ct_imp<T, true, b1>
|
||||
{
|
||||
typedef T const param_type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct call_traits
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
//
|
||||
// C++ Builder workaround: we should be able to define a compile time
|
||||
// constant and pass that as a single template parameter to ct_imp<T,bool>,
|
||||
// however compiler bugs prevent this - instead pass three bool's to
|
||||
// ct_imp<T,bool,bool,bool> and add an extra partial specialisation
|
||||
// of ct_imp to handle the logic. (JM)
|
||||
typedef typename detail::ct_imp<
|
||||
T,
|
||||
::boost::is_pointer<T>::value,
|
||||
::boost::is_arithmetic<T>::value
|
||||
>::param_type param_type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct call_traits<T&>
|
||||
{
|
||||
typedef T& value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
|
||||
#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
|
||||
// these are illegal specialisations; cv-qualifies applied to
|
||||
// references have no effect according to [8.3.2p1],
|
||||
// C++ Builder requires them though as it treats cv-qualified
|
||||
// references as distinct types...
|
||||
template <typename T>
|
||||
struct call_traits<T&const>
|
||||
{
|
||||
typedef T& value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
template <typename T>
|
||||
struct call_traits<T&volatile>
|
||||
{
|
||||
typedef T& value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
template <typename T>
|
||||
struct call_traits<T&const volatile>
|
||||
{
|
||||
typedef T& value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
#endif
|
||||
#ifndef __SUNPRO_CC
|
||||
template <typename T, std::size_t N>
|
||||
struct call_traits<T [N]>
|
||||
{
|
||||
private:
|
||||
typedef T array_type[N];
|
||||
public:
|
||||
// degrades array to pointer:
|
||||
typedef const T* value_type;
|
||||
typedef array_type& reference;
|
||||
typedef const array_type& const_reference;
|
||||
typedef const T* const param_type;
|
||||
};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
struct call_traits<const T [N]>
|
||||
{
|
||||
private:
|
||||
typedef const T array_type[N];
|
||||
public:
|
||||
// degrades array to pointer:
|
||||
typedef const T* value_type;
|
||||
typedef array_type& reference;
|
||||
typedef const array_type& const_reference;
|
||||
typedef const T* const param_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_DETAIL_CALL_TRAITS_HPP
|
@ -1,435 +0,0 @@
|
||||
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// compressed_pair: pair that "compresses" empty members
|
||||
// (see libs/utility/compressed_pair.htm)
|
||||
//
|
||||
// JM changes 25 Jan 2000:
|
||||
// Removed default arguments from compressed_pair_switch to get
|
||||
// C++ Builder 4 to accept them
|
||||
// rewriten swap to get gcc and C++ builder to compile.
|
||||
// added partial specialisations for case T1 == T2 to avoid duplicate constructor defs.
|
||||
|
||||
#ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP
|
||||
#define BOOST_DETAIL_COMPRESSED_PAIR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/object_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_SAME_TRAITS_HPP
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_CALL_TRAITS_HPP
|
||||
#include <boost/call_traits.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair;
|
||||
|
||||
|
||||
// compressed_pair
|
||||
|
||||
namespace details
|
||||
{
|
||||
// JM altered 26 Jan 2000:
|
||||
template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty>
|
||||
struct compressed_pair_switch;
|
||||
|
||||
template <class T1, class T2>
|
||||
struct compressed_pair_switch<T1, T2, false, false, false>
|
||||
{static const int value = 0;};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct compressed_pair_switch<T1, T2, false, true, true>
|
||||
{static const int value = 3;};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct compressed_pair_switch<T1, T2, false, true, false>
|
||||
{static const int value = 1;};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct compressed_pair_switch<T1, T2, false, false, true>
|
||||
{static const int value = 2;};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct compressed_pair_switch<T1, T2, true, true, true>
|
||||
{static const int value = 4;};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct compressed_pair_switch<T1, T2, true, false, false>
|
||||
{static const int value = 5;};
|
||||
|
||||
template <class T1, class T2, int Version> class compressed_pair_imp;
|
||||
|
||||
#ifdef __GNUC__
|
||||
// workaround for GCC (JM):
|
||||
using std::swap;
|
||||
#endif
|
||||
//
|
||||
// can't call unqualified swap from within classname::swap
|
||||
// as Koenig lookup rules will find only the classname::swap
|
||||
// member function not the global declaration, so use cp_swap
|
||||
// as a forwarding function (JM):
|
||||
template <typename T>
|
||||
inline void cp_swap(T& t1, T& t2)
|
||||
{
|
||||
#ifndef __GNUC__
|
||||
using std::swap;
|
||||
#endif
|
||||
swap(t1, t2);
|
||||
}
|
||||
|
||||
// 0 derive from neither
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_imp<T1, T2, 0>
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_imp() {}
|
||||
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_(x), second_(y) {}
|
||||
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_(x) {}
|
||||
|
||||
compressed_pair_imp(second_param_type y)
|
||||
: second_(y) {}
|
||||
|
||||
first_reference first() {return first_;}
|
||||
first_const_reference first() const {return first_;}
|
||||
|
||||
second_reference second() {return second_;}
|
||||
second_const_reference second() const {return second_;}
|
||||
|
||||
void swap(::boost::compressed_pair<T1, T2>& y)
|
||||
{
|
||||
cp_swap(first_, y.first());
|
||||
cp_swap(second_, y.second());
|
||||
}
|
||||
private:
|
||||
first_type first_;
|
||||
second_type second_;
|
||||
};
|
||||
|
||||
// 1 derive from T1
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_imp<T1, T2, 1>
|
||||
: private T1
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_imp() {}
|
||||
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_type(x), second_(y) {}
|
||||
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_type(x) {}
|
||||
|
||||
compressed_pair_imp(second_param_type y)
|
||||
: second_(y) {}
|
||||
|
||||
first_reference first() {return *this;}
|
||||
first_const_reference first() const {return *this;}
|
||||
|
||||
second_reference second() {return second_;}
|
||||
second_const_reference second() const {return second_;}
|
||||
|
||||
void swap(::boost::compressed_pair<T1,T2>& y)
|
||||
{
|
||||
// no need to swap empty base class:
|
||||
cp_swap(second_, y.second());
|
||||
}
|
||||
private:
|
||||
second_type second_;
|
||||
};
|
||||
|
||||
// 2 derive from T2
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_imp<T1, T2, 2>
|
||||
: private T2
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_imp() {}
|
||||
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: second_type(y), first_(x) {}
|
||||
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_(x) {}
|
||||
|
||||
compressed_pair_imp(second_param_type y)
|
||||
: second_type(y) {}
|
||||
|
||||
first_reference first() {return first_;}
|
||||
first_const_reference first() const {return first_;}
|
||||
|
||||
second_reference second() {return *this;}
|
||||
second_const_reference second() const {return *this;}
|
||||
|
||||
void swap(::boost::compressed_pair<T1,T2>& y)
|
||||
{
|
||||
// no need to swap empty base class:
|
||||
cp_swap(first_, y.first());
|
||||
}
|
||||
|
||||
private:
|
||||
first_type first_;
|
||||
};
|
||||
|
||||
// 3 derive from T1 and T2
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_imp<T1, T2, 3>
|
||||
: private T1,
|
||||
private T2
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_imp() {}
|
||||
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_type(x), second_type(y) {}
|
||||
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_type(x) {}
|
||||
|
||||
compressed_pair_imp(second_param_type y)
|
||||
: second_type(y) {}
|
||||
|
||||
first_reference first() {return *this;}
|
||||
first_const_reference first() const {return *this;}
|
||||
|
||||
second_reference second() {return *this;}
|
||||
second_const_reference second() const {return *this;}
|
||||
//
|
||||
// no need to swap empty bases:
|
||||
void swap(::boost::compressed_pair<T1,T2>&) {}
|
||||
};
|
||||
|
||||
// JM
|
||||
// 4 T1 == T2, T1 and T2 both empty
|
||||
// Note does not actually store an instance of T2 at all -
|
||||
// but reuses T1 base class for both first() and second().
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_imp<T1, T2, 4>
|
||||
: private T1
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_imp() {}
|
||||
|
||||
compressed_pair_imp(first_param_type x, second_param_type)
|
||||
: first_type(x) {}
|
||||
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_type(x) {}
|
||||
|
||||
first_reference first() {return *this;}
|
||||
first_const_reference first() const {return *this;}
|
||||
|
||||
second_reference second() {return *this;}
|
||||
second_const_reference second() const {return *this;}
|
||||
|
||||
void swap(::boost::compressed_pair<T1,T2>&) {}
|
||||
private:
|
||||
};
|
||||
|
||||
// 5 T1 == T2 and are not empty: //JM
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_imp<T1, T2, 5>
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_imp() {}
|
||||
|
||||
compressed_pair_imp(first_param_type x, second_param_type y)
|
||||
: first_(x), second_(y) {}
|
||||
|
||||
compressed_pair_imp(first_param_type x)
|
||||
: first_(x), second_(x) {}
|
||||
|
||||
first_reference first() {return first_;}
|
||||
first_const_reference first() const {return first_;}
|
||||
|
||||
second_reference second() {return second_;}
|
||||
second_const_reference second() const {return second_;}
|
||||
|
||||
void swap(::boost::compressed_pair<T1, T2>& y)
|
||||
{
|
||||
cp_swap(first_, y.first());
|
||||
cp_swap(second_, y.second());
|
||||
}
|
||||
private:
|
||||
first_type first_;
|
||||
second_type second_;
|
||||
};
|
||||
|
||||
} // details
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair
|
||||
: private ::boost::details::compressed_pair_imp<T1, T2,
|
||||
::boost::details::compressed_pair_switch<
|
||||
T1,
|
||||
T2,
|
||||
::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
|
||||
::boost::is_empty<T1>::value,
|
||||
::boost::is_empty<T2>::value>::value>
|
||||
{
|
||||
private:
|
||||
typedef details::compressed_pair_imp<T1, T2,
|
||||
::boost::details::compressed_pair_switch<
|
||||
T1,
|
||||
T2,
|
||||
::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value,
|
||||
::boost::is_empty<T1>::value,
|
||||
::boost::is_empty<T2>::value>::value> base;
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair() : base() {}
|
||||
compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
|
||||
explicit compressed_pair(first_param_type x) : base(x) {}
|
||||
explicit compressed_pair(second_param_type y) : base(y) {}
|
||||
|
||||
first_reference first() {return base::first();}
|
||||
first_const_reference first() const {return base::first();}
|
||||
|
||||
second_reference second() {return base::second();}
|
||||
second_const_reference second() const {return base::second();}
|
||||
|
||||
void swap(compressed_pair& y) { base::swap(y); }
|
||||
};
|
||||
|
||||
// JM
|
||||
// Partial specialisation for case where T1 == T2:
|
||||
//
|
||||
template <class T>
|
||||
class compressed_pair<T, T>
|
||||
: private details::compressed_pair_imp<T, T,
|
||||
::boost::details::compressed_pair_switch<
|
||||
T,
|
||||
T,
|
||||
::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
|
||||
::boost::is_empty<T>::value,
|
||||
::boost::is_empty<T>::value>::value>
|
||||
{
|
||||
private:
|
||||
typedef details::compressed_pair_imp<T, T,
|
||||
::boost::details::compressed_pair_switch<
|
||||
T,
|
||||
T,
|
||||
::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value,
|
||||
::boost::is_empty<T>::value,
|
||||
::boost::is_empty<T>::value>::value> base;
|
||||
public:
|
||||
typedef T first_type;
|
||||
typedef T second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair() : base() {}
|
||||
compressed_pair(first_param_type x, second_param_type y) : base(x, y) {}
|
||||
#if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530))
|
||||
explicit
|
||||
#endif
|
||||
compressed_pair(first_param_type x) : base(x) {}
|
||||
|
||||
first_reference first() {return base::first();}
|
||||
first_const_reference first() const {return base::first();}
|
||||
|
||||
second_reference second() {return base::second();}
|
||||
second_const_reference second() const {return base::second();}
|
||||
|
||||
void swap(::boost::compressed_pair<T,T>& y) { base::swap(y); }
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
inline
|
||||
void
|
||||
swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP
|
||||
|
||||
|
||||
|
@ -1,169 +0,0 @@
|
||||
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
//
|
||||
// Crippled version for crippled compilers:
|
||||
// see libs/utility/call_traits.htm
|
||||
//
|
||||
|
||||
/* Release notes:
|
||||
01st October 2000:
|
||||
Fixed call_traits on VC6, using "poor man's partial specialisation",
|
||||
using ideas taken from "Generative programming" by Krzysztof Czarnecki
|
||||
& Ulrich Eisenecker.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OB_CALL_TRAITS_HPP
|
||||
#define BOOST_OB_CALL_TRAITS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/arithmetic_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/composite_traits.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
//
|
||||
// use member templates to emulate
|
||||
// partial specialisation:
|
||||
//
|
||||
namespace detail{
|
||||
|
||||
template <class T>
|
||||
struct standard_call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T& param_type;
|
||||
};
|
||||
template <class T>
|
||||
struct simple_call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T param_type;
|
||||
};
|
||||
template <class T>
|
||||
struct reference_call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T reference;
|
||||
typedef T const_reference;
|
||||
typedef T param_type;
|
||||
};
|
||||
|
||||
template <bool pointer, bool arithmetic, bool reference>
|
||||
struct call_traits_chooser
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
typedef standard_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_traits_chooser<true, false, false>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
typedef simple_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_traits_chooser<false, false, true>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
typedef reference_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <bool size_is_small>
|
||||
struct call_traits_sizeof_chooser2
|
||||
{
|
||||
template <class T>
|
||||
struct small_rebind
|
||||
{
|
||||
typedef simple_call_traits<T> small_type;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct call_traits_sizeof_chooser2<false>
|
||||
{
|
||||
template <class T>
|
||||
struct small_rebind
|
||||
{
|
||||
typedef standard_call_traits<T> small_type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_traits_chooser<false, true, false>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
enum { sizeof_choice = (sizeof(T) <= sizeof(void*)) };
|
||||
typedef call_traits_sizeof_chooser2<(sizeof(T) <= sizeof(void*))> chooser;
|
||||
typedef typename chooser::template small_rebind<T> bound_type;
|
||||
typedef typename bound_type::small_type type;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
template <typename T>
|
||||
struct call_traits
|
||||
{
|
||||
private:
|
||||
typedef detail::call_traits_chooser<
|
||||
::boost::is_pointer<T>::value,
|
||||
::boost::is_arithmetic<T>::value,
|
||||
::boost::is_reference<T>::value
|
||||
> chooser;
|
||||
typedef typename chooser::template rebind<T> bound_type;
|
||||
typedef typename bound_type::type call_traits_type;
|
||||
public:
|
||||
typedef typename call_traits_type::value_type value_type;
|
||||
typedef typename call_traits_type::reference reference;
|
||||
typedef typename call_traits_type::const_reference const_reference;
|
||||
typedef typename call_traits_type::param_type param_type;
|
||||
};
|
||||
|
||||
#else
|
||||
//
|
||||
// sorry call_traits is completely non-functional
|
||||
// blame your broken compiler:
|
||||
//
|
||||
|
||||
template <typename T>
|
||||
struct call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
#endif // member templates
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_OB_CALL_TRAITS_HPP
|
@ -1,509 +0,0 @@
|
||||
// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
|
||||
// Permission to copy, use, modify, sell and
|
||||
// distribute this software is granted provided this copyright notice appears
|
||||
// in all copies. This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
// see libs/utility/compressed_pair.hpp
|
||||
//
|
||||
/* Release notes:
|
||||
20 Jan 2001:
|
||||
Fixed obvious bugs (David Abrahams)
|
||||
07 Oct 2000:
|
||||
Added better single argument constructor support.
|
||||
03 Oct 2000:
|
||||
Added VC6 support (JM).
|
||||
23rd July 2000:
|
||||
Additional comments added. (JM)
|
||||
Jan 2000:
|
||||
Original version: this version crippled for use with crippled compilers
|
||||
- John Maddock Jan 2000.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
#define BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/object_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_SAME_TRAITS_HPP
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_CALL_TRAITS_HPP
|
||||
#include <boost/call_traits.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
//
|
||||
// use member templates to emulate
|
||||
// partial specialisation. Note that due to
|
||||
// problems with overload resolution with VC6
|
||||
// each of the compressed_pair versions that follow
|
||||
// have one template single-argument constructor
|
||||
// in place of two specific constructors:
|
||||
//
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair;
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class A, class T1, class T2>
|
||||
struct best_conversion_traits
|
||||
{
|
||||
typedef char one;
|
||||
typedef char (&two)[2];
|
||||
static A a;
|
||||
static one test(T1);
|
||||
static two test(T2);
|
||||
|
||||
enum { value = sizeof(test(a)) };
|
||||
};
|
||||
|
||||
template <int>
|
||||
struct init_one;
|
||||
|
||||
template <>
|
||||
struct init_one<1>
|
||||
{
|
||||
template <class A, class T1, class T2>
|
||||
static void init(const A& a, T1* p1, T2*)
|
||||
{
|
||||
*p1 = a;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct init_one<2>
|
||||
{
|
||||
template <class A, class T1, class T2>
|
||||
static void init(const A& a, T1*, T2* p2)
|
||||
{
|
||||
*p2 = a;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// T1 != T2, both non-empty
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_0
|
||||
{
|
||||
private:
|
||||
T1 _first;
|
||||
T2 _second;
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_0() : _first(), _second() {}
|
||||
compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {}
|
||||
template <class A>
|
||||
explicit compressed_pair_0(const A& val)
|
||||
{
|
||||
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
|
||||
}
|
||||
compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: _first(x.first()), _second(x.second()) {}
|
||||
|
||||
#if 0
|
||||
compressed_pair_0& operator=(const compressed_pair_0& x) {
|
||||
cout << "assigning compressed pair 0" << endl;
|
||||
_first = x._first;
|
||||
_second = x._second;
|
||||
cout << "finished assigning compressed pair 0" << endl;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
first_reference first() { return _first; }
|
||||
first_const_reference first() const { return _first; }
|
||||
|
||||
second_reference second() { return _second; }
|
||||
second_const_reference second() const { return _second; }
|
||||
|
||||
void swap(compressed_pair_0& y)
|
||||
{
|
||||
using std::swap;
|
||||
swap(_first, y._first);
|
||||
swap(_second, y._second);
|
||||
}
|
||||
};
|
||||
|
||||
// T1 != T2, T2 empty
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_1 : T2
|
||||
{
|
||||
private:
|
||||
T1 _first;
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_1() : T2(), _first() {}
|
||||
compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
|
||||
|
||||
template <class A>
|
||||
explicit compressed_pair_1(const A& val)
|
||||
{
|
||||
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
|
||||
}
|
||||
|
||||
compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T2(x.second()), _first(x.first()) {}
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
// Total weirdness. If the assignment to _first is moved after
|
||||
// the call to the inherited operator=, then this breaks graph/test/graph.cpp
|
||||
// by way of iterator_adaptor.
|
||||
compressed_pair_1& operator=(const compressed_pair_1& x) {
|
||||
_first = x._first;
|
||||
T2::operator=(x);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
first_reference first() { return _first; }
|
||||
first_const_reference first() const { return _first; }
|
||||
|
||||
second_reference second() { return *this; }
|
||||
second_const_reference second() const { return *this; }
|
||||
|
||||
void swap(compressed_pair_1& y)
|
||||
{
|
||||
// no need to swap empty base class:
|
||||
using std::swap;
|
||||
swap(_first, y._first);
|
||||
}
|
||||
};
|
||||
|
||||
// T1 != T2, T1 empty
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_2 : T1
|
||||
{
|
||||
private:
|
||||
T2 _second;
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_2() : T1(), _second() {}
|
||||
compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {}
|
||||
template <class A>
|
||||
explicit compressed_pair_2(const A& val)
|
||||
{
|
||||
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
|
||||
}
|
||||
compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T1(x.first()), _second(x.second()) {}
|
||||
|
||||
#if 0
|
||||
compressed_pair_2& operator=(const compressed_pair_2& x) {
|
||||
cout << "assigning compressed pair 2" << endl;
|
||||
T1::operator=(x);
|
||||
_second = x._second;
|
||||
cout << "finished assigning compressed pair 2" << endl;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
first_reference first() { return *this; }
|
||||
first_const_reference first() const { return *this; }
|
||||
|
||||
second_reference second() { return _second; }
|
||||
second_const_reference second() const { return _second; }
|
||||
|
||||
void swap(compressed_pair_2& y)
|
||||
{
|
||||
// no need to swap empty base class:
|
||||
using std::swap;
|
||||
swap(_second, y._second);
|
||||
}
|
||||
};
|
||||
|
||||
// T1 != T2, both empty
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_3 : T1, T2
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_3() : T1(), T2() {}
|
||||
compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {}
|
||||
template <class A>
|
||||
explicit compressed_pair_3(const A& val)
|
||||
{
|
||||
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
|
||||
}
|
||||
compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T1(x.first()), T2(x.second()) {}
|
||||
|
||||
first_reference first() { return *this; }
|
||||
first_const_reference first() const { return *this; }
|
||||
|
||||
second_reference second() { return *this; }
|
||||
second_const_reference second() const { return *this; }
|
||||
|
||||
void swap(compressed_pair_3& y)
|
||||
{
|
||||
// no need to swap empty base classes:
|
||||
}
|
||||
};
|
||||
|
||||
// T1 == T2, and empty
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_4 : T1
|
||||
{
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_4() : T1() {}
|
||||
compressed_pair_4(first_param_type x, second_param_type) : T1(x) {}
|
||||
// only one single argument constructor since T1 == T2
|
||||
explicit compressed_pair_4(first_param_type x) : T1(x) {}
|
||||
compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T1(x.first()){}
|
||||
|
||||
first_reference first() { return *this; }
|
||||
first_const_reference first() const { return *this; }
|
||||
|
||||
second_reference second() { return *this; }
|
||||
second_const_reference second() const { return *this; }
|
||||
|
||||
void swap(compressed_pair_4& y)
|
||||
{
|
||||
// no need to swap empty base classes:
|
||||
}
|
||||
};
|
||||
|
||||
// T1 == T2, not empty
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_5
|
||||
{
|
||||
private:
|
||||
T1 _first;
|
||||
T2 _second;
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair_5() : _first(), _second() {}
|
||||
compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
|
||||
// only one single argument constructor since T1 == T2
|
||||
explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
|
||||
compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c)
|
||||
: _first(c.first()), _second(c.second()) {}
|
||||
|
||||
first_reference first() { return _first; }
|
||||
first_const_reference first() const { return _first; }
|
||||
|
||||
second_reference second() { return _second; }
|
||||
second_const_reference second() const { return _second; }
|
||||
|
||||
void swap(compressed_pair_5& y)
|
||||
{
|
||||
using std::swap;
|
||||
swap(_first, y._first);
|
||||
swap(_second, y._second);
|
||||
}
|
||||
};
|
||||
|
||||
template <bool e1, bool e2, bool same>
|
||||
struct compressed_pair_chooser
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef compressed_pair_0<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct compressed_pair_chooser<false, true, false>
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef compressed_pair_1<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct compressed_pair_chooser<true, false, false>
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef compressed_pair_2<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct compressed_pair_chooser<true, true, false>
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef compressed_pair_3<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct compressed_pair_chooser<true, true, true>
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef compressed_pair_4<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct compressed_pair_chooser<false, false, true>
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef compressed_pair_5<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct compressed_pair_traits
|
||||
{
|
||||
private:
|
||||
typedef compressed_pair_chooser<is_empty<T1>::value, is_empty<T2>::value, is_same<T1,T2>::value> chooser;
|
||||
typedef typename chooser::template rebind<T1, T2> bound_type;
|
||||
public:
|
||||
typedef typename bound_type::type type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
|
||||
{
|
||||
private:
|
||||
typedef typename detail::compressed_pair_traits<T1, T2>::type base_type;
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair() : base_type() {}
|
||||
compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {}
|
||||
template <class A>
|
||||
explicit compressed_pair(const A& x) : base_type(x){}
|
||||
|
||||
first_reference first() { return base_type::first(); }
|
||||
first_const_reference first() const { return base_type::first(); }
|
||||
|
||||
second_reference second() { return base_type::second(); }
|
||||
second_const_reference second() const { return base_type::second(); }
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
#else
|
||||
// no partial specialisation, no member templates:
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair
|
||||
{
|
||||
private:
|
||||
T1 _first;
|
||||
T2 _second;
|
||||
public:
|
||||
typedef T1 first_type;
|
||||
typedef T2 second_type;
|
||||
typedef typename call_traits<first_type>::param_type first_param_type;
|
||||
typedef typename call_traits<second_type>::param_type second_param_type;
|
||||
typedef typename call_traits<first_type>::reference first_reference;
|
||||
typedef typename call_traits<second_type>::reference second_reference;
|
||||
typedef typename call_traits<first_type>::const_reference first_const_reference;
|
||||
typedef typename call_traits<second_type>::const_reference second_const_reference;
|
||||
|
||||
compressed_pair() : _first(), _second() {}
|
||||
compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {}
|
||||
explicit compressed_pair(first_param_type x) : _first(x), _second() {}
|
||||
// can't define this in case T1 == T2:
|
||||
// explicit compressed_pair(second_param_type y) : _first(), _second(y) {}
|
||||
|
||||
first_reference first() { return _first; }
|
||||
first_const_reference first() const { return _first; }
|
||||
|
||||
second_reference second() { return _second; }
|
||||
second_const_reference second() const { return _second; }
|
||||
|
||||
void swap(compressed_pair& y)
|
||||
{
|
||||
using std::swap;
|
||||
swap(_first, y._first);
|
||||
swap(_second, y._second);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
|
||||
|
||||
|
@ -1,73 +0,0 @@
|
||||
// (C) Copyright Jens Maurer 2001. Permission to copy, use,
|
||||
// modify, sell and distribute this software is granted provided this
|
||||
// copyright notice appears in all copies. This software is provided
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
//
|
||||
// Revision History:
|
||||
|
||||
// 15 Nov 2001 Jens Maurer
|
||||
// created.
|
||||
|
||||
#ifndef BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
||||
#define BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
||||
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<class Generator>
|
||||
class generator_iterator_policies
|
||||
{
|
||||
public:
|
||||
generator_iterator_policies() { }
|
||||
|
||||
template<class Base>
|
||||
void initialize(Base& base) {
|
||||
m_value = (*base)();
|
||||
}
|
||||
|
||||
// The Iter template argument is necessary for compatibility with a MWCW
|
||||
// bug workaround
|
||||
template <class IteratorAdaptor>
|
||||
void increment(IteratorAdaptor& iter) {
|
||||
m_value = (*iter.base())();
|
||||
}
|
||||
|
||||
template <class IteratorAdaptor>
|
||||
const typename Generator::result_type&
|
||||
dereference(const IteratorAdaptor&) const
|
||||
{ return m_value; }
|
||||
|
||||
template <class IteratorAdaptor1, class IteratorAdaptor2>
|
||||
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
|
||||
{ return x.base() == y.base() &&
|
||||
x.policies().m_value == y.policies().m_value; }
|
||||
|
||||
private:
|
||||
typename Generator::result_type m_value;
|
||||
};
|
||||
|
||||
template<class Generator>
|
||||
struct generator_iterator_generator
|
||||
{
|
||||
typedef iterator_adaptor<Generator*, generator_iterator_policies<Generator>,
|
||||
typename Generator::result_type, const typename Generator::result_type&,
|
||||
const typename Generator::result_type*, std::input_iterator_tag,
|
||||
long> type;
|
||||
};
|
||||
|
||||
template <class Generator>
|
||||
inline typename generator_iterator_generator<Generator>::type
|
||||
make_generator_iterator(Generator & gen)
|
||||
{
|
||||
typedef typename generator_iterator_generator<Generator>::type result_t;
|
||||
return result_t(&gen);
|
||||
}
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP
|
||||
|
@ -1,937 +0,0 @@
|
||||
// Boost operators.hpp header file ----------------------------------------//
|
||||
|
||||
// (C) Copyright David Abrahams, Jeremy Siek, and Daryle Walker 1999-2001.
|
||||
// Permission to copy, use, modify, sell and distribute this software is
|
||||
// granted provided this copyright notice appears in all copies. This
|
||||
// software is provided "as is" without express or implied warranty, and
|
||||
// with no claim as to its suitability for any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 02 Dec 01 Bug fixed in random_access_iteratable. (Helmut Zeisel)
|
||||
// 28 Sep 01 Factored out iterator operator groups. (Daryle Walker)
|
||||
// 27 Aug 01 'left' form for non commutative operators added;
|
||||
// additional classes for groups of related operators added;
|
||||
// workaround for empty base class optimization
|
||||
// bug of GCC 3.0 (Helmut Zeisel)
|
||||
// 25 Jun 01 output_iterator_helper changes: removed default template
|
||||
// parameters, added support for self-proxying, additional
|
||||
// documentation and tests (Aleksey Gurtovoy)
|
||||
// 29 May 01 Added operator classes for << and >>. Added input and output
|
||||
// iterator helper classes. Added classes to connect equality and
|
||||
// relational operators. Added classes for groups of related
|
||||
// operators. Reimplemented example operator and iterator helper
|
||||
// classes in terms of the new groups. (Daryle Walker, with help
|
||||
// from Alexy Gurtovoy)
|
||||
// 11 Feb 01 Fixed bugs in the iterator helpers which prevented explicitly
|
||||
// supplied arguments from actually being used (Dave Abrahams)
|
||||
// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and
|
||||
// refactoring of compiler workarounds, additional documentation
|
||||
// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from
|
||||
// Dave Abrahams)
|
||||
// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and
|
||||
// Jeremy Siek (Dave Abrahams)
|
||||
// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5
|
||||
// (Mark Rodgers)
|
||||
// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy)
|
||||
// 10 Jun 00 Support for the base class chaining technique was added
|
||||
// (Aleksey Gurtovoy). See documentation and the comments below
|
||||
// for the details.
|
||||
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
|
||||
// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary
|
||||
// specializations of dividable, subtractable, modable (Ed Brey)
|
||||
// 17 Nov 99 Add comments (Beman Dawes)
|
||||
// Remove unnecessary specialization of operators<> (Ed Brey)
|
||||
// 15 Nov 99 Fix less_than_comparable<T,U> second operand type for first two
|
||||
// operators.(Beman Dawes)
|
||||
// 12 Nov 99 Add operators templates (Ed Brey)
|
||||
// 11 Nov 99 Add single template parameter version for compilers without
|
||||
// partial specialization (Beman Dawes)
|
||||
// 10 Nov 99 Initial version
|
||||
|
||||
// 10 Jun 00:
|
||||
// An additional optional template parameter was added to most of
|
||||
// operator templates to support the base class chaining technique (see
|
||||
// documentation for the details). Unfortunately, a straightforward
|
||||
// implementation of this change would have broken compatibility with the
|
||||
// previous version of the library by making it impossible to use the same
|
||||
// template name (e.g. 'addable') for both the 1- and 2-argument versions of
|
||||
// an operator template. This implementation solves the backward-compatibility
|
||||
// issue at the cost of some simplicity.
|
||||
//
|
||||
// One of the complications is an existence of special auxiliary class template
|
||||
// 'is_chained_base<>' (see 'detail' namespace below), which is used
|
||||
// to determine whether its template parameter is a library's operator template
|
||||
// or not. You have to specialize 'is_chained_base<>' for each new
|
||||
// operator template you add to the library.
|
||||
//
|
||||
// However, most of the non-trivial implementation details are hidden behind
|
||||
// several local macros defined below, and as soon as you understand them,
|
||||
// you understand the whole library implementation.
|
||||
|
||||
#ifndef BOOST_OPERATORS_HPP
|
||||
#define BOOST_OPERATORS_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/iterator.hpp>
|
||||
|
||||
#if defined(__sgi) && !defined(__GNUC__)
|
||||
#pragma set woff 1234
|
||||
#endif
|
||||
|
||||
#if defined(BOOST_MSVC)
|
||||
# pragma warning( disable : 4284 ) // complaint about return type of
|
||||
#endif // operator-> not begin a UDT
|
||||
|
||||
namespace boost {
|
||||
namespace detail {
|
||||
|
||||
// Helmut Zeisel, empty base class optimization bug with GCC 3.0.0
|
||||
#if defined(__GNUC__) && __GNUC__==3 && __GNUC_MINOR__==0 && __GNU_PATCHLEVEL__==0
|
||||
class empty_base {
|
||||
bool dummy;
|
||||
};
|
||||
#else
|
||||
class empty_base {};
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
} // namespace boost
|
||||
|
||||
// In this section we supply the xxxx1 and xxxx2 forms of the operator
|
||||
// templates, which are explicitly targeted at the 1-type-argument and
|
||||
// 2-type-argument operator forms, respectively. Some compilers get confused
|
||||
// when inline friend functions are overloaded in namespaces other than the
|
||||
// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of
|
||||
// these templates must go in the global namespace.
|
||||
|
||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
namespace boost
|
||||
{
|
||||
#endif
|
||||
|
||||
// Basic operator classes (contributed by Dave Abrahams) ------------------//
|
||||
|
||||
// Note that friend functions defined in a class are implicitly inline.
|
||||
// See the C++ std, 11.4 [class.friend] paragraph 5
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct less_than_comparable2 : B
|
||||
{
|
||||
friend bool operator<=(const T& x, const U& y) { return !(x > y); }
|
||||
friend bool operator>=(const T& x, const U& y) { return !(x < y); }
|
||||
friend bool operator>(const U& x, const T& y) { return y < x; }
|
||||
friend bool operator<(const U& x, const T& y) { return y > x; }
|
||||
friend bool operator<=(const U& x, const T& y) { return !(y < x); }
|
||||
friend bool operator>=(const U& x, const T& y) { return !(y > x); }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct less_than_comparable1 : B
|
||||
{
|
||||
friend bool operator>(const T& x, const T& y) { return y < x; }
|
||||
friend bool operator<=(const T& x, const T& y) { return !(y < x); }
|
||||
friend bool operator>=(const T& x, const T& y) { return !(x < y); }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct equality_comparable2 : B
|
||||
{
|
||||
friend bool operator==(const U& y, const T& x) { return x == y; }
|
||||
friend bool operator!=(const U& y, const T& x) { return !(x == y); }
|
||||
friend bool operator!=(const T& y, const U& x) { return !(y == x); }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct equality_comparable1 : B
|
||||
{
|
||||
friend bool operator!=(const T& x, const T& y) { return !(x == y); }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct multipliable2 : B
|
||||
{
|
||||
friend T operator*(T x, const U& y) { return x *= y; }
|
||||
friend T operator*(const U& y, T x) { return x *= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct multipliable1 : B
|
||||
{
|
||||
friend T operator*(T x, const T& y) { return x *= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct addable2 : B
|
||||
{
|
||||
friend T operator+(T x, const U& y) { return x += y; }
|
||||
friend T operator+(const U& y, T x) { return x += y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct addable1 : B
|
||||
{
|
||||
friend T operator+(T x, const T& y) { return x += y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct subtractable2 : B
|
||||
{
|
||||
friend T operator-(T x, const U& y) { return x -= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct subtractable2_left : B
|
||||
{
|
||||
friend T operator-(const U& x, const T& y)
|
||||
{ T result(x); return result -= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct subtractable1 : B
|
||||
{
|
||||
friend T operator-(T x, const T& y) { return x -= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct dividable2 : B
|
||||
{
|
||||
friend T operator/(T x, const U& y) { return x /= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct dividable2_left : B
|
||||
{
|
||||
friend T operator/(const U& x, const T& y)
|
||||
{ T result(x); return result /= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct dividable1 : B
|
||||
{
|
||||
friend T operator/(T x, const T& y) { return x /= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct modable2 : B
|
||||
{
|
||||
friend T operator%(T x, const U& y) { return x %= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct modable2_left : B
|
||||
{
|
||||
friend T operator%(const U& x, const T& y)
|
||||
{ T result(x); return result %= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct modable1 : B
|
||||
{
|
||||
friend T operator%(T x, const T& y) { return x %= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct xorable2 : B
|
||||
{
|
||||
friend T operator^(T x, const U& y) { return x ^= y; }
|
||||
friend T operator^(const U& y, T x) { return x ^= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct xorable1 : B
|
||||
{
|
||||
friend T operator^(T x, const T& y) { return x ^= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct andable2 : B
|
||||
{
|
||||
friend T operator&(T x, const U& y) { return x &= y; }
|
||||
friend T operator&(const U& y, T x) { return x &= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct andable1 : B
|
||||
{
|
||||
friend T operator&(T x, const T& y) { return x &= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct orable2 : B
|
||||
{
|
||||
friend T operator|(T x, const U& y) { return x |= y; }
|
||||
friend T operator|(const U& y, T x) { return x |= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct orable1 : B
|
||||
{
|
||||
friend T operator|(T x, const T& y) { return x |= y; }
|
||||
};
|
||||
|
||||
// incrementable and decrementable contributed by Jeremy Siek
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct incrementable : B
|
||||
{
|
||||
friend T operator++(T& x, int)
|
||||
{
|
||||
incrementable_type tmp(x);
|
||||
++x;
|
||||
return tmp;
|
||||
}
|
||||
private: // The use of this typedef works around a Borland bug
|
||||
typedef T incrementable_type;
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct decrementable : B
|
||||
{
|
||||
friend T operator--(T& x, int)
|
||||
{
|
||||
decrementable_type tmp(x);
|
||||
--x;
|
||||
return tmp;
|
||||
}
|
||||
private: // The use of this typedef works around a Borland bug
|
||||
typedef T decrementable_type;
|
||||
};
|
||||
|
||||
// Iterator operator classes (contributed by Jeremy Siek) ------------------//
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||
struct dereferenceable : B
|
||||
{
|
||||
P operator->() const
|
||||
{
|
||||
return &*static_cast<const T&>(*this);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class I, class R, class B = ::boost::detail::empty_base>
|
||||
struct indexable : B
|
||||
{
|
||||
R operator[](I n) const
|
||||
{
|
||||
return *(static_cast<const T&>(*this) + n);
|
||||
}
|
||||
};
|
||||
|
||||
// More operator classes (contributed by Daryle Walker) --------------------//
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct left_shiftable2 : B
|
||||
{
|
||||
friend T operator<<(T x, const U& y) { return x <<= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct left_shiftable1 : B
|
||||
{
|
||||
friend T operator<<(T x, const T& y) { return x <<= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct right_shiftable2 : B
|
||||
{
|
||||
friend T operator>>(T x, const U& y) { return x >>= y; }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct right_shiftable1 : B
|
||||
{
|
||||
friend T operator>>(T x, const T& y) { return x >>= y; }
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct equivalent2 : B
|
||||
{
|
||||
friend bool operator==(const T& x, const U& y)
|
||||
{
|
||||
return !(x < y) && !(x > y);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct equivalent1 : B
|
||||
{
|
||||
friend bool operator==(const T&x, const T&y)
|
||||
{
|
||||
return !(x < y) && !(y < x);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct partially_ordered2 : B
|
||||
{
|
||||
friend bool operator<=(const T& x, const U& y)
|
||||
{ return (x < y) || (x == y); }
|
||||
friend bool operator>=(const T& x, const U& y)
|
||||
{ return (x > y) || (x == y); }
|
||||
friend bool operator>(const U& x, const T& y)
|
||||
{ return y < x; }
|
||||
friend bool operator<(const U& x, const T& y)
|
||||
{ return y > x; }
|
||||
friend bool operator<=(const U& x, const T& y)
|
||||
{ return (y > x) || (y == x); }
|
||||
friend bool operator>=(const U& x, const T& y)
|
||||
{ return (y < x) || (y == x); }
|
||||
};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct partially_ordered1 : B
|
||||
{
|
||||
friend bool operator>(const T& x, const T& y)
|
||||
{ return y < x; }
|
||||
friend bool operator<=(const T& x, const T& y)
|
||||
{ return (x < y) || (x == y); }
|
||||
friend bool operator>=(const T& x, const T& y)
|
||||
{ return (y < x) || (x == y); }
|
||||
};
|
||||
|
||||
// Combined operator classes (contributed by Daryle Walker) ----------------//
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct totally_ordered2
|
||||
: less_than_comparable2<T, U
|
||||
, equality_comparable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct totally_ordered1
|
||||
: less_than_comparable1<T
|
||||
, equality_comparable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct additive2
|
||||
: addable2<T, U
|
||||
, subtractable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct additive1
|
||||
: addable1<T
|
||||
, subtractable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct multiplicative2
|
||||
: multipliable2<T, U
|
||||
, dividable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct multiplicative1
|
||||
: multipliable1<T
|
||||
, dividable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct integer_multiplicative2
|
||||
: multiplicative2<T, U
|
||||
, modable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct integer_multiplicative1
|
||||
: multiplicative1<T
|
||||
, modable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct arithmetic2
|
||||
: additive2<T, U
|
||||
, multiplicative2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct arithmetic1
|
||||
: additive1<T
|
||||
, multiplicative1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct integer_arithmetic2
|
||||
: additive2<T, U
|
||||
, integer_multiplicative2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct integer_arithmetic1
|
||||
: additive1<T
|
||||
, integer_multiplicative1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct bitwise2
|
||||
: xorable2<T, U
|
||||
, andable2<T, U
|
||||
, orable2<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct bitwise1
|
||||
: xorable1<T
|
||||
, andable1<T
|
||||
, orable1<T, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct unit_steppable
|
||||
: incrementable<T
|
||||
, decrementable<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct shiftable2
|
||||
: left_shiftable2<T, U
|
||||
, right_shiftable2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct shiftable1
|
||||
: left_shiftable1<T
|
||||
, right_shiftable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct ring_operators2
|
||||
: additive2<T, U
|
||||
, subtractable2_left<T, U
|
||||
, multipliable2<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct ring_operators1
|
||||
: additive1<T
|
||||
, multipliable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct ordered_ring_operators2
|
||||
: ring_operators2<T, U
|
||||
, totally_ordered2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct ordered_ring_operators1
|
||||
: ring_operators1<T
|
||||
, totally_ordered1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct field_operators2
|
||||
: ring_operators2<T, U
|
||||
, dividable2<T, U
|
||||
, dividable2_left<T, U, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct field_operators1
|
||||
: ring_operators1<T
|
||||
, dividable1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct ordered_field_operators2
|
||||
: field_operators2<T, U
|
||||
, totally_ordered2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct ordered_field_operators1
|
||||
: field_operators1<T
|
||||
, totally_ordered1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct euclidian_ring_operators2
|
||||
: ring_operators2<T, U
|
||||
, dividable2<T, U
|
||||
, dividable2_left<T, U
|
||||
, modable2<T, U
|
||||
, modable2_left<T, U, B
|
||||
> > > > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct euclidian_ring_operators1
|
||||
: ring_operators1<T
|
||||
, dividable1<T
|
||||
, modable1<T, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class U, class B = ::boost::detail::empty_base>
|
||||
struct ordered_euclidian_ring_operators2
|
||||
: totally_ordered2<T, U
|
||||
, euclidian_ring_operators2<T, U, B
|
||||
> > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct ordered_euclidian_ring_operators1
|
||||
: totally_ordered1<T
|
||||
, euclidian_ring_operators1<T, B
|
||||
> > {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||
struct input_iteratable
|
||||
: equality_comparable1<T
|
||||
, incrementable<T
|
||||
, dereferenceable<T, P, B
|
||||
> > > {};
|
||||
|
||||
template <class T, class B = ::boost::detail::empty_base>
|
||||
struct output_iteratable
|
||||
: incrementable<T, B
|
||||
> {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||
struct forward_iteratable
|
||||
: input_iteratable<T, P, B
|
||||
> {};
|
||||
|
||||
template <class T, class P, class B = ::boost::detail::empty_base>
|
||||
struct bidirectional_iteratable
|
||||
: forward_iteratable<T, P
|
||||
, decrementable<T, B
|
||||
> > {};
|
||||
|
||||
// To avoid repeated derivation from equality_comparable,
|
||||
// which is an indirect base class of bidirectional_iterable,
|
||||
// random_access_iteratable must not be derived from totally_ordered1
|
||||
// but from less_than_comparable1 only. (Helmut Zeisel, 02-Dec-2001)
|
||||
template <class T, class P, class D, class R, class B = ::boost::detail::empty_base>
|
||||
struct random_access_iteratable
|
||||
: bidirectional_iteratable<T, P
|
||||
, less_than_comparable1<T
|
||||
, additive2<T, D
|
||||
, indexable<T, D, R, B
|
||||
> > > > {};
|
||||
|
||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
} // namespace boost
|
||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
|
||||
// BOOST_IMPORT_TEMPLATE1 .. BOOST_IMPORT_TEMPLATE4 -
|
||||
//
|
||||
// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an
|
||||
// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used
|
||||
// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for
|
||||
// two-argument forms. Note that these macros expect to be invoked from within
|
||||
// boost.
|
||||
|
||||
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
// The template is already in boost so we have nothing to do.
|
||||
# define BOOST_IMPORT_TEMPLATE4(template_name)
|
||||
# define BOOST_IMPORT_TEMPLATE3(template_name)
|
||||
# define BOOST_IMPORT_TEMPLATE2(template_name)
|
||||
# define BOOST_IMPORT_TEMPLATE1(template_name)
|
||||
|
||||
#else // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
# ifndef BOOST_NO_USING_TEMPLATE
|
||||
|
||||
// Bring the names in with a using-declaration
|
||||
// to avoid stressing the compiler.
|
||||
# define BOOST_IMPORT_TEMPLATE4(template_name) using ::template_name;
|
||||
# define BOOST_IMPORT_TEMPLATE3(template_name) using ::template_name;
|
||||
# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name;
|
||||
# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name;
|
||||
|
||||
# else
|
||||
|
||||
// Otherwise, because a Borland C++ 5.5 bug prevents a using declaration
|
||||
// from working, we are forced to use inheritance for that compiler.
|
||||
# define BOOST_IMPORT_TEMPLATE4(template_name) \
|
||||
template <class T, class U, class V, class W, class B = ::boost::detail::empty_base> \
|
||||
struct template_name : ::template_name<T, U, V, W, B> {};
|
||||
|
||||
# define BOOST_IMPORT_TEMPLATE3(template_name) \
|
||||
template <class T, class U, class V, class B = ::boost::detail::empty_base> \
|
||||
struct template_name : ::template_name<T, U, V, B> {};
|
||||
|
||||
# define BOOST_IMPORT_TEMPLATE2(template_name) \
|
||||
template <class T, class U, class B = ::boost::detail::empty_base> \
|
||||
struct template_name : ::template_name<T, U, B> {};
|
||||
|
||||
# define BOOST_IMPORT_TEMPLATE1(template_name) \
|
||||
template <class T, class B = ::boost::detail::empty_base> \
|
||||
struct template_name : ::template_name<T, B> {};
|
||||
|
||||
# endif // BOOST_NO_USING_TEMPLATE
|
||||
|
||||
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE
|
||||
|
||||
//
|
||||
// Here's where we put it all together, defining the xxxx forms of the templates
|
||||
// in namespace boost. We also define specializations of is_chained_base<> for
|
||||
// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as
|
||||
// neccessary.
|
||||
//
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
// is_chained_base<> - a traits class used to distinguish whether an operator
|
||||
// template argument is being used for base class chaining, or is specifying a
|
||||
// 2nd argument type.
|
||||
|
||||
namespace boost {
|
||||
// A type parameter is used instead of a plain bool because Borland's compiler
|
||||
// didn't cope well with the more obvious non-type template parameter.
|
||||
namespace detail {
|
||||
struct true_t {};
|
||||
struct false_t {};
|
||||
} // namespace detail
|
||||
|
||||
// Unspecialized version assumes that most types are not being used for base
|
||||
// class chaining. We specialize for the operator templates defined in this
|
||||
// library.
|
||||
template<class T> struct is_chained_base {
|
||||
typedef ::boost::detail::false_t value;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
// Import a 4-type-argument operator template into boost (if neccessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
|
||||
BOOST_IMPORT_TEMPLATE4(template_name4) \
|
||||
template<class T, class U, class V, class W, class B> \
|
||||
struct is_chained_base< ::boost::template_name4<T, U, V, W, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// Import a 3-type-argument operator template into boost (if neccessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
|
||||
BOOST_IMPORT_TEMPLATE3(template_name3) \
|
||||
template<class T, class U, class V, class B> \
|
||||
struct is_chained_base< ::boost::template_name3<T, U, V, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// Import a 2-type-argument operator template into boost (if neccessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||
BOOST_IMPORT_TEMPLATE2(template_name2) \
|
||||
template<class T, class U, class B> \
|
||||
struct is_chained_base< ::boost::template_name2<T, U, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// Import a 1-type-argument operator template into boost (if neccessary) and
|
||||
// provide a specialization of 'is_chained_base<>' for it.
|
||||
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
||||
BOOST_IMPORT_TEMPLATE1(template_name1) \
|
||||
template<class T, class B> \
|
||||
struct is_chained_base< ::boost::template_name1<T, B> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
};
|
||||
|
||||
// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it
|
||||
// can be used for specifying both 1-argument and 2-argument forms. Requires the
|
||||
// existence of two previously defined class templates named '<template_name>1'
|
||||
// and '<template_name>2' which must implement the corresponding 1- and 2-
|
||||
// argument forms.
|
||||
//
|
||||
// The template type parameter O == is_chained_base<U>::value is used to
|
||||
// distinguish whether the 2nd argument to <template_name> is being used for
|
||||
// base class chaining from another boost operator template or is describing a
|
||||
// 2nd operand type. O == true_t only when U is actually an another operator
|
||||
// template from the library. Partial specialization is used to select an
|
||||
// implementation in terms of either '<template_name>1' or '<template_name>2'.
|
||||
//
|
||||
|
||||
# define BOOST_OPERATOR_TEMPLATE(template_name) \
|
||||
template <class T \
|
||||
,class U = T \
|
||||
,class B = ::boost::detail::empty_base \
|
||||
,class O = typename is_chained_base<U>::value \
|
||||
> \
|
||||
struct template_name : template_name##2<T, U, B> {}; \
|
||||
\
|
||||
template<class T, class U, class B> \
|
||||
struct template_name<T, U, B, ::boost::detail::true_t> \
|
||||
: template_name##1<T, U> {}; \
|
||||
\
|
||||
template <class T, class B> \
|
||||
struct template_name<T, T, B, ::boost::detail::false_t> \
|
||||
: template_name##1<T, B> {}; \
|
||||
\
|
||||
template<class T, class U, class B, class O> \
|
||||
struct is_chained_base< ::boost::template_name<T, U, B, O> > { \
|
||||
typedef ::boost::detail::true_t value; \
|
||||
}; \
|
||||
\
|
||||
BOOST_OPERATOR_TEMPLATE2(template_name##2) \
|
||||
BOOST_OPERATOR_TEMPLATE1(template_name##1)
|
||||
|
||||
|
||||
#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
# define BOOST_OPERATOR_TEMPLATE4(template_name4) \
|
||||
BOOST_IMPORT_TEMPLATE4(template_name4)
|
||||
# define BOOST_OPERATOR_TEMPLATE3(template_name3) \
|
||||
BOOST_IMPORT_TEMPLATE3(template_name3)
|
||||
# define BOOST_OPERATOR_TEMPLATE2(template_name2) \
|
||||
BOOST_IMPORT_TEMPLATE2(template_name2)
|
||||
# define BOOST_OPERATOR_TEMPLATE1(template_name1) \
|
||||
BOOST_IMPORT_TEMPLATE1(template_name1)
|
||||
|
||||
// In this case we can only assume that template_name<> is equivalent to the
|
||||
// more commonly needed template_name1<> form.
|
||||
# define BOOST_OPERATOR_TEMPLATE(template_name) \
|
||||
template <class T, class B = ::boost::detail::empty_base> \
|
||||
struct template_name : template_name##1<T, B> {};
|
||||
|
||||
#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
namespace boost {
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE(less_than_comparable)
|
||||
BOOST_OPERATOR_TEMPLATE(equality_comparable)
|
||||
BOOST_OPERATOR_TEMPLATE(multipliable)
|
||||
BOOST_OPERATOR_TEMPLATE(addable)
|
||||
BOOST_OPERATOR_TEMPLATE(subtractable)
|
||||
BOOST_OPERATOR_TEMPLATE2(subtractable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(dividable)
|
||||
BOOST_OPERATOR_TEMPLATE2(dividable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(modable)
|
||||
BOOST_OPERATOR_TEMPLATE2(modable2_left)
|
||||
BOOST_OPERATOR_TEMPLATE(xorable)
|
||||
BOOST_OPERATOR_TEMPLATE(andable)
|
||||
BOOST_OPERATOR_TEMPLATE(orable)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE1(incrementable)
|
||||
BOOST_OPERATOR_TEMPLATE1(decrementable)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE2(dereferenceable)
|
||||
BOOST_OPERATOR_TEMPLATE3(indexable)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE(left_shiftable)
|
||||
BOOST_OPERATOR_TEMPLATE(right_shiftable)
|
||||
BOOST_OPERATOR_TEMPLATE(equivalent)
|
||||
BOOST_OPERATOR_TEMPLATE(partially_ordered)
|
||||
|
||||
BOOST_OPERATOR_TEMPLATE(totally_ordered)
|
||||
BOOST_OPERATOR_TEMPLATE(additive)
|
||||
BOOST_OPERATOR_TEMPLATE(multiplicative)
|
||||
BOOST_OPERATOR_TEMPLATE(integer_multiplicative)
|
||||
BOOST_OPERATOR_TEMPLATE(arithmetic)
|
||||
BOOST_OPERATOR_TEMPLATE(integer_arithmetic)
|
||||
BOOST_OPERATOR_TEMPLATE(bitwise)
|
||||
BOOST_OPERATOR_TEMPLATE1(unit_steppable)
|
||||
BOOST_OPERATOR_TEMPLATE(shiftable)
|
||||
BOOST_OPERATOR_TEMPLATE(ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(field_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_field_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(euclidian_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE(ordered_euclidian_ring_operators)
|
||||
BOOST_OPERATOR_TEMPLATE2(input_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE1(output_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE2(forward_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE2(bidirectional_iteratable)
|
||||
BOOST_OPERATOR_TEMPLATE4(random_access_iteratable)
|
||||
|
||||
#undef BOOST_OPERATOR_TEMPLATE
|
||||
#undef BOOST_OPERATOR_TEMPLATE4
|
||||
#undef BOOST_OPERATOR_TEMPLATE3
|
||||
#undef BOOST_OPERATOR_TEMPLATE2
|
||||
#undef BOOST_OPERATOR_TEMPLATE1
|
||||
#undef BOOST_IMPORT_TEMPLATE1
|
||||
#undef BOOST_IMPORT_TEMPLATE2
|
||||
#undef BOOST_IMPORT_TEMPLATE3
|
||||
#undef BOOST_IMPORT_TEMPLATE4
|
||||
|
||||
// The following 'operators' classes can only be used portably if the derived class
|
||||
// declares ALL of the required member operators.
|
||||
template <class T, class U>
|
||||
struct operators2
|
||||
: totally_ordered2<T,U
|
||||
, integer_arithmetic2<T,U
|
||||
, bitwise2<T,U
|
||||
> > > {};
|
||||
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template <class T, class U = T>
|
||||
struct operators : operators2<T, U> {};
|
||||
|
||||
template <class T> struct operators<T, T>
|
||||
#else
|
||||
template <class T> struct operators
|
||||
#endif
|
||||
: totally_ordered<T
|
||||
, integer_arithmetic<T
|
||||
, bitwise<T
|
||||
, unit_steppable<T
|
||||
> > > > {};
|
||||
|
||||
// Iterator helper classes (contributed by Jeremy Siek) -------------------//
|
||||
// (Input and output iterator helpers contributed by Daryle Walker) -------//
|
||||
// (Changed to use combined operator classes by Daryle Walker) ------------//
|
||||
template <class T,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V const *,
|
||||
class R = V const &>
|
||||
struct input_iterator_helper
|
||||
: input_iteratable<T, P
|
||||
, boost::iterator<std::input_iterator_tag, V, D, P, R
|
||||
> > {};
|
||||
|
||||
template<class T>
|
||||
struct output_iterator_helper
|
||||
: output_iteratable<T
|
||||
, boost::iterator<std::output_iterator_tag, void, void, void, void
|
||||
> >
|
||||
{
|
||||
T& operator*() { return static_cast<T&>(*this); }
|
||||
T& operator++() { return static_cast<T&>(*this); }
|
||||
};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct forward_iterator_helper
|
||||
: forward_iteratable<T, P
|
||||
, boost::iterator<std::forward_iterator_tag, V, D, P, R
|
||||
> > {};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct bidirectional_iterator_helper
|
||||
: bidirectional_iteratable<T, P
|
||||
, boost::iterator<std::bidirectional_iterator_tag, V, D, P, R
|
||||
> > {};
|
||||
|
||||
template <class T,
|
||||
class V,
|
||||
class D = std::ptrdiff_t,
|
||||
class P = V*,
|
||||
class R = V&>
|
||||
struct random_access_iterator_helper
|
||||
: random_access_iteratable<T, P, D, R
|
||||
, boost::iterator<std::random_access_iterator_tag, V, D, P, R
|
||||
> >
|
||||
{
|
||||
friend D requires_difference_operator(const T& x, const T& y) {
|
||||
return x - y;
|
||||
}
|
||||
}; // random_access_iterator_helper
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#if defined(__sgi) && !defined(__GNUC__)
|
||||
#pragma reset woff 1234
|
||||
#endif
|
||||
|
||||
#endif // BOOST_OPERATORS_HPP
|
@ -1,162 +0,0 @@
|
||||
#ifndef BOOST_REF_HPP_INCLUDED
|
||||
# define BOOST_REF_HPP_INCLUDED
|
||||
|
||||
# if _MSC_VER+0 >= 1020
|
||||
# pragma once
|
||||
# endif
|
||||
|
||||
# include <boost/config.hpp>
|
||||
# include <boost/utility/addressof.hpp>
|
||||
|
||||
//
|
||||
// ref.hpp - ref/cref, useful helper functions
|
||||
//
|
||||
// Copyright (C) 1999, 2000 Jaakko J<>rvi (jaakko.jarvi@cs.utu.fi)
|
||||
// Copyright (C) 2001, 2002 Peter Dimov
|
||||
// Copyright (C) 2002 David Abrahams
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
// See http://www.boost.org/libs/bind/ref.html for documentation.
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
template<class T> class reference_wrapper
|
||||
{
|
||||
public:
|
||||
typedef T type;
|
||||
|
||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
|
||||
|
||||
explicit reference_wrapper(T& t): t_(&t) {}
|
||||
|
||||
#else
|
||||
|
||||
explicit reference_wrapper(T& t): t_(addressof(t)) {}
|
||||
|
||||
#endif
|
||||
|
||||
operator T& () const { return *t_; }
|
||||
|
||||
T& get() const { return *t_; }
|
||||
|
||||
T* get_pointer() const { return t_; }
|
||||
|
||||
private:
|
||||
|
||||
T* t_;
|
||||
};
|
||||
|
||||
# if defined(__BORLANDC__) && (__BORLANDC__ <= 0x560)
|
||||
# define BOOST_REF_CONST
|
||||
# else
|
||||
# define BOOST_REF_CONST const
|
||||
# endif
|
||||
|
||||
template<class T> inline reference_wrapper<T> BOOST_REF_CONST ref(T & t)
|
||||
{
|
||||
return reference_wrapper<T>(t);
|
||||
}
|
||||
|
||||
template<class T> inline reference_wrapper<T const> BOOST_REF_CONST cref(T const & t)
|
||||
{
|
||||
return reference_wrapper<T const>(t);
|
||||
}
|
||||
|
||||
# undef BOOST_REF_CONST
|
||||
|
||||
# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
template<typename T>
|
||||
class is_reference_wrapper
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = false);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class is_reference_wrapper<reference_wrapper<T> >
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(bool, value = true);
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class unwrap_reference
|
||||
{
|
||||
public:
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class unwrap_reference<reference_wrapper<T> >
|
||||
{
|
||||
public:
|
||||
typedef T type;
|
||||
};
|
||||
# else // no partial specialization
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#include <boost/type.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
typedef char (&yes_reference_wrapper_t)[1];
|
||||
typedef char (&no_reference_wrapper_t)[2];
|
||||
|
||||
no_reference_wrapper_t is_reference_wrapper_test(...);
|
||||
|
||||
template<typename T>
|
||||
yes_reference_wrapper_t is_reference_wrapper_test(type< reference_wrapper<T> >);
|
||||
|
||||
template<bool wrapped>
|
||||
struct reference_unwrapper
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct reference_unwrapper<true>
|
||||
{
|
||||
template <class T>
|
||||
struct apply
|
||||
{
|
||||
typedef typename T::type type;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class is_reference_wrapper
|
||||
{
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(
|
||||
bool, value = (
|
||||
sizeof(detail::is_reference_wrapper_test(type<T>()))
|
||||
== sizeof(detail::yes_reference_wrapper_t)));
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class unwrap_reference
|
||||
: public detail::reference_unwrapper<
|
||||
is_reference_wrapper<T>::value
|
||||
>::template apply<T>
|
||||
{};
|
||||
|
||||
# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_REF_HPP_INCLUDED
|
@ -1,63 +0,0 @@
|
||||
// boost utility.hpp header file -------------------------------------------//
|
||||
|
||||
// (C) Copyright boost.org 1999. Permission to copy, use, modify, sell
|
||||
// and distribute this software is granted provided this copyright
|
||||
// notice appears in all copies. This software is provided "as is" without
|
||||
// express or implied warranty, and with no claim as to its suitability for
|
||||
// any purpose.
|
||||
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Classes appear in alphabetical order
|
||||
|
||||
#ifndef BOOST_UTILITY_HPP
|
||||
#define BOOST_UTILITY_HPP
|
||||
|
||||
// certain headers are part of the <utility.hpp> interface
|
||||
|
||||
#include <boost/checked_delete.hpp>
|
||||
#include <boost/utility/base_from_member.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
// next() and prior() template functions -----------------------------------//
|
||||
|
||||
// Helper functions for classes like bidirectional iterators not supporting
|
||||
// operator+ and operator-.
|
||||
//
|
||||
// Usage:
|
||||
// const std::list<T>::iterator p = get_some_iterator();
|
||||
// const std::list<T>::iterator prev = boost::prior(p);
|
||||
|
||||
// Contributed by Dave Abrahams
|
||||
|
||||
template <class T>
|
||||
inline T next(T x) { return ++x; }
|
||||
|
||||
template <class T>
|
||||
inline T prior(T x) { return --x; }
|
||||
|
||||
|
||||
// class noncopyable -------------------------------------------------------//
|
||||
|
||||
// Private copy constructor and copy assignment ensure classes derived from
|
||||
// class noncopyable cannot be copied.
|
||||
|
||||
// Contributed by Dave Abrahams
|
||||
|
||||
class noncopyable
|
||||
{
|
||||
protected:
|
||||
noncopyable(){}
|
||||
~noncopyable(){}
|
||||
private: // emphasize the following members are private
|
||||
noncopyable( const noncopyable& );
|
||||
const noncopyable& operator=( const noncopyable& );
|
||||
}; // noncopyable
|
||||
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_UTILITY_HPP
|
||||
|
@ -1,31 +0,0 @@
|
||||
// Copyright (C) 2002 Brad King (brad.king@kitware.com)
|
||||
// Doug Gregor (gregod@cs.rpi.edu)
|
||||
// Peter Dimov
|
||||
//
|
||||
// Permission to copy, use, sell and distribute this software is granted
|
||||
// provided this copyright notice appears in all copies.
|
||||
// Permission to modify the code and to distribute modified code is granted
|
||||
// provided this copyright notice appears in all copies, and a notice
|
||||
// that the code was modified is included with the copyright notice.
|
||||
//
|
||||
// This software is provided "as is" without express or implied warranty,
|
||||
// and with no claim as to its suitability for any purpose.
|
||||
|
||||
// For more information, see http://www.boost.org
|
||||
|
||||
#ifndef BOOST_UTILITY_ADDRESSOF_HPP
|
||||
#define BOOST_UTILITY_ADDRESSOF_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
// Do not make addressof() inline. Breaks MSVC 7. (Peter Dimov)
|
||||
|
||||
template <typename T> T* addressof(T& v)
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_UTILITY_ADDRESSOF_HPP
|
@ -1,59 +0,0 @@
|
||||
// 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
|
@ -1,34 +0,0 @@
|
||||
// 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;
|
||||
|
||||
// Also has a few function templates
|
||||
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_UTILITY_FWD_HPP
|
34
index.html
34
index.html
@ -1,34 +0,0 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta http-equiv="Content-Language" content="en-us">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<title>Boost Utility Library</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF">
|
||||
|
||||
<h1><IMG SRC="../../c++boost.gif" WIDTH="276" HEIGHT="86" align="center">Boost
|
||||
Utility Library</h1>
|
||||
<p>The Boost Utility Library isn't really a single library at all. It is
|
||||
just a collection for components too small to be called libraries in their own
|
||||
right.</p>
|
||||
<p>But that doesn't mean there isn't useful stuff here. Take a look:</p>
|
||||
<blockquote>
|
||||
<p><a href="base_from_member.html">base_from_member</a><br>
|
||||
<a href="call_traits.htm">call_traits.htm</a><br>
|
||||
<a href="compressed_pair.htm">compressed_pair.htm</a><br>
|
||||
<a href="operators.htm">operators.htm</a><br>
|
||||
<a href="tie.html">tie</a><br>
|
||||
<a href="utility.htm">utility.htm</a></p>
|
||||
</blockquote>
|
||||
<hr>
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->07 May, 2002<!--webbot bot="Timestamp" endspan i-checksum="13976" --></p>
|
||||
<p> </p>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
@ -203,10 +203,10 @@ explicit indirect_iterator_generator::type(const BaseIterator& it)
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class BaseIterator,
|
||||
class Value, class Reference, class ConstReference,
|
||||
class Category, class Pointer, class ConstPointer>
|
||||
struct indirect_iterator_pair_generator;
|
||||
template <class BaseIterator,
|
||||
class Value, class Pointer, class Reference,
|
||||
class ConstPointer, class ConstReference>
|
||||
class indirect_iterator_pair_generator
|
||||
{
|
||||
public:
|
||||
typedef <tt><a href=
|
||||
@ -292,6 +292,13 @@ 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>
|
||||
|
||||
@ -300,19 +307,6 @@ 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>
|
||||
|
||||
@ -320,6 +314,11 @@ 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>
|
||||
@ -423,7 +422,7 @@ a,b,c,d,e,f,g,
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->18 Sep 2001<!--webbot bot="Timestamp" endspan i-checksum="14941" -->
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" -->
|
||||
|
||||
|
||||
<p>© Copyright Jeremy Siek and David Abrahams 2001. Permission to
|
||||
|
@ -33,8 +33,8 @@ int main(int, char*[])
|
||||
|
||||
char mutable_characters[N];
|
||||
char* pointers_to_mutable_chars[N];
|
||||
for (int j = 0; j < N; ++j)
|
||||
pointers_to_mutable_chars[j] = &mutable_characters[j];
|
||||
for (int i = 0; i < N; ++i)
|
||||
pointers_to_mutable_chars[i] = &mutable_characters[i];
|
||||
|
||||
PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars),
|
||||
mutable_indirect_last(pointers_to_mutable_chars + N);
|
||||
@ -42,21 +42,19 @@ int main(int, char*[])
|
||||
const_indirect_last(pointers_to_chars + N);
|
||||
|
||||
std::transform(const_indirect_first, const_indirect_last,
|
||||
mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
|
||||
mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
|
||||
|
||||
std::copy(mutable_indirect_first, mutable_indirect_last,
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
|
||||
// Example of using make_indirect_iterator()
|
||||
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
std::copy(boost::make_indirect_iterator(pointers_to_chars),
|
||||
boost::make_indirect_iterator(pointers_to_chars + N),
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
boost::make_indirect_iterator(pointers_to_chars + N),
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ typedef std::set<storage::iterator> iterator_set;
|
||||
void more_indirect_iterator_tests()
|
||||
{
|
||||
// For some reason all heck breaks loose in the compiler under these conditions.
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 || !defined(__STL_DEBUG)
|
||||
#if !defined(BOOST_MSVC) || !defined(__STL_DEBUG)
|
||||
storage store(1000);
|
||||
std::generate(store.begin(), store.end(), rand);
|
||||
|
||||
@ -46,7 +46,7 @@ void more_indirect_iterator_tests()
|
||||
|
||||
typedef boost::indirect_iterator_pair_generator<
|
||||
pointer_deque::iterator
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, int
|
||||
#endif
|
||||
> IndirectDeque;
|
||||
@ -75,7 +75,7 @@ void more_indirect_iterator_tests()
|
||||
|
||||
typedef boost::indirect_iterator_generator<
|
||||
iterator_set::iterator
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, int
|
||||
#endif
|
||||
>::type indirect_set_iterator;
|
||||
@ -117,7 +117,7 @@ main()
|
||||
ptr[k] = array + k;
|
||||
|
||||
typedef boost::indirect_iterator_generator<dummyT**
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, dummyT
|
||||
#endif
|
||||
>::type indirect_iterator;
|
||||
@ -127,7 +127,7 @@ main()
|
||||
indirect_iterator i(ptr);
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
|
||||
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array);
|
||||
#endif
|
||||
|
||||
@ -139,7 +139,7 @@ main()
|
||||
|
||||
dummyT*const* const_ptr = ptr;
|
||||
|
||||
#ifndef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array);
|
||||
#endif
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
|
@ -4,9 +4,7 @@
|
||||
// "as is" without express or implied warranty, and with no claim as
|
||||
// to its suitability for any purpose.
|
||||
|
||||
// 04 Nov 2001 Jeremy Siek
|
||||
// Updated with respect to new named parameter interface.
|
||||
// 08 Mar 2001 Jeremy Siek
|
||||
// 8 Mar 2001 Jeremy Siek
|
||||
// Initial checkin.
|
||||
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
@ -21,15 +19,16 @@ main()
|
||||
{
|
||||
using boost::dummyT;
|
||||
dummyT array[] = { dummyT(0), dummyT(1), dummyT(2),
|
||||
dummyT(3), dummyT(4), dummyT(5) };
|
||||
dummyT(3), dummyT(4), dummyT(5) };
|
||||
typedef boost::iterator_adaptor<dummyT*,
|
||||
boost::default_iterator_policies, dummyT> my_iter;
|
||||
my_iter mi(array);
|
||||
|
||||
{
|
||||
typedef boost::iterator_adaptor<my_iter, boost::default_iterator_policies,
|
||||
boost::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));
|
||||
@ -43,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);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/pending/iterator_adaptors.hpp>
|
||||
#include <boost/pending/integer_range.hpp>
|
||||
|
||||
int
|
||||
@ -21,7 +21,8 @@ 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*
|
||||
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)),
|
||||
|
@ -9,10 +9,6 @@
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 30 Nov 01 Added permutation_iterator.(Toon Knapen)
|
||||
// 19 Nov 01 Added generator_iterator. (Jens Maurer)
|
||||
// 04 Nov 01 Updated with respect to change in named parameters.
|
||||
// (Jeremy Siek)
|
||||
// 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
|
||||
@ -51,20 +47,15 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
#include <boost/generator_iterator.hpp>
|
||||
#include <boost/pending/iterator_tests.hpp>
|
||||
#include <boost/pending/integer_range.hpp>
|
||||
#include <boost/concept_archetype.hpp>
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
#include <boost/permutation_iterator.hpp>
|
||||
#include <stdlib.h>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <set>
|
||||
#include <list>
|
||||
|
||||
struct my_iterator_tag : public std::random_access_iterator_tag { };
|
||||
|
||||
@ -106,18 +97,6 @@ typedef std::deque<int> storage;
|
||||
typedef std::deque<int*> pointer_deque;
|
||||
typedef std::set<storage::iterator> iterator_set;
|
||||
|
||||
template <class T> struct foo;
|
||||
|
||||
void blah(int) { }
|
||||
|
||||
struct my_gen
|
||||
{
|
||||
typedef int result_type;
|
||||
my_gen() : n(0) { }
|
||||
int operator()() { return ++n; }
|
||||
int n;
|
||||
};
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
@ -126,61 +105,17 @@ main()
|
||||
const int N = sizeof(array)/sizeof(dummyT);
|
||||
|
||||
// sanity check, if this doesn't pass the test is buggy
|
||||
boost::random_access_iterator_test(array, N, array);
|
||||
boost::random_access_iterator_test(array,N,array);
|
||||
|
||||
// Check that the policy concept checks and the default policy
|
||||
// implementation match up.
|
||||
boost::function_requires<
|
||||
boost::RandomAccessIteratorPoliciesConcept<
|
||||
boost::default_iterator_policies,
|
||||
boost::iterator_adaptor<storage::iterator, boost::default_iterator_policies>,
|
||||
boost::default_iterator_policies, int*,
|
||||
boost::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t,
|
||||
int*, int&>
|
||||
> >();
|
||||
|
||||
// Test the named parameters
|
||||
{
|
||||
// Test computation of defaults
|
||||
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
|
||||
boost::value_type_is<int> > Iter1;
|
||||
// don't use std::iterator_traits here to avoid VC++ problems
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, int>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, int&>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, int*>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::difference_type, std::ptrdiff_t>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::iterator_category, std::random_access_iterator_tag>::value));
|
||||
}
|
||||
{
|
||||
// Test computation of default when the Value is const
|
||||
typedef boost::iterator_adaptor<std::list<int>::iterator,
|
||||
boost::default_iterator_policies,
|
||||
boost::value_type_is<const int> > Iter1;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, int>::value));
|
||||
#if defined(__BORLANDC__) || defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
// We currently don't know how to workaround this bug.
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, int&>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, int*>::value));
|
||||
#else
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, const int&>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, const int*>::value));
|
||||
#endif
|
||||
}
|
||||
{
|
||||
// Test with no defaults
|
||||
typedef boost::iterator_adaptor<int*, boost::default_iterator_policies,
|
||||
boost::reference_is<long>,
|
||||
boost::pointer_is<float*>,
|
||||
boost::value_type_is<char>,
|
||||
boost::iterator_category_is<std::input_iterator_tag>,
|
||||
boost::difference_type_is<int>
|
||||
> Iter1;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::value_type, char>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::reference, long>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::pointer, float*>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::difference_type, int>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Iter1::iterator_category, std::input_iterator_tag>::value));
|
||||
}
|
||||
|
||||
// Test the iterator_adaptor
|
||||
{
|
||||
boost::iterator_adaptor<dummyT*, boost::default_iterator_policies, dummyT> i(array);
|
||||
@ -224,7 +159,7 @@ main()
|
||||
std::reverse(reversed, reversed + N);
|
||||
|
||||
typedef boost::reverse_iterator_generator<dummyT*
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, dummyT
|
||||
#endif
|
||||
>::type reverse_iterator;
|
||||
@ -232,13 +167,13 @@ main()
|
||||
reverse_iterator i(reversed + N);
|
||||
boost::random_access_iterator_test(i, N, array);
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array);
|
||||
#endif
|
||||
|
||||
typedef boost::reverse_iterator_generator<const dummyT*
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
, dummyT, const dummyT&, const dummyT
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, const dummyT
|
||||
#endif
|
||||
>::type const_reverse_iterator;
|
||||
|
||||
@ -247,7 +182,7 @@ main()
|
||||
|
||||
const dummyT* const_reversed = reversed;
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array);
|
||||
#endif
|
||||
|
||||
@ -282,7 +217,7 @@ main()
|
||||
|
||||
// Many compilers' builtin deque iterators don't interoperate well, though
|
||||
// STLport fixes that problem.
|
||||
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && (!defined(BOOST_MSVC) || BOOST_MSVC > 1200)
|
||||
#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && !defined(BOOST_MSVC)
|
||||
boost::const_nonconst_iterator_test(i, ++j);
|
||||
#endif
|
||||
}
|
||||
@ -300,7 +235,7 @@ main()
|
||||
typedef boost::detail::non_bidirectional_category<dummyT*>::type category;
|
||||
|
||||
typedef boost::filter_iterator_generator<one_or_four, dummyT*
|
||||
#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) || defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
, dummyT
|
||||
#endif
|
||||
>::type filter_iter;
|
||||
@ -309,8 +244,8 @@ main()
|
||||
// Borland is choking on accessing the policies_type explicitly
|
||||
// from the filter_iter.
|
||||
boost::forward_iterator_test(make_filter_iterator(array, array+N,
|
||||
one_or_four()),
|
||||
dummyT(1), dummyT(4));
|
||||
one_or_four()),
|
||||
dummyT(1), dummyT(4));
|
||||
#else
|
||||
filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N));
|
||||
boost::forward_iterator_test(i, dummyT(1), dummyT(4));
|
||||
@ -327,7 +262,7 @@ main()
|
||||
// On compilers not supporting partial specialization, we can do more type
|
||||
// deduction with deque iterators than with pointers... unless the library
|
||||
// is broken ;-(
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 || defined(__SGI_STL_PORT)
|
||||
#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT)
|
||||
std::deque<dummyT> array2;
|
||||
std::copy(array+0, array+N, std::back_inserter(array2));
|
||||
boost::forward_iterator_test(
|
||||
@ -339,7 +274,7 @@ main()
|
||||
dummyT(1), dummyT(4));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1200 // This just freaks MSVC out completely
|
||||
#if !defined(BOOST_MSVC) // This just freaks MSVC out completely
|
||||
boost::forward_iterator_test(
|
||||
boost::make_filter_iterator<one_or_four>(
|
||||
boost::make_reverse_iterator(array2.end()),
|
||||
@ -348,7 +283,7 @@ main()
|
||||
dummyT(4), dummyT(1));
|
||||
#endif
|
||||
|
||||
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(BOOST_NO_STD_ITERATOR_TRAITS)
|
||||
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
|
||||
boost::forward_iterator_test(
|
||||
boost::make_filter_iterator(array+0, array+N, one_or_four()),
|
||||
dummyT(1), dummyT(4));
|
||||
@ -371,12 +306,12 @@ main()
|
||||
#else
|
||||
typedef boost::iterator_adaptor<boost::forward_iterator_archetype<dummyT>,
|
||||
boost::default_iterator_policies,
|
||||
boost::reference_is<const dummyT&>,
|
||||
boost::pointer_is<const dummyT*> ,
|
||||
boost::iterator_category_is<std::forward_iterator_tag>,
|
||||
boost::value_type_is<dummyT>,
|
||||
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;
|
||||
@ -395,55 +330,6 @@ main()
|
||||
if (zero) // don't do this, just make sure it compiles
|
||||
assert((*i).m_x == i->foo());
|
||||
}
|
||||
|
||||
{
|
||||
// check generator_iterator
|
||||
my_gen g1;
|
||||
boost::generator_iterator_generator<my_gen>::type gen =
|
||||
boost::make_generator_iterator(g1);
|
||||
assert(*gen == 1);
|
||||
++gen;
|
||||
gen++;
|
||||
assert(*gen == 3);
|
||||
}
|
||||
|
||||
{
|
||||
// check permutation_iterator
|
||||
typedef std::deque< int > element_range_type;
|
||||
typedef std::list< int > index_type;
|
||||
|
||||
static const int element_range_size = 10;
|
||||
static const int index_size = 4;
|
||||
|
||||
element_range_type elements( element_range_size );
|
||||
|
||||
for(element_range_type::iterator el_it = elements.begin();
|
||||
el_it != elements.end();
|
||||
++el_it)
|
||||
{
|
||||
*el_it = std::distance( elements.begin(), el_it );
|
||||
}
|
||||
|
||||
index_type indices( index_size );
|
||||
|
||||
for(index_type::iterator i_it = indices.begin();
|
||||
i_it != indices.end();
|
||||
++i_it)
|
||||
{
|
||||
*i_it = element_range_size - index_size
|
||||
+ std::distance(indices.begin(), i_it );
|
||||
}
|
||||
|
||||
std::reverse( indices.begin(), indices.end() );
|
||||
|
||||
typedef boost::permutation_iterator_generator< element_range_type::iterator, index_type::iterator >::type permutation_type;
|
||||
permutation_type begin = boost::make_permutation_iterator( elements.begin(), indices.begin() );
|
||||
permutation_type end = boost::make_permutation_iterator( elements.begin(), indices.end() );
|
||||
|
||||
int expected_outcome[] = { 9, 8, 7, 6 };
|
||||
assert( std::equal( begin, end, expected_outcome ) );
|
||||
}
|
||||
|
||||
std::cout << "test successful " << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
@ -26,37 +26,6 @@
|
||||
"../../more/generic_programming.html#adaptors">adaptors</a> which apply
|
||||
specific useful behaviors to arbitrary base iterators.
|
||||
|
||||
<h2>Backward Compatibility Note</h2>
|
||||
|
||||
<p>The library's interface has changed since it was first released, breaking
|
||||
backward compatibility:
|
||||
|
||||
<ol>
|
||||
|
||||
<li><a href="#policies">Policies classes</a> now operate on instances of the
|
||||
whole <tt>iterator_adaptor</tt> object, rather than just operating on the
|
||||
<tt>Base</tt> object. This change not only gives the policies class access
|
||||
to both members of a pair of interacting iterators, but also eliminates the
|
||||
need for the ugly <tt>type<Reference></tt> and
|
||||
<tt>type<Difference></tt> parameters to various policy functions.
|
||||
|
||||
<li>The <a href="#named_template_parameters">Named Template Parameter</a>
|
||||
interface has been made simpler, easier to use, and compatible with more
|
||||
compilers.
|
||||
|
||||
</ol>
|
||||
|
||||
<h2>Other Documentation</h2>
|
||||
|
||||
<p><a href="iterator_adaptors.pdf">``Policy Adaptors and the Boost Iterator
|
||||
Adaptor Library''</a> is a technical paper describing this library and the
|
||||
powerful design pattern on which it is based. It was presented at the <a
|
||||
href="http://www.oonumerics.org/tmpw01">C++ Template Workshop</a> at OOPSLA
|
||||
2001; the slides from the talk are available <a
|
||||
href="iterator_adaptors.ppt">here</a>. Please note that while the slides
|
||||
incorporate the minor interface changes described in the previous section,
|
||||
the paper does not.
|
||||
|
||||
<h2>Table of Contents</h2>
|
||||
|
||||
<ul>
|
||||
@ -92,8 +61,6 @@
|
||||
|
||||
<li><a href="#declaration_synopsis">Declaration Synopsis</a>
|
||||
|
||||
<li><a href="#portability">Portability</a>
|
||||
|
||||
<li><a href="#notes">Notes</a>
|
||||
</ul>
|
||||
|
||||
@ -124,13 +91,9 @@
|
||||
"../../boost/function_output_iterator.hpp">boost/function_output_iterator.hpp</a></tt><br>
|
||||
|
||||
<a href="function_output_iterator.htm">Function Output Iterator Adaptor</a>
|
||||
<li>Header <tt><a href="../../boost/generator_iterator.hpp">boost/generator_iterator.hpp</a></tt><br>
|
||||
<a href="generator_iterator.htm">Generator Iterator Adaptor</a>
|
||||
<li>Header <tt><a href="../../boost/permutation_iterator.hpp">boost/permutation_iterator.hpp</a></tt><br>
|
||||
<a href="permutation_iterator.htm">Permutation Iterator Adaptor</a>
|
||||
</ul>
|
||||
|
||||
<p><b><a href="../../people/dave_abrahams.htm">Dave
|
||||
<p><b><a href="http://www.boost.org/people/dave_abrahams.htm">Dave
|
||||
Abrahams</a></b> started the library, applying <a href=
|
||||
"../../more/generic_programming.html#policy">policy class</a> technique and
|
||||
handling const/non-const iterator interactions. He also contributed the
|
||||
@ -139,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="../../people/jeremy_siek.htm">Jeremy
|
||||
<b><a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy
|
||||
Siek</a></b> contributed the <a href="transform_iterator.htm">transform
|
||||
iterator</a> adaptor, the integer-only version of <tt><a href=
|
||||
"counting_iterator.htm">counting_iterator_generator</a></tt>,
|
||||
@ -151,11 +114,7 @@
|
||||
"filter_iterator.htm">filter_</a></tt> iterator generators and made some
|
||||
simplifications to the main <tt><a href=
|
||||
"#iterator_adaptor">iterator_adaptor</a></tt> template.<br>
|
||||
<b><a href="../../people/jens_maurer.htm">Jens Maurer</a></b>
|
||||
contributed the <a href="generator_iterator.htm">generator iterator</a>
|
||||
adaptor.<br>
|
||||
Toon Knapen contributed the <a href="permutation_iterator.htm">permutation
|
||||
iterator</a> adaptor.<br>
|
||||
|
||||
|
||||
<h2><a name="iterator_adaptor">Class template</a>
|
||||
<tt>iterator_adaptor</tt></h2>
|
||||
@ -172,11 +131,11 @@
|
||||
<p><tt>iterator_adaptor</tt> is declared like this:
|
||||
<pre>
|
||||
template <class Base, class Policies,
|
||||
class ValueOrNamedParam = typename std::iterator_traits<Base>::value_type,
|
||||
class ReferenceOrNamedParam = <i>...(see below)</i>,
|
||||
class PointerOrNamedParam = <i>...(see below)</i>,
|
||||
class CategoryOrNamedParam = typename std::iterator_traits<Base>::iterator_category,
|
||||
class DistanceOrNamedParam = typename std::iterator_traits<Base>::difference_type>
|
||||
class ValueOrNamedParams = typename std::iterator_traits<Base>::value_type,
|
||||
class ReferenceOrNamedParams = <i>...(see below)</i>,
|
||||
class PointerOrNamedParams = <i>...(see below)</i>,
|
||||
class CategoryOrNamedParams = typename std::iterator_traits<Base>::iterator_category,
|
||||
class DistanceOrNamedParams = typename std::iterator_traits<Base>::difference_type>
|
||||
struct iterator_adaptor;
|
||||
</pre>
|
||||
|
||||
@ -184,7 +143,7 @@ struct iterator_adaptor;
|
||||
|
||||
<p>Although <tt>iterator_adaptor</tt> takes seven template parameters,
|
||||
defaults have been carefully chosen to minimize the number of parameters
|
||||
you must supply in most cases, especially if <tt>Base</tt> is an
|
||||
you must supply in most cases, especially if <tt>BaseType</tt> is an
|
||||
iterator.
|
||||
|
||||
<table border="1" summary="iterator_adaptor template parameters">
|
||||
@ -193,26 +152,17 @@ struct iterator_adaptor;
|
||||
|
||||
<th>Description
|
||||
|
||||
<th>Requirements
|
||||
|
||||
<tr>
|
||||
<td><tt>Base</tt>
|
||||
<td><tt>BaseType</tt>
|
||||
|
||||
<td>The data type on which the resulting iterator is based. Do
|
||||
not be misled by the name "Base": this is not a base
|
||||
class.
|
||||
|
||||
<td>
|
||||
<a href="http://www.sgi.com/tech/stl/Assignable.html">Assignable</a>,
|
||||
<a href="http://www.sgi.com/tech/stl/DefaultConstructible.html">Default Constructible</a>
|
||||
<td>The type being wrapped.
|
||||
|
||||
<tr>
|
||||
<td><tt>Policies</tt>
|
||||
|
||||
<td>A <a href="../../more/generic_programming.html#policy">policy
|
||||
class</a> that supplies core functionality to the resulting iterator.
|
||||
|
||||
<td>See table <a href="#policies">below</a>.
|
||||
class</a> that supplies core functionality to the resulting iterator. A
|
||||
detailed description can be found <a href="#policies">below</a>.
|
||||
|
||||
<tr>
|
||||
<td><tt>Value</tt>
|
||||
@ -223,7 +173,7 @@ struct iterator_adaptor;
|
||||
"#1">[1]</a>. If the <tt>value_type</tt> you wish to use is an abstract
|
||||
base class see note <a href="#5">[5]</a>.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<Base>::value_type</tt> <a href=
|
||||
<tt>std::iterator_traits<BaseType>::value_type</tt> <a href=
|
||||
"#2">[2]</a>
|
||||
|
||||
<tr>
|
||||
@ -233,57 +183,36 @@ struct iterator_adaptor;
|
||||
particular, the result type of <tt>operator*()</tt>.<br>
|
||||
<b>Default:</b> If <tt>Value</tt> is supplied, <tt>Value&</tt> is
|
||||
used. Otherwise
|
||||
<tt>std::iterator_traits<Base>::reference</tt> is used. <a href="#7">[7]</a>
|
||||
|
||||
<td><a
|
||||
href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterators</a>,
|
||||
<a
|
||||
href="http://www.sgi.com/tech/stl/BidirectionalIterator.html">BidirectionalIterators</a>,
|
||||
and <a
|
||||
href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterators</a>
|
||||
require that Reference is a true reference type (e.g. not a proxy).
|
||||
<tt>std::iterator_traits<BaseType>::reference</tt> is used.
|
||||
|
||||
<tr>
|
||||
<td><tt>Pointer</tt>
|
||||
|
||||
<td>The <tt>pointer</tt> type of the resulting iterator, and in
|
||||
particular, the result type of <tt>operator->()</tt>.<br>
|
||||
<b>Default:</b> If <tt>Value</tt> was not supplied, <tt>std::iterator_traits<Base>::pointer</tt>. <a
|
||||
href="#7">[7]</a> Otherwise, if <code>iterator_category</code> is
|
||||
<code>input_iterator</code>, then a class yielding
|
||||
<tt>Value*</tt> when <code>operator->()</code> is applied.
|
||||
Otherwise, <tt>Value*</tt>.
|
||||
|
||||
<td><code>value_type*</code> or a
|
||||
class which yields <code>value_type*</code> when
|
||||
<code>operator->()</code> is applied.
|
||||
<b>Default:</b> If <tt>Value</tt> was supplied, then <tt>Value*</tt>,
|
||||
otherwise <tt>std::iterator_traits<BaseType>::pointer</tt>.
|
||||
|
||||
<tr>
|
||||
<td><tt>Category</tt>
|
||||
|
||||
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<Base>::iterator_category</tt>
|
||||
|
||||
<td>One of
|
||||
<code>std::input_iterator_tag</code>,
|
||||
<code>std::output_iterator_tag</code>,
|
||||
<code>std::forward_iterator_tag</code>,
|
||||
<code>std::bidirectional_iterator_tag</code>, or
|
||||
<code>std::random_access_iterator_tag</code>.
|
||||
<tt>std::iterator_traits<BaseType>::iterator_category</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>Distance</tt>
|
||||
|
||||
<td>The <tt>difference_type</tt> for the resulting iterator.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<Base>::difference_type</tt>
|
||||
<td>A signed integral type
|
||||
<tt>std::iterator_traits<BaseType>::difference_type</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>NamedParam</tt>
|
||||
<td><tt>NamedParams</tt>
|
||||
|
||||
<td>A named template parameter (see below).
|
||||
<td>A list of named template parameters generated using the
|
||||
<a href="#iterator_traits_generator">
|
||||
<tt>iterator_traits_generator</tt></a> class (see below).
|
||||
</table>
|
||||
|
||||
<h3><a name="named_template_parameters">Named Template Parameters</a></h3>
|
||||
@ -294,32 +223,59 @@ struct iterator_adaptor;
|
||||
template parameter, but use the defaults for the third through
|
||||
fifth. As a solution to these problems we provide a mechanism for
|
||||
naming the last five template parameters, and providing them in
|
||||
any order through a set of named template parameters. The following
|
||||
classes are provided for specifying the parameters. Any of these
|
||||
classes can be used for any of the last five template parameters
|
||||
of <tt>iterator_adaptor</tt>.
|
||||
any order through the <tt>iterator_traits_generator</tt> class.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class Value> struct value_type_is;
|
||||
template <class Reference> struct reference_is;
|
||||
template <class Pointer> struct pointer_is;
|
||||
template <class Distance> struct difference_type_is;
|
||||
template <class Category> struct iterator_category_is;
|
||||
<a name="iterator_traits_generator">class iterator_traits_generator</a>
|
||||
{
|
||||
public:
|
||||
template <class Value>
|
||||
struct value_type : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Reference>
|
||||
struct reference : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Pointer>
|
||||
struct pointer : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Distance>
|
||||
struct difference_type : public <i>recursive magic</i> { };
|
||||
|
||||
template <class Category>
|
||||
struct iterator_category : public <i>recursive magic</i> { };
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
For example, the following adapts <tt>foo_iterator</tt> to create
|
||||
an <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a>
|
||||
with <tt>reference</tt> type <tt>foo</tt>, and whose other traits
|
||||
are determined according to the defaults described <a
|
||||
href="#template_parameters">above</a>.
|
||||
The <tt>iterator_traits_generator</tt> is used to create a list of
|
||||
of template arguments. For example, suppose you want to set the
|
||||
<tt>Reference</tt> and <tt>Category</tt> parameters, and use the
|
||||
defaults for the rest. Then you can use the traits generator as
|
||||
follows:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
typedef iterator_adaptor<foo_iterator, foo_policies,
|
||||
reference_is<foo>, iterator_category_is<std::input_iterator_tag>
|
||||
> MyIterator;
|
||||
iterator_traits_generator::reference<foo>::category<std::input_iterator_tag>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
This generated type can then be passed into the <tt>iterator_adaptor</tt>
|
||||
class to replace any of the last five parameters. If you use the traits
|
||||
generator in the <i>i</i>th parameter position, then the parameters <i>i</i>
|
||||
through 7 will use the types specified in the generator. For example, the
|
||||
following adapts <tt>foo_iterator</tt> to create an <a href=
|
||||
"http://www.sgi.com/tech/stl/InputIterator.html">InputIterator</a> with
|
||||
<tt>reference</tt> type <tt>foo</tt>, and whose other traits are determined
|
||||
according to the defaults described <a href="#template_parameters">above</a>.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
iterator_adaptor<foo_iterator, foo_policies,
|
||||
iterator_traits_generator
|
||||
::reference<foo>
|
||||
::iterator_category<std::input_iterator_tag>
|
||||
>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
@ -341,16 +297,12 @@ typedef iterator_adaptor<foo_iterator, foo_policies,
|
||||
|
||||
<table border="1" summary="iterator_adaptor Policies operations">
|
||||
<caption>
|
||||
<b>Policies Class Requirements</b><br>
|
||||
<tt><b>T</b></tt>: adapted iterator type; <tt><b>x, y</b></tt>: objects of type
|
||||
T; <tt><b>p</b></tt>: <tt>T::policies_type</tt>
|
||||
<tt><b>d</b></tt>:
|
||||
<tt>T::difference_type</tt>; <tt><b>i1</b></tt>, <tt><b>i2</b></tt>:
|
||||
<tt>T::base_type</tt>
|
||||
<b>Core Iterator Operations</b><br>
|
||||
<tt>T</tt>: adapted iterator type; <tt>p</tt>: object of type T; <tt>n</tt>: <tt>T::size_type</tt>; <tt>x</tt>: <tt>T::difference_type</tt>; <tt>p1</tt>, <tt>p2</tt>: iterators
|
||||
</caption>
|
||||
|
||||
<tr>
|
||||
<th>Expression
|
||||
<th>Operation
|
||||
|
||||
<th>Effects
|
||||
|
||||
@ -359,7 +311,7 @@ typedef iterator_adaptor<foo_iterator, foo_policies,
|
||||
<th>Required for Iterator Categories
|
||||
|
||||
<tr>
|
||||
<td nowrap><tt>p.initialize(b)</tt>
|
||||
<td><tt>initialize</tt>
|
||||
|
||||
<td>optionally modify base iterator during iterator construction
|
||||
|
||||
@ -371,66 +323,79 @@ typedef iterator_adaptor<foo_iterator, foo_policies,
|
||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward</a>/ <a
|
||||
href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access</a>
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access</a>
|
||||
|
||||
|
||||
<tr>
|
||||
<td nowrap><tt>p.dereference(x)</tt>
|
||||
<td><tt>dereference</tt>
|
||||
|
||||
<td>returns an element of the iterator's <tt>reference</tt> type
|
||||
|
||||
<td><tt>*x</tt>, <tt>x[d]</tt>
|
||||
<td><tt>*p</tt>, <tt>p[n]</tt>
|
||||
|
||||
|
||||
<tr>
|
||||
<td nowrap><tt>p.equal(x, y)</tt>
|
||||
<td><tt>equal</tt>
|
||||
|
||||
<td>tests the iterator for equality
|
||||
|
||||
<td><tt>i1 == i2</tt>, <tt>i1 != i2</tt>
|
||||
<td><tt>p1 == p2</tt>, <tt>p1 != p2</tt>
|
||||
|
||||
<tr>
|
||||
<td nowrap><tt>p.increment(x)</tt>
|
||||
<td><tt>increment</tt>
|
||||
|
||||
<td>increments the iterator
|
||||
|
||||
<td><tt>++x</tt>, <tt>x++</tt>
|
||||
<td><tt>++p</tt>, <tt>p++</tt>
|
||||
|
||||
<tr>
|
||||
<td nowrap><tt>p.decrement(x)</tt>
|
||||
<td><tt>decrement</tt>
|
||||
|
||||
<td>decrements the iterator
|
||||
|
||||
<td><tt>--x</tt>, <tt>x--</tt>
|
||||
<td><tt>--p</tt>, <tt>p--</tt>
|
||||
|
||||
<td><a href=
|
||||
"http://www.sgi.com/tech/stl/BidirectionalIterator.html">Bidirectional</a>/
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access</a>
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access</a>
|
||||
|
||||
<tr>
|
||||
<td nowrap><tt>p.distance(x, y)</tt>
|
||||
<td><tt>less</tt>
|
||||
|
||||
<td>imposes a <a href=
|
||||
"http://www.sgi.com/tech/stl/StrictWeakOrdering.html">Strict Weak
|
||||
Ordering</a> relation on iterators
|
||||
|
||||
<td>
|
||||
<tt>p1 < p2</tt>,
|
||||
<tt>p1 <= p2</tt>,
|
||||
<tt>p1 > p2</tt>,
|
||||
<tt>p1 >= p2</tt>
|
||||
|
||||
<td rowspan="3"><a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>distance</tt>
|
||||
|
||||
<td>measures the distance between iterators
|
||||
|
||||
<td><tt>y - x</tt>, <tt>x < y</tt>
|
||||
|
||||
<td rowspan="2"><a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access</a>
|
||||
<td><tt>p1 - p2</tt>
|
||||
|
||||
<tr>
|
||||
<td nowrap><tt>p.advance(x, n)</tt>
|
||||
<td><tt>advance</tt>
|
||||
|
||||
<td>adds an integer offset to iterators
|
||||
|
||||
<td>
|
||||
<tt>x + d</tt>,
|
||||
<tt>d + x</tt>,
|
||||
|
||||
<br>
|
||||
<tt>x += d</tt>,
|
||||
<tt>x - d</tt>,<br>
|
||||
<tt>x -= d</tt>
|
||||
<tt>p + x</tt>,
|
||||
<tt>x + p</tt>,
|
||||
<tt>p += x</tt>,
|
||||
<tt>p - x</tt>,
|
||||
<tt>p -= x</tt>
|
||||
|
||||
</table>
|
||||
|
||||
@ -449,40 +414,40 @@ typedef iterator_adaptor<foo_iterator, foo_policies,
|
||||
<pre>
|
||||
struct <a name="default_iterator_policies">default_iterator_policies</a>
|
||||
{
|
||||
// Some of these members were defined static, but Borland got confused
|
||||
// and thought they were non-const. Also, Sun C++ does not like static
|
||||
// function templates.
|
||||
template <class BaseType>
|
||||
void initialize(BaseType&)
|
||||
{ }
|
||||
|
||||
template <class Base>
|
||||
void initialize(Base&)
|
||||
{ }
|
||||
template <class Reference, class BaseType>
|
||||
Reference dereference(type<Reference>, const BaseType& x) const
|
||||
{ return *x; }
|
||||
|
||||
template <class IteratorAdaptor>
|
||||
typename IteratorAdaptor::reference dereference(const IteratorAdaptor& x) const
|
||||
{ return *x.base(); }
|
||||
template <class BaseType>
|
||||
static void increment(BaseType& x)
|
||||
{ ++x; }
|
||||
|
||||
template <class IteratorAdaptor>
|
||||
void increment(IteratorAdaptor& x)
|
||||
{ ++x.base(); }
|
||||
template <class BaseType1, class BaseType2>
|
||||
bool equal(BaseType1& x, BaseType2& y) const
|
||||
{ return x == y; }
|
||||
|
||||
template <class IteratorAdaptor>
|
||||
void decrement(IteratorAdaptor& x)
|
||||
{ --x.base(); }
|
||||
template <class BaseType>
|
||||
static void decrement(BaseType& x)
|
||||
{ --x; }
|
||||
|
||||
template <class IteratorAdaptor, class DifferenceType>
|
||||
void advance(IteratorAdaptor& x, DifferenceType n)
|
||||
{ x.base() += n; }
|
||||
template <class BaseType, class DifferenceType>
|
||||
static void advance(BaseType& x, DifferenceType n)
|
||||
{ x += n; }
|
||||
|
||||
template <class IteratorAdaptor1, class IteratorAdaptor2>
|
||||
typename IteratorAdaptor1::difference_type
|
||||
distance(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
|
||||
{ return y.base() - x.base(); }
|
||||
template <class Difference, class BaseType1, class BaseType2>
|
||||
Difference distance(type<Difference>, BaseType1& x, BaseType2& y) const
|
||||
{ return y - x; }
|
||||
|
||||
template <class IteratorAdaptor1, class IteratorAdaptor2>
|
||||
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
|
||||
{ return x.base() == y.base(); }
|
||||
template <class BaseType1, class BaseType2>
|
||||
bool less(BaseType1& x, BaseType2& y) const
|
||||
{ return x < y; }
|
||||
};
|
||||
</pre></blockquote>
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>Template member functions are used throughout
|
||||
<tt>default_iterator_policies</tt> so that it can be employed with a wide
|
||||
@ -515,30 +480,15 @@ struct <a name="default_iterator_policies">default_iterator_policies</a>
|
||||
iterator_adaptor(const
|
||||
iterator_adaptor<B,Policies,V,R,P,Category,Distance>&)</tt>
|
||||
<br><br>
|
||||
This constructor allows for conversion from mutable to
|
||||
This constructor allows for conversion from non-<tt>const</tt> to
|
||||
constant adapted iterators. See <a href=
|
||||
"#iterator_interactions">below</a> for more details.<br>
|
||||
Requires: <tt>B</tt> is convertible to <tt>Base</tt>.
|
||||
|
||||
<tr>
|
||||
<td><tt>const base_type& base() const;</tt>
|
||||
<br><br>
|
||||
Return a const reference to the base object.
|
||||
|
||||
<tr> <td><tt>base_type& base();</tt>
|
||||
<td><tt>base_type base() const;</tt>
|
||||
<br><br>
|
||||
Return a reference to the base object. This is to give the policies object
|
||||
access to the base object. See <a href="#policies">above</a> for policies
|
||||
iterator_adaptor interaction.<a href="#8">[8]</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>const Policies& policies() const;</tt>
|
||||
<br><br>
|
||||
Return a const reference to the policies object.
|
||||
|
||||
<tr> <td><tt>Policies& policies();</tt>
|
||||
<br><br>
|
||||
Return a reference to the policies object.
|
||||
Return a copy of the base object.
|
||||
</table>
|
||||
|
||||
<h3><a name="example">Example</a></h3>
|
||||
@ -556,37 +506,40 @@ struct <a name="default_iterator_policies">default_iterator_policies</a>
|
||||
argument and that we'll need to be able to deduce the <tt>result_type</tt>
|
||||
of the function so we can use it for the adapted iterator's
|
||||
<tt>value_type</tt>. <a href=
|
||||
"http://www.sgi.com/tech/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>
|
||||
"http://www.sgi.com/Technology/STL/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>
|
||||
is the <a href="../../more/generic_programming.html#concept">Concept</a>
|
||||
that fulfills those requirements.
|
||||
|
||||
<p>To implement a transform iterator we will only change one of the base
|
||||
iterator's behaviors, so the <tt>transform_iterator_policies</tt> class can
|
||||
inherit the rest from <tt>default_iterator_policies</tt>. We will define the
|
||||
<tt>dereference()</tt> member function, which is used to implement
|
||||
inherit the rest from <tt>default_iterator_policies</tt>. We will define
|
||||
the <tt>dereference()</tt> member function, which is used to implement
|
||||
<tt>operator*()</tt> of the adapted iterator. The implementation will
|
||||
dereference the base iterator and apply the function object. The complete
|
||||
code for <tt>transform_iterator_policies</tt> is:<br>
|
||||
dereference the base iterator and apply the function object. The
|
||||
<tt>type<Reference></tt> parameter is used to convey the appropriate
|
||||
return type. The complete code for <tt>transform_iterator_policies</tt>
|
||||
is:<br>
|
||||
<br>
|
||||
|
||||
<blockquote><pre>
|
||||
template <class AdaptableUnaryFunction>
|
||||
struct transform_iterator_policies : public default_iterator_policies
|
||||
{
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class AdaptableUnaryFunction>
|
||||
struct transform_iterator_policies : public default_iterator_policies
|
||||
{
|
||||
transform_iterator_policies() { }
|
||||
|
||||
transform_iterator_policies(const AdaptableUnaryFunction& f)
|
||||
: m_f(f) { }
|
||||
|
||||
template <class IteratorAdaptor>
|
||||
typename IteratorAdaptor::reference
|
||||
dereference(const IteratorAdaptor& iter) const
|
||||
{ return m_f(*iter.base()); }
|
||||
: m_f(f) { }
|
||||
|
||||
template <class Reference, class BaseIterator>
|
||||
Reference dereference(type<Reference>, const BaseIterator& i) const
|
||||
{ return m_f(*i); }
|
||||
|
||||
AdaptableUnaryFunction m_f;
|
||||
};
|
||||
|
||||
</pre></blockquote>
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>The next step is to use the <tt>iterator_adaptor</tt> template to
|
||||
construct the transform iterator type. The nicest way to package the
|
||||
@ -622,7 +575,7 @@ public:
|
||||
|
||||
<p>As a finishing touch, we will create an <a href=
|
||||
"../../more/generic_programming.html#object_generator">object generator</a>
|
||||
for the transform iterator. Our object generator makes it more
|
||||
for the transform iterator. This is a function that makes it more
|
||||
convenient to create a transform iterator.<br>
|
||||
<br>
|
||||
|
||||
@ -658,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;
|
||||
}
|
||||
@ -705,7 +658,7 @@ int main(int, char*[])
|
||||
|
||||
<li>Interoperable iterators can be freely mixed in comparison expressions
|
||||
so long as the <tt>Policies</tt> class has <tt>equal</tt> (and, for
|
||||
random access iterators, <tt>distance</tt>) members that can accept both
|
||||
random access iterators, <tt>less</tt>) members that can accept both
|
||||
<tt>Base</tt> types in either order.
|
||||
|
||||
<li>Interoperable iterators can be freely mixed in subtraction
|
||||
@ -759,12 +712,11 @@ they share the same <tt>Policies</tt> and since <tt>Category</tt> and
|
||||
the projection <tt>const_iterator</tt>.
|
||||
|
||||
<li> Since <tt>projection_iterator_policies</tt> implements only the
|
||||
<tt>dereference</tt> operation, and inherits all other behaviors from
|
||||
<tt><a
|
||||
href="#default_iterator_policies">default_iterator_policies</a></tt>,
|
||||
which has fully-templatized <tt>equal</tt> and <tt>distance</tt>
|
||||
operations, the <tt>iterator</tt> and <tt>const_iterator</tt> can be
|
||||
freely mixed in comparison and subtraction expressions.
|
||||
<tt>dereference</tt> operation, and inherits all other behaviors from <tt><a
|
||||
href="#default_iterator_policies">default_iterator_policies</a></tt>, which has
|
||||
fully-templatized <tt>equal</tt>, <tt>less</tt>, and <tt>distance</tt>
|
||||
operations, the <tt>iterator</tt> and <tt>const_iterator</tt> can be freely
|
||||
mixed in comparison and subtraction expressions.
|
||||
|
||||
</ul>
|
||||
|
||||
@ -772,7 +724,7 @@ freely mixed in comparison and subtraction expressions.
|
||||
|
||||
<p>There is an unlimited number of ways the <tt>iterator_adaptors</tt>
|
||||
class can be used to create iterators. One interesting exercise would be to
|
||||
re-implement the iterators of <tt>std::list</tt> and <tt>slist</tt>
|
||||
re-implement the iterators of <tt>std::list</tt> and <tt>std::slist</tt>
|
||||
using <tt>iterator_adaptors</tt>, where the adapted <tt>Iterator</tt> types
|
||||
would be node pointers.
|
||||
|
||||
@ -809,17 +761,16 @@ struct iterator_adaptor
|
||||
iterator_adaptor();
|
||||
explicit iterator_adaptor(const Base&, const Policies& = Policies());
|
||||
|
||||
base_type& base();
|
||||
const base_type& base() const;
|
||||
base_type base() const;
|
||||
|
||||
template <class B, class V, class R, class P>
|
||||
iterator_adaptor(
|
||||
const iterator_adaptor<B,Policies,V,R,P,Category,Distance>&);
|
||||
|
||||
reference operator*() const; <a href="#6">[6]</a>
|
||||
reference operator*() const;
|
||||
<i>operator_arrow_result_type</i> operator->() const; <a href=
|
||||
"#3">[3]</a>
|
||||
<i>value_type</i> operator[](difference_type n) const; <a href="#3">[4]</a>, <a href="#6">[6]</a>
|
||||
<i>value_type</i> operator[](difference_type n) const; <a href="#3">[4]</a>
|
||||
|
||||
iterator_adaptor& operator++();
|
||||
iterator_adaptor& operator++(int);
|
||||
@ -855,19 +806,6 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
|
||||
// and similarly for operators !=, <, <=, >=, >
|
||||
</pre>
|
||||
|
||||
<h3><a name="portability">Portability</a></h3>
|
||||
|
||||
<p>Generally, the iterator adaptors library can be compiled with all compilers
|
||||
supporting iterator traits and type traits.</p>
|
||||
|
||||
<p>Microsoft VC++ is not able to handle iterator adaptors based on a
|
||||
<code>vector<T>::iterator</code> without specifying all template paramters explicitly.
|
||||
In case not all template parameters are specified explicitly, the iterator adaptors
|
||||
library will deduce these types using iterator_traits. But since in VC++ a
|
||||
<code>vector<T>::iterator</code> is a <code>T*</code>, VC++ can't handle using
|
||||
iterator_traits due to the lack of partial template specialization.</p>
|
||||
|
||||
|
||||
<h3><a name="notes">Notes</a></h3>
|
||||
|
||||
<p><a name="1">[1]</a> The standard specifies that the <tt>value_type</tt>
|
||||
@ -876,12 +814,12 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
|
||||
<tt>reference</tt> types for all <a href=
|
||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward Iterators</a> are
|
||||
<tt>const T*</tt> and <tt>const T&</tt>, respectively. Stripping the
|
||||
<tt>const</tt>-ness of <tt>Value</tt> allows you to easily make a constant
|
||||
iterator by supplying a <tt>const</tt> type for <tt>Value</tt>, and allowing
|
||||
the defaults for the <tt>Pointer</tt> and <tt>Reference</tt> parameters to
|
||||
take effect. Although compilers that don't support partial specialization
|
||||
won't strip <tt>const</tt> for you, having a <tt>const value_type</tt> is
|
||||
often harmless in practice.
|
||||
<tt>const</tt>-ness of <tt>Value</tt> allows you to easily
|
||||
make a <tt>const</tt> iterator adaptor by supplying a <tt>const</tt> type
|
||||
for <tt>Value</tt>, and allowing the defaults for the <tt>Pointer</tt> and
|
||||
<tt>Reference</tt> parameters to take effect. Although compilers that don't
|
||||
support partial specialization won't strip <tt>const</tt> for you, having a
|
||||
<tt>const value_type</tt> is often harmless in practice.
|
||||
|
||||
<p><a name="2">[2]</a> If your compiler does not support partial
|
||||
specialization and the base iterator is a builtin pointer type, you
|
||||
@ -919,50 +857,10 @@ 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>
|
||||
|
||||
<p><a name="7">[7]</a>
|
||||
If you are using a compiler that does not have a version of
|
||||
<tt>std::iterator_traits</tt> that works for pointers (i.e., if your
|
||||
compiler does not support partial specialization) then if the
|
||||
<tt>Base</tt> type is a const pointer, then the correct defaults
|
||||
for the <tt>reference</tt> and <tt>pointer</tt> types can not be
|
||||
deduced. You must specify these types explicitly.
|
||||
<p><a name="8">[8]</a>
|
||||
Exposing the base object might be considered as being dangerous.
|
||||
A possible fix would require compiler support for template friends.
|
||||
As this is not widely available today, the base object remains exposed for now.
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->30 Nov 2001<!--webbot bot="Timestamp" endspan i-checksum="15239" -->
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->19 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14895" -->
|
||||
|
||||
|
||||
<p>© Copyright Dave Abrahams and Jeremy Siek 2001. Permission to copy,
|
||||
@ -973,7 +871,7 @@ bool operator==(const iterator_adaptor<B1,P,V1,R1,P1,C,D>&,
|
||||
|
||||
</body>
|
||||
|
||||
<!-- LocalWords: HTML html charset alt gif abrahams htm const iterator
|
||||
<!-- LocalWords: HTML html charset alt gif abrahams htm const
|
||||
incrementable david abrahams
|
||||
-->
|
||||
|
||||
@ -989,7 +887,5 @@ 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>
|
||||
|
||||
|
Binary file not shown.
Binary file not shown.
@ -85,17 +85,15 @@ template <class Iterator,
|
||||
struct non_portable_tests
|
||||
{
|
||||
// Unfortunately, the VC6 standard library doesn't supply these :(
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::pointer test_pt;
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::reference test_rt;
|
||||
BOOST_STATIC_ASSERT((
|
||||
::boost::is_same<
|
||||
test_pt,
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::pointer,
|
||||
pointer
|
||||
>::value));
|
||||
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
::boost::is_same<
|
||||
test_rt,
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::reference,
|
||||
reference
|
||||
>::value));
|
||||
};
|
||||
@ -104,17 +102,15 @@ template <class Iterator,
|
||||
class value_type, class difference_type, class pointer, class reference, class category>
|
||||
struct portable_tests
|
||||
{
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::difference_type test_dt;
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::iterator_category test_cat;
|
||||
BOOST_STATIC_ASSERT((
|
||||
::boost::is_same<
|
||||
test_dt,
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::difference_type,
|
||||
difference_type
|
||||
>::value));
|
||||
|
||||
|
||||
BOOST_STATIC_ASSERT((
|
||||
::boost::is_same<
|
||||
test_cat,
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::iterator_category,
|
||||
category
|
||||
>::value));
|
||||
};
|
||||
@ -125,10 +121,9 @@ template <class Iterator,
|
||||
struct input_iterator_test
|
||||
: portable_tests<Iterator,value_type,difference_type,pointer,reference,category>
|
||||
{
|
||||
typedef typename boost::detail::iterator_traits<Iterator>::value_type test_vt;
|
||||
BOOST_STATIC_ASSERT((
|
||||
::boost::is_same<
|
||||
test_vt,
|
||||
boost::is_same<
|
||||
typename boost::detail::iterator_traits<Iterator>::value_type,
|
||||
value_type
|
||||
>::value));
|
||||
};
|
||||
|
@ -9,29 +9,16 @@
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 29 May 01 Factored implementation, added comparison tests, use Test Tools
|
||||
// library (Daryle Walker)
|
||||
// 12 Dec 99 Initial version with iterator operators (Jeremy Siek)
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp> // for main
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#include <boost/config.hpp> // for BOOST_STATIC_CONSTANT
|
||||
#include <boost/cstdlib.hpp> // for boost::exit_success
|
||||
#include <boost/operators.hpp> // for boost::random_access_iterator_helper
|
||||
|
||||
#include <cstddef> // for std::ptrdiff_t, std::size_t
|
||||
#include <cstring> // for std::strcmp
|
||||
#include <iostream> // for std::cout (std::endl, ends, and flush indirectly)
|
||||
#include <string> // for std::string
|
||||
#include <strstream> // for std::ostrstream
|
||||
|
||||
# ifdef BOOST_NO_STDC_NAMESPACE
|
||||
namespace std { using ::strcmp; }
|
||||
# endif
|
||||
#include <boost/operators.hpp>
|
||||
using namespace boost;
|
||||
|
||||
|
||||
// Iterator test class
|
||||
template <class T, class R, class P>
|
||||
struct test_iter
|
||||
: public boost::random_access_iterator_helper<
|
||||
@ -42,7 +29,7 @@ struct test_iter
|
||||
typedef std::ptrdiff_t Distance;
|
||||
|
||||
public:
|
||||
explicit test_iter(T* i =0) : _i(i) { }
|
||||
test_iter(T* i) : _i(i) { }
|
||||
test_iter(const self& x) : _i(x._i) { }
|
||||
self& operator=(const self& x) { _i = x._i; return *this; }
|
||||
Reference operator*() const { return *_i; }
|
||||
@ -56,287 +43,127 @@ public:
|
||||
return x._i - y._i;
|
||||
}
|
||||
protected:
|
||||
P _i;
|
||||
T* _i;
|
||||
};
|
||||
|
||||
// Iterator operator testing classes
|
||||
class test_opr_base
|
||||
{
|
||||
protected:
|
||||
// Test data and types
|
||||
BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u );
|
||||
BOOST_STATIC_CONSTANT( std::size_t, scratch_length = 40u );
|
||||
|
||||
typedef std::string fruit_array_type[ fruit_length ];
|
||||
typedef char scratch_array_type[ scratch_length ];
|
||||
|
||||
static fruit_array_type fruit;
|
||||
static scratch_array_type scratch;
|
||||
|
||||
}; // test_opr_base
|
||||
|
||||
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
|
||||
// A definition is required even for integral static constants
|
||||
const std::size_t test_opr_base::fruit_length;
|
||||
const std::size_t test_opr_base::scratch_length;
|
||||
#endif
|
||||
|
||||
template <typename T, typename R = T&, typename P = T*>
|
||||
class test_opr
|
||||
: public test_opr_base
|
||||
{
|
||||
typedef test_opr<T, R, P> self_type;
|
||||
|
||||
public:
|
||||
// Types
|
||||
typedef T value_type;
|
||||
typedef R reference;
|
||||
typedef P pointer;
|
||||
|
||||
typedef test_iter<T, R, P> iter_type;
|
||||
|
||||
// Test controller
|
||||
static void master_test( char const name[] );
|
||||
|
||||
private:
|
||||
// Test data
|
||||
static iter_type const fruit_begin;
|
||||
static iter_type const fruit_end;
|
||||
|
||||
// Test parts
|
||||
static void post_increment_test();
|
||||
static void post_decrement_test();
|
||||
static void indirect_referral_test();
|
||||
static void offset_addition_test();
|
||||
static void reverse_offset_addition_test();
|
||||
static void offset_subtraction_test();
|
||||
static void comparison_test();
|
||||
static void indexing_test();
|
||||
|
||||
}; // test_opr
|
||||
|
||||
|
||||
// Class-static data definitions
|
||||
test_opr_base::fruit_array_type
|
||||
test_opr_base::fruit = { "apple", "orange", "pear", "peach", "grape", "plum" };
|
||||
|
||||
test_opr_base::scratch_array_type
|
||||
test_opr_base::scratch = "";
|
||||
|
||||
template <typename T, typename R, typename P>
|
||||
typename test_opr<T, R, P>::iter_type const
|
||||
test_opr<T, R, P>::fruit_begin = test_iter<T,R,P>( fruit );
|
||||
|
||||
template <typename T, typename R, typename P>
|
||||
typename test_opr<T, R, P>::iter_type const
|
||||
test_opr<T, R, P>::fruit_end = test_iter<T,R,P>( fruit + fruit_length );
|
||||
|
||||
|
||||
// Main testing function
|
||||
int
|
||||
test_main( int , char * [] )
|
||||
main()
|
||||
{
|
||||
using std::string;
|
||||
string array[] = { "apple", "orange", "pear", "peach", "grape", "plum" };
|
||||
{
|
||||
test_iter<string,string&,string*> i = array,
|
||||
ie = array + sizeof(array)/sizeof(string);
|
||||
|
||||
typedef test_opr<string, string &, string *> test1_type;
|
||||
typedef test_opr<string, string const &, string const *> test2_type;
|
||||
// Tests for all of the operators added by random_access_iterator_helper
|
||||
|
||||
test1_type::master_test( "non-const string" );
|
||||
test2_type::master_test( "const string" );
|
||||
// test i++
|
||||
while (i != ie)
|
||||
cout << *i++ << " ";
|
||||
cout << endl;
|
||||
i = array;
|
||||
|
||||
return boost::exit_success;
|
||||
}
|
||||
|
||||
// Tests for all of the operators added by random_access_iterator_helper
|
||||
template <typename T, typename R, typename P>
|
||||
void
|
||||
test_opr<T, R, P>::master_test
|
||||
(
|
||||
char const name[]
|
||||
)
|
||||
{
|
||||
std::cout << "Doing test run for " << name << '.' << std::endl;
|
||||
|
||||
post_increment_test();
|
||||
post_decrement_test();
|
||||
indirect_referral_test();
|
||||
offset_addition_test();
|
||||
reverse_offset_addition_test();
|
||||
offset_subtraction_test();
|
||||
comparison_test();
|
||||
indexing_test();
|
||||
}
|
||||
|
||||
// Test post-increment
|
||||
template <typename T, typename R, typename P>
|
||||
void
|
||||
test_opr<T, R, P>::post_increment_test
|
||||
(
|
||||
)
|
||||
{
|
||||
std::cout << "\tDoing post-increment test." << std::endl;
|
||||
|
||||
std::ostrstream oss( scratch, scratch_length );
|
||||
for ( iter_type i = fruit_begin ; i != fruit_end ; )
|
||||
{
|
||||
oss << *i++ << ' ';
|
||||
// test i--
|
||||
while (ie != i) {
|
||||
ie--;
|
||||
cout << *ie << " ";
|
||||
}
|
||||
cout << endl;
|
||||
ie = array + sizeof(array)/sizeof(string);
|
||||
|
||||
oss << std::ends;
|
||||
BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ")
|
||||
== 0 );
|
||||
}
|
||||
|
||||
// Test post-decrement
|
||||
template <typename T, typename R, typename P>
|
||||
void
|
||||
test_opr<T, R, P>::post_decrement_test
|
||||
(
|
||||
)
|
||||
{
|
||||
std::cout << "\tDoing post-decrement test." << std::endl;
|
||||
|
||||
std::ostrstream oss( scratch, scratch_length );
|
||||
for ( iter_type i = fruit_end ; i != fruit_begin ; )
|
||||
{
|
||||
i--;
|
||||
oss << *i << ' ';
|
||||
// test i->m
|
||||
while (i != ie) {
|
||||
cout << i->size() << " ";
|
||||
++i;
|
||||
}
|
||||
cout << endl;
|
||||
i = array;
|
||||
|
||||
oss << std::ends;
|
||||
BOOST_TEST( std::strcmp(oss.str(), "plum grape peach pear orange apple ")
|
||||
== 0 );
|
||||
}
|
||||
|
||||
// Test indirect structure referral
|
||||
template <typename T, typename R, typename P>
|
||||
void
|
||||
test_opr<T, R, P>::indirect_referral_test
|
||||
(
|
||||
)
|
||||
{
|
||||
std::cout << "\tDoing indirect reference test." << std::endl;
|
||||
|
||||
std::ostrstream oss( scratch, scratch_length );
|
||||
for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
|
||||
{
|
||||
oss << i->size() << ' ';
|
||||
// test i + n
|
||||
while (i < ie) {
|
||||
cout << *i << " ";
|
||||
i = i + 2;
|
||||
}
|
||||
cout << endl;
|
||||
i = array;
|
||||
|
||||
oss << std::ends;
|
||||
BOOST_TEST( std::strcmp(oss.str(), "5 6 4 5 5 4 ") == 0 );
|
||||
}
|
||||
|
||||
// Test offset addition
|
||||
template <typename T, typename R, typename P>
|
||||
void
|
||||
test_opr<T, R, P>::offset_addition_test
|
||||
(
|
||||
)
|
||||
{
|
||||
std::cout << "\tDoing offset addition test." << std::endl;
|
||||
|
||||
std::ptrdiff_t const two = 2;
|
||||
std::ostrstream oss( scratch, scratch_length );
|
||||
for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two )
|
||||
{
|
||||
oss << *i << ' ';
|
||||
// test n + i
|
||||
while (i < ie) {
|
||||
cout << *i << " ";
|
||||
i = ptrdiff_t(2) + i;
|
||||
}
|
||||
cout << endl;
|
||||
i = array;
|
||||
|
||||
oss << std::ends;
|
||||
BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 );
|
||||
}
|
||||
|
||||
// Test offset addition, in reverse order
|
||||
template <typename T, typename R, typename P>
|
||||
void
|
||||
test_opr<T, R, P>::reverse_offset_addition_test
|
||||
(
|
||||
)
|
||||
{
|
||||
std::cout << "\tDoing reverse offset addition test." << std::endl;
|
||||
|
||||
std::ptrdiff_t const two = 2;
|
||||
std::ostrstream oss( scratch, scratch_length );
|
||||
for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i )
|
||||
{
|
||||
oss << *i << ' ';
|
||||
// test i - n
|
||||
while (ie > i) {
|
||||
ie = ie - 2;
|
||||
cout << *ie << " ";
|
||||
}
|
||||
cout << endl;
|
||||
ie = array + sizeof(array)/sizeof(string);
|
||||
|
||||
oss << std::ends;
|
||||
BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 );
|
||||
}
|
||||
// test i[n]
|
||||
for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j)
|
||||
cout << i[j] << " ";
|
||||
cout << endl;
|
||||
}
|
||||
{
|
||||
test_iter<string, const string&, const string*> i = array,
|
||||
ie = array + sizeof(array)/sizeof(string);
|
||||
|
||||
// Test offset subtraction
|
||||
template <typename T, typename R, typename P>
|
||||
void
|
||||
test_opr<T, R, P>::offset_subtraction_test
|
||||
(
|
||||
)
|
||||
{
|
||||
std::cout << "\tDoing offset subtraction test." << std::endl;
|
||||
// Tests for all of the operators added by random_access_iterator_helper
|
||||
|
||||
std::ptrdiff_t const two = 2;
|
||||
std::ostrstream oss( scratch, scratch_length );
|
||||
for ( iter_type i = fruit_end ; fruit_begin < i ; )
|
||||
{
|
||||
i = i - two;
|
||||
if ( (fruit_begin < i) || (fruit_begin == i) )
|
||||
{
|
||||
oss << *i << ' ';
|
||||
}
|
||||
// test i++
|
||||
while (i != ie)
|
||||
cout << *i++ << " ";
|
||||
cout << endl;
|
||||
i = array;
|
||||
|
||||
// test i--
|
||||
while (ie != i) {
|
||||
ie--;
|
||||
cout << *ie << " ";
|
||||
}
|
||||
cout << endl;
|
||||
ie = array + sizeof(array)/sizeof(string);
|
||||
|
||||
oss << std::ends;
|
||||
BOOST_TEST( std::strcmp(oss.str(), "grape pear apple ") == 0 );
|
||||
}
|
||||
|
||||
// Test comparisons
|
||||
template <typename T, typename R, typename P>
|
||||
void
|
||||
test_opr<T, R, P>::comparison_test
|
||||
(
|
||||
)
|
||||
{
|
||||
using std::cout;
|
||||
using std::ptrdiff_t;
|
||||
|
||||
cout << "\tDoing comparison tests.\n\t\tPass:";
|
||||
|
||||
for ( iter_type i = fruit_begin ; i != fruit_end ; ++i )
|
||||
{
|
||||
ptrdiff_t const i_offset = i - fruit_begin;
|
||||
|
||||
cout << ' ' << *i << std::flush;
|
||||
for ( iter_type j = fruit_begin ; j != fruit_end ; ++j )
|
||||
{
|
||||
ptrdiff_t const j_offset = j - fruit_begin;
|
||||
|
||||
BOOST_TEST( (i != j) == (i_offset != j_offset) );
|
||||
BOOST_TEST( (i > j) == (i_offset > j_offset) );
|
||||
BOOST_TEST( (i <= j) == (i_offset <= j_offset) );
|
||||
BOOST_TEST( (i >= j) == (i_offset >= j_offset) );
|
||||
}
|
||||
// test i->m
|
||||
while (i != ie) {
|
||||
cout << i->size() << " ";
|
||||
++i;
|
||||
}
|
||||
cout << std::endl;
|
||||
}
|
||||
cout << endl;
|
||||
i = array;
|
||||
|
||||
// Test indexing
|
||||
template <typename T, typename R, typename P>
|
||||
void
|
||||
test_opr<T, R, P>::indexing_test
|
||||
(
|
||||
)
|
||||
{
|
||||
std::cout << "\tDoing indexing test." << std::endl;
|
||||
|
||||
std::ostrstream oss( scratch, scratch_length );
|
||||
for ( std::size_t k = 0u ; k < fruit_length ; ++k )
|
||||
{
|
||||
oss << fruit_begin[ k ] << ' ';
|
||||
// test i + n
|
||||
while (i < ie) {
|
||||
cout << *i << " ";
|
||||
i = i + 2;
|
||||
}
|
||||
cout << endl;
|
||||
i = array;
|
||||
|
||||
oss << std::ends;
|
||||
BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ")
|
||||
== 0 );
|
||||
// test n + i
|
||||
while (i < ie) {
|
||||
cout << *i << " ";
|
||||
i = ptrdiff_t(2) + i;
|
||||
}
|
||||
cout << endl;
|
||||
i = array;
|
||||
|
||||
// test i - n
|
||||
while (ie > i) {
|
||||
ie = ie - 2;
|
||||
cout << *ie << " ";
|
||||
}
|
||||
cout << endl;
|
||||
ie = array + sizeof(array)/sizeof(string);
|
||||
|
||||
// test i[n]
|
||||
for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j)
|
||||
cout << i[j] << " ";
|
||||
cout << endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
namespace
|
||||
{
|
||||
class DontTreadOnMe : private boost::noncopyable
|
||||
class DontTreadOnMe : boost::noncopyable
|
||||
{
|
||||
public:
|
||||
DontTreadOnMe() { std::cout << "defanged!" << std::endl; }
|
||||
@ -35,4 +35,4 @@ int main()
|
||||
object1 = object2;
|
||||
return 0;
|
||||
} // main
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
// 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
|
||||
@ -31,6 +30,13 @@
|
||||
# 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> --
|
||||
//
|
||||
@ -47,8 +53,8 @@ template <unsigned size> struct complement; // forward
|
||||
template <class Number, unsigned size>
|
||||
struct complement_traits_aux
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(Number, max = complement<size>::template traits<Number>::max);
|
||||
BOOST_STATIC_CONSTANT(Number, min = complement<size>::template traits<Number>::min);
|
||||
DECLARE_CLASS_CONST(Number, max = complement<size>::template traits<Number>::max);
|
||||
DECLARE_CLASS_CONST(Number, min = complement<size>::template traits<Number>::min);
|
||||
};
|
||||
|
||||
template <unsigned size>
|
||||
@ -61,11 +67,11 @@ struct complement
|
||||
// indirection through complement_traits_aux neccessary to keep MSVC happy
|
||||
typedef complement_traits_aux<Number, size - 1> prev;
|
||||
public:
|
||||
BOOST_STATIC_CONSTANT(Number, max =
|
||||
DECLARE_CLASS_CONST(Number, max =
|
||||
Number(Number(prev::max) << CHAR_BIT)
|
||||
+ Number(UCHAR_MAX));
|
||||
|
||||
BOOST_STATIC_CONSTANT(Number, min = Number(Number(prev::min) << CHAR_BIT));
|
||||
DECLARE_CLASS_CONST(Number, min = Number(Number(prev::min) << CHAR_BIT));
|
||||
};
|
||||
};
|
||||
|
||||
@ -79,8 +85,8 @@ template <> struct complement_base<false>
|
||||
template <class Number>
|
||||
struct values
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(Number, min = 0);
|
||||
BOOST_STATIC_CONSTANT(Number, max = UCHAR_MAX);
|
||||
DECLARE_CLASS_CONST(Number, min = 0);
|
||||
DECLARE_CLASS_CONST(Number, max = UCHAR_MAX);
|
||||
};
|
||||
};
|
||||
|
||||
@ -89,8 +95,8 @@ template <> struct complement_base<true>
|
||||
template <class Number>
|
||||
struct values
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(Number, min = SCHAR_MIN);
|
||||
BOOST_STATIC_CONSTANT(Number, max = SCHAR_MAX);
|
||||
DECLARE_CLASS_CONST(Number, min = SCHAR_MIN);
|
||||
DECLARE_CLASS_CONST(Number, max = SCHAR_MAX);
|
||||
};
|
||||
};
|
||||
|
||||
@ -101,10 +107,10 @@ struct complement<1>
|
||||
template <class Number>
|
||||
struct traits
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(bool, is_signed = boost::detail::is_signed<Number>::value);
|
||||
BOOST_STATIC_CONSTANT(Number, min =
|
||||
DECLARE_CLASS_CONST(bool, is_signed = boost::detail::is_signed<Number>::value);
|
||||
DECLARE_CLASS_CONST(Number, min =
|
||||
complement_base<is_signed>::template values<Number>::min);
|
||||
BOOST_STATIC_CONSTANT(Number, max =
|
||||
DECLARE_CLASS_CONST(Number, max =
|
||||
complement_base<is_signed>::template values<Number>::max);
|
||||
};
|
||||
};
|
||||
@ -115,8 +121,8 @@ struct complement<1>
|
||||
template <class Number>
|
||||
struct complement_traits
|
||||
{
|
||||
BOOST_STATIC_CONSTANT(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max));
|
||||
BOOST_STATIC_CONSTANT(Number, min = (complement_traits_aux<Number, sizeof(Number)>::min));
|
||||
DECLARE_CLASS_CONST(Number, max = (complement_traits_aux<Number, sizeof(Number)>::max));
|
||||
DECLARE_CLASS_CONST(Number, min = (complement_traits_aux<Number, sizeof(Number)>::min));
|
||||
};
|
||||
|
||||
// =================================================================================
|
||||
@ -145,9 +151,9 @@ template <> struct stream_as<signed char> {
|
||||
typedef unsigned char t1; typedef unsigned t2;
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in
|
||||
#if defined(BOOST_MSVC) // No intmax streaming built-in
|
||||
|
||||
// With this library implementation, __int64 and __uint64 get streamed as strings
|
||||
// On this platform, __int64 and __uint64 get streamed as strings
|
||||
template <> struct stream_as<boost::uintmax_t> {
|
||||
typedef std::string t1;
|
||||
typedef std::string t2;
|
||||
@ -168,7 +174,7 @@ template <class T> struct promote
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in
|
||||
#if defined(BOOST_MSVC) // No intmax streaming built-in
|
||||
|
||||
// On this platform, stream them as long/unsigned long if they fit.
|
||||
// Otherwise, write a string.
|
||||
@ -347,7 +353,7 @@ void test(Number* = 0)
|
||||
|
||||
// factoring out difference_type for the assert below confused Borland :(
|
||||
typedef boost::detail::is_signed<
|
||||
#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
|
||||
#ifndef BOOST_MSVC
|
||||
typename
|
||||
#endif
|
||||
boost::detail::numeric_traits<Number>::difference_type
|
||||
@ -374,7 +380,7 @@ int main()
|
||||
test<unsigned int>();
|
||||
test<long>();
|
||||
test<unsigned long>();
|
||||
#if defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_INTEGRAL_INT64_T)
|
||||
#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX)
|
||||
test<long long>();
|
||||
test<unsigned long long>();
|
||||
#elif defined(BOOST_MSVC)
|
||||
|
1796
operators.htm
1796
operators.htm
File diff suppressed because it is too large
Load Diff
@ -8,28 +8,18 @@
|
||||
// See http://www.boost.org for most recent version including documentation.
|
||||
|
||||
// Revision History
|
||||
// 01 Oct 01 Added tests for "left" operators
|
||||
// and new grouped operators. (Helmut Zeisel)
|
||||
// 20 May 01 Output progress messages. Added tests for new operator
|
||||
// templates. Updated random number generator. Changed tests to
|
||||
// use Boost Test Tools library. (Daryle Walker)
|
||||
// 04 Jun 00 Added regression test for a bug I found (David Abrahams)
|
||||
// 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy)
|
||||
// ?? ??? 00 Major update to randomly test all one- and two- argument forms by
|
||||
// wrapping integral types and comparing the results of operations
|
||||
// to the results for the raw types (David Abrahams)
|
||||
// wrapping integral types and comparing the results of operations to
|
||||
// the results for the raw types (David Abrahams)
|
||||
// 12 Dec 99 Minor update, output confirmation message.
|
||||
// 15 Nov 99 Initial version
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
|
||||
#include <boost/config.hpp> // for BOOST_MSVC
|
||||
#include <boost/cstdlib.hpp> // for boost::exit_success
|
||||
#include <boost/operators.hpp> // for the tested items
|
||||
#include <boost/random/linear_congruential.hpp> // for boost::minstd_rand
|
||||
#include <boost/test/test_tools.hpp> // for main
|
||||
|
||||
#include <iostream> // for std::cout (std::endl indirectly)
|
||||
#include <boost/operators.hpp>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <boost/min_rand.hpp>
|
||||
|
||||
|
||||
namespace
|
||||
@ -38,18 +28,14 @@ namespace
|
||||
int true_value(int x) { return x; }
|
||||
long true_value(long x) { return x; }
|
||||
signed char true_value(signed char x) { return x; }
|
||||
short true_value(short x) { return x; }
|
||||
unsigned int true_value(unsigned int x) { return x; }
|
||||
unsigned long true_value(unsigned long x) { return x; }
|
||||
unsigned char true_value(unsigned char x) { return x; }
|
||||
unsigned short true_value(unsigned short x) { return x; }
|
||||
|
||||
// The use of operators<> here tended to obscure
|
||||
// interactions with certain compiler bugs
|
||||
// The use of operators<> here tended to obscure interactions with certain
|
||||
// compiler bugs
|
||||
template <class T>
|
||||
class Wrapped1
|
||||
: boost::operators<Wrapped1<T> >
|
||||
, boost::shiftable<Wrapped1<T> >
|
||||
class Wrapped1 : boost::operators<Wrapped1<T> >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped1( T v = T() ) : _value(v) {}
|
||||
@ -74,10 +60,6 @@ namespace
|
||||
{ _value &= x._value; return *this; }
|
||||
Wrapped1& operator^=(const Wrapped1& x)
|
||||
{ _value ^= x._value; return *this; }
|
||||
Wrapped1& operator<<=(const Wrapped1& x)
|
||||
{ _value <<= x._value; return *this; }
|
||||
Wrapped1& operator>>=(const Wrapped1& x)
|
||||
{ _value >>= x._value; return *this; }
|
||||
Wrapped1& operator++() { ++_value; return *this; }
|
||||
Wrapped1& operator--() { --_value; return *this; }
|
||||
|
||||
@ -88,11 +70,9 @@ namespace
|
||||
T true_value(Wrapped1<T> x) { return x.value(); }
|
||||
|
||||
template <class T, class U>
|
||||
class Wrapped2
|
||||
: boost::operators<Wrapped2<T, U> >
|
||||
, boost::operators2<Wrapped2<T, U>, U>
|
||||
, boost::shiftable1<Wrapped2<T, U>
|
||||
, boost::shiftable2<Wrapped2<T, U>, U > >
|
||||
class Wrapped2 :
|
||||
boost::operators<Wrapped2<T, U> >,
|
||||
boost::operators2<Wrapped2<T, U>, U>
|
||||
{
|
||||
public:
|
||||
explicit Wrapped2( T v = T() ) : _value(v) {}
|
||||
@ -117,10 +97,6 @@ namespace
|
||||
{ _value &= x._value; return *this; }
|
||||
Wrapped2& operator^=(const Wrapped2& x)
|
||||
{ _value ^= x._value; return *this; }
|
||||
Wrapped2& operator<<=(const Wrapped2& x)
|
||||
{ _value <<= x._value; return *this; }
|
||||
Wrapped2& operator>>=(const Wrapped2& x)
|
||||
{ _value >>= x._value; return *this; }
|
||||
Wrapped2& operator++() { ++_value; return *this; }
|
||||
Wrapped2& operator--() { --_value; return *this; }
|
||||
|
||||
@ -135,8 +111,6 @@ namespace
|
||||
Wrapped2& operator|=(U u) { _value |= u; return *this; }
|
||||
Wrapped2& operator&=(U u) { _value &= u; return *this; }
|
||||
Wrapped2& operator^=(U u) { _value ^= u; return *this; }
|
||||
Wrapped2& operator<<=(U u) { _value <<= u; return *this; }
|
||||
Wrapped2& operator>>=(U u) { _value >>= u; return *this; }
|
||||
|
||||
private:
|
||||
T _value;
|
||||
@ -144,383 +118,203 @@ namespace
|
||||
template <class T, class U>
|
||||
T true_value(Wrapped2<T,U> x) { return x.value(); }
|
||||
|
||||
template <class T>
|
||||
class Wrapped3
|
||||
: boost::equivalent<Wrapped3<T> >
|
||||
, boost::partially_ordered<Wrapped3<T> >
|
||||
, boost::equality_comparable<Wrapped3<T> >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped3( T v = T() ) : _value(v) {}
|
||||
T value() const { return _value; }
|
||||
|
||||
bool operator<(const Wrapped3& x) const { return _value < x._value; }
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
template <class T>
|
||||
T true_value(Wrapped3<T> x) { return x.value(); }
|
||||
|
||||
template <class T, class U>
|
||||
class Wrapped4
|
||||
: boost::equality_comparable1<Wrapped4<T, U>
|
||||
, boost::equivalent1<Wrapped4<T, U>
|
||||
, boost::partially_ordered1<Wrapped4<T, U> > > >
|
||||
, boost::partially_ordered2<Wrapped4<T, U>, U
|
||||
, boost::equivalent2<Wrapped4<T, U>, U
|
||||
, boost::equality_comparable2<Wrapped4<T, U>, U> > >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped4( T v = T() ) : _value(v) {}
|
||||
T value() const { return _value; }
|
||||
|
||||
bool operator<(const Wrapped4& x) const { return _value < x._value; }
|
||||
|
||||
bool operator<(U u) const { return _value < u; }
|
||||
bool operator>(U u) const { return _value > u; }
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
template <class T, class U>
|
||||
T true_value(Wrapped4<T,U> x) { return x.value(); }
|
||||
|
||||
// U must be convertible to T
|
||||
template <class T, class U>
|
||||
class Wrapped5
|
||||
: boost::ordered_field_operators2<Wrapped5<T, U>, U>
|
||||
, boost::ordered_field_operators1<Wrapped5<T, U> >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped5( T v = T() ) : _value(v) {}
|
||||
|
||||
// Conversion from U to Wrapped5<T,U>
|
||||
Wrapped5(U u) : _value(u) {}
|
||||
|
||||
T value() const { return _value; }
|
||||
bool operator<(const Wrapped5& x) const { return _value < x._value; }
|
||||
bool operator<(U u) const { return _value < u; }
|
||||
bool operator>(U u) const { return _value > u; }
|
||||
bool operator==(const Wrapped5& u) const { return _value == u._value; }
|
||||
bool operator==(U u) const { return _value == u; }
|
||||
Wrapped5& operator/=(const Wrapped5& u) { _value /= u._value; return *this;}
|
||||
Wrapped5& operator/=(U u) { _value /= u; return *this;}
|
||||
Wrapped5& operator*=(const Wrapped5& u) { _value *= u._value; return *this;}
|
||||
Wrapped5& operator*=(U u) { _value *= u; return *this;}
|
||||
Wrapped5& operator-=(const Wrapped5& u) { _value -= u._value; return *this;}
|
||||
Wrapped5& operator-=(U u) { _value -= u; return *this;}
|
||||
Wrapped5& operator+=(const Wrapped5& u) { _value += u._value; return *this;}
|
||||
Wrapped5& operator+=(U u) { _value += u; return *this;}
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
template <class T, class U>
|
||||
T true_value(Wrapped5<T,U> x) { return x.value(); }
|
||||
|
||||
// U must be convertible to T
|
||||
template <class T, class U>
|
||||
class Wrapped6
|
||||
: boost::ordered_euclidian_ring_operators2<Wrapped6<T, U>, U>
|
||||
, boost::ordered_euclidian_ring_operators1<Wrapped6<T, U> >
|
||||
{
|
||||
public:
|
||||
explicit Wrapped6( T v = T() ) : _value(v) {}
|
||||
|
||||
// Conversion from U to Wrapped6<T,U>
|
||||
Wrapped6(U u) : _value(u) {}
|
||||
|
||||
T value() const { return _value; }
|
||||
bool operator<(const Wrapped6& x) const { return _value < x._value; }
|
||||
bool operator<(U u) const { return _value < u; }
|
||||
bool operator>(U u) const { return _value > u; }
|
||||
bool operator==(const Wrapped6& u) const { return _value == u._value; }
|
||||
bool operator==(U u) const { return _value == u; }
|
||||
Wrapped6& operator%=(const Wrapped6& u) { _value %= u._value; return *this;}
|
||||
Wrapped6& operator%=(U u) { _value %= u; return *this;}
|
||||
Wrapped6& operator/=(const Wrapped6& u) { _value /= u._value; return *this;}
|
||||
Wrapped6& operator/=(U u) { _value /= u; return *this;}
|
||||
Wrapped6& operator*=(const Wrapped6& u) { _value *= u._value; return *this;}
|
||||
Wrapped6& operator*=(U u) { _value *= u; return *this;}
|
||||
Wrapped6& operator-=(const Wrapped6& u) { _value -= u._value; return *this;}
|
||||
Wrapped6& operator-=(U u) { _value -= u; return *this;}
|
||||
Wrapped6& operator+=(const Wrapped6& u) { _value += u._value; return *this;}
|
||||
Wrapped6& operator+=(U u) { _value += u; return *this;}
|
||||
|
||||
private:
|
||||
T _value;
|
||||
};
|
||||
template <class T, class U>
|
||||
T true_value(Wrapped6<T,U> x) { return x.value(); }
|
||||
|
||||
// MyInt uses only the single template-argument form of all_operators<>
|
||||
typedef Wrapped1<int> MyInt;
|
||||
|
||||
typedef Wrapped2<long, long> MyLong;
|
||||
|
||||
typedef Wrapped3<signed char> MyChar;
|
||||
|
||||
typedef Wrapped4<short, short> MyShort;
|
||||
|
||||
typedef Wrapped5<double, int> MyDoubleInt;
|
||||
|
||||
typedef Wrapped6<long, int> MyLongInt;
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( true_value(y1) == true_value(y2) );
|
||||
BOOST_TEST( true_value(x1) == true_value(x2) );
|
||||
assert(true_value(y1) == true_value(y2));
|
||||
assert(true_value(x1) == true_value(x2));
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 < y1) == (x2 < y2) );
|
||||
BOOST_TEST( (x1 <= y1) == (x2 <= y2) );
|
||||
BOOST_TEST( (x1 >= y1) == (x2 >= y2) );
|
||||
BOOST_TEST( (x1 > y1) == (x2 > y2) );
|
||||
assert((x1 < y1) == (x2 < y2));
|
||||
assert((x1 <= y1) == (x2 <= y2));
|
||||
assert((x1 >= y1) == (x2 >= y2));
|
||||
assert((x1 > y1) == (x2 > y2));
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_less_than_comparable_aux( x1, y1, x2, y2 );
|
||||
test_less_than_comparable_aux( y1, x1, y2, x2 );
|
||||
sanity_check(x1, y1, x2, y2);
|
||||
test_less_than_comparable_aux(x1, y1, x2, y2);
|
||||
test_less_than_comparable_aux(y1, x1, y2, x2);
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 == y1) == (x2 == y2) );
|
||||
BOOST_TEST( (x1 != y1) == (x2 != y2) );
|
||||
assert((x1 == y1) == (x2 == y2));
|
||||
assert((x1 != y1) == (x2 != y2));
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_equality_comparable_aux( x1, y1, x2, y2 );
|
||||
test_equality_comparable_aux( y1, x1, y2, x2 );
|
||||
sanity_check(x1, y1, x2, y2);
|
||||
test_equality_comparable_aux(x1, y1, x2, y2);
|
||||
test_equality_comparable_aux(y1, x1, y2, x2);
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 * y1).value() == (x2 * y2) );
|
||||
assert((x1 * y1).value() == (x2 * y2));
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_multipliable_aux( x1, y1, x2, y2 );
|
||||
test_multipliable_aux( y1, x1, y2, x2 );
|
||||
sanity_check(x1, y1, x2, y2);
|
||||
test_multipliable_aux(x1, y1, x2, y2);
|
||||
test_multipliable_aux(y1, x1, y2, x2);
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 + y1).value() == (x2 + y2) );
|
||||
assert((x1 + y1).value() == (x2 + y2));
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_addable_aux( x1, y1, x2, y2 );
|
||||
test_addable_aux( y1, x1, y2, x2 );
|
||||
sanity_check(x1, y1, x2, y2);
|
||||
test_addable_aux(x1, y1, x2, y2);
|
||||
test_addable_aux(y1, x1, y2, x2);
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
BOOST_TEST( (x1 - y1).value() == (x2 - y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_subtractable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
BOOST_TEST( (y1 - x1).value() == (y2 - x2) );
|
||||
sanity_check(x1, y1, x2, y2);
|
||||
assert((x1 - y1).value() == x2 - y2);
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
if ( y2 != 0 )
|
||||
BOOST_TEST( (x1 / y1).value() == (x2 / y2) );
|
||||
sanity_check(x1, y1, x2, y2);
|
||||
if (y2 != 0)
|
||||
assert((x1 / y1).value() == x2 / y2);
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_dividable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
if ( x2 != 0 )
|
||||
BOOST_TEST( (y1 / x1).value() == (y2 / x2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
if ( y2 != 0 )
|
||||
BOOST_TEST( (x1 % y1).value() == (x2 % y2) );
|
||||
sanity_check(x1, y1, x2, y2);
|
||||
if (y2 != 0)
|
||||
assert((x1 / y1).value() == x2 / y2);
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_modable_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
if ( x2 != 0 )
|
||||
BOOST_TEST( (y1 % x1).value() == (y2 % x2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 ^ y1).value() == (x2 ^ y2) );
|
||||
assert((x1 ^ y1).value() == (x2 ^ y2));
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_xorable_aux( x1, y1, x2, y2 );
|
||||
test_xorable_aux( y1, x1, y2, x2 );
|
||||
sanity_check(x1, y1, x2, y2);
|
||||
test_xorable_aux(x1, y1, x2, y2);
|
||||
test_xorable_aux(y1, x1, y2, x2);
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 & y1).value() == (x2 & y2) );
|
||||
assert((x1 & y1).value() == (x2 & y2));
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_andable_aux( x1, y1, x2, y2 );
|
||||
test_andable_aux( y1, x1, y2, x2 );
|
||||
sanity_check(x1, y1, x2, y2);
|
||||
test_andable_aux(x1, y1, x2, y2);
|
||||
test_andable_aux(y1, x1, y2, x2);
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
BOOST_TEST( (x1 | y1).value() == (x2 | y2) );
|
||||
assert((x1 | y1).value() == (x2 | y2));
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
test_orable_aux( x1, y1, x2, y2 );
|
||||
test_orable_aux( y1, x1, y2, x2 );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_left_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
BOOST_TEST( (x1 << y1).value() == (x2 << y2) );
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
sanity_check( x1, y1, x2, y2 );
|
||||
BOOST_TEST( (x1 >> y1).value() == (x2 >> y2) );
|
||||
sanity_check(x1, y1, x2, y2);
|
||||
test_orable_aux(x1, y1, x2, y2);
|
||||
test_orable_aux(y1, x1, y2, x2);
|
||||
}
|
||||
|
||||
template <class X1, class X2>
|
||||
void test_incrementable(X1 x1, X2 x2)
|
||||
{
|
||||
sanity_check( x1, x1, x2, x2 );
|
||||
BOOST_TEST( (x1++).value() == x2++ );
|
||||
BOOST_TEST( x1.value() == x2 );
|
||||
sanity_check(x1, x1, x2, x2);
|
||||
assert(x1++.value() == x2++);
|
||||
assert(x1.value() == x2);
|
||||
}
|
||||
|
||||
template <class X1, class X2>
|
||||
void test_decrementable(X1 x1, X2 x2)
|
||||
{
|
||||
sanity_check( x1, x1, x2, x2 );
|
||||
BOOST_TEST( (x1--).value() == x2-- );
|
||||
BOOST_TEST( x1.value() == x2 );
|
||||
sanity_check(x1, x1, x2, x2);
|
||||
assert(x1--.value() == x2--);
|
||||
assert(x1.value() == x2);
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
test_less_than_comparable( x1, y1, x2, y2 );
|
||||
test_equality_comparable( x1, y1, x2, y2 );
|
||||
test_multipliable( x1, y1, x2, y2 );
|
||||
test_addable( x1, y1, x2, y2 );
|
||||
test_subtractable( x1, y1, x2, y2 );
|
||||
test_dividable( x1, y1, x2, y2 );
|
||||
test_modable( x1, y1, x2, y2 );
|
||||
test_xorable( x1, y1, x2, y2 );
|
||||
test_andable( x1, y1, x2, y2 );
|
||||
test_orable( x1, y1, x2, y2 );
|
||||
test_left_shiftable( x1, y1, x2, y2 );
|
||||
test_right_shiftable( x1, y1, x2, y2 );
|
||||
test_incrementable( x1, x2 );
|
||||
test_decrementable( x1, x2 );
|
||||
test_less_than_comparable(x1, y1, x2, y2);
|
||||
test_equality_comparable(x1, y1, x2, y2);
|
||||
test_multipliable(x1, y1, x2, y2);
|
||||
test_addable(x1, y1, x2, y2);
|
||||
test_subtractable(x1, y1, x2, y2);
|
||||
test_dividable(x1, y1, x2, y2);
|
||||
test_modable(x1, y1, x2, y2);
|
||||
test_xorable(x1, y1, x2, y2);
|
||||
test_andable(x1, y1, x2, y2);
|
||||
test_orable(x1, y1, x2, y2);
|
||||
test_incrementable(x1, x2);
|
||||
test_decrementable(x1, x2);
|
||||
}
|
||||
|
||||
template <class X1, class Y1, class X2, class Y2>
|
||||
void test_left(X1 x1, Y1 y1, X2 x2, Y2 y2)
|
||||
{
|
||||
test_subtractable_left( x1, y1, x2, y2 );
|
||||
test_dividable_left( x1, y1, x2, y2 );
|
||||
test_modable_left( x1, y1, x2, y2 );
|
||||
}
|
||||
|
||||
template <class Big, class Small>
|
||||
struct tester
|
||||
{
|
||||
void operator()(boost::minstd_rand& randomizer) const
|
||||
void operator()(boost::min_rand& randomizer) const
|
||||
{
|
||||
Big b1 = Big( randomizer() );
|
||||
Big b2 = Big( randomizer() );
|
||||
Small s = Small( randomizer() );
|
||||
Big b1 = Big(randomizer());
|
||||
Big b2 = Big(randomizer());
|
||||
Small s = Small(randomizer());
|
||||
|
||||
test_all( Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2 );
|
||||
test_all( Wrapped2<Big, Small>(b1), s, b1, s );
|
||||
test_all(Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2);
|
||||
test_all(Wrapped2<Big, Small>(b1), s, b1, s);
|
||||
}
|
||||
};
|
||||
|
||||
template <class Big, class Small>
|
||||
struct tester_left
|
||||
{
|
||||
void operator()(boost::minstd_rand& randomizer) const
|
||||
{
|
||||
Big b1 = Big( randomizer() );
|
||||
Small s = Small( randomizer() );
|
||||
|
||||
test_left( Wrapped6<Big, Small>(b1), s, b1, s );
|
||||
}
|
||||
};
|
||||
|
||||
// added as a regression test. We had a bug which this uncovered.
|
||||
struct Point
|
||||
: boost::addable<Point
|
||||
, boost::subtractable<Point> >
|
||||
: boost::addable<Point,
|
||||
boost::subtractable<Point> >
|
||||
{
|
||||
Point( int h, int v ) : h(h), v(v) {}
|
||||
Point() :h(0), v(0) {}
|
||||
const Point& operator+=( const Point& rhs )
|
||||
{ h += rhs.h; v += rhs.v; return *this; }
|
||||
const Point& operator-=( const Point& rhs )
|
||||
{ h -= rhs.h; v -= rhs.v; return *this; }
|
||||
const Point& operator+=( const Point& rhs ) { h += rhs.h; v += rhs.v; return *this; }
|
||||
const Point& operator-=( const Point& rhs ) { h -= rhs.h; v -= rhs.v; return *this; }
|
||||
|
||||
int h;
|
||||
int v;
|
||||
};
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
|
||||
@ -544,34 +338,22 @@ template Wrapped2<unsigned int, unsigned char>;
|
||||
template Wrapped2<unsigned long, unsigned int>;
|
||||
template Wrapped2<unsigned long, unsigned char>;
|
||||
template Wrapped2<unsigned long, unsigned long>;
|
||||
|
||||
template Wrapped6<long, int>;
|
||||
template Wrapped6<long, signed char>;
|
||||
template Wrapped6<int, signed char>;
|
||||
template Wrapped6<unsigned long, unsigned int>;
|
||||
template Wrapped6<unsigned long, unsigned char>;
|
||||
template Wrapped6<unsigned int, unsigned char>;
|
||||
#endif
|
||||
|
||||
#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) )
|
||||
#ifdef NDEBUG
|
||||
#error This program is pointless when NDEBUG disables assert()!
|
||||
#endif
|
||||
|
||||
|
||||
int
|
||||
test_main( int , char * [] )
|
||||
int main()
|
||||
{
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
// Regression test.
|
||||
Point x;
|
||||
x = x + Point(3, 4);
|
||||
x = x - Point(3, 4);
|
||||
|
||||
cout << "Created point, and operated on it." << endl;
|
||||
|
||||
for (int n = 0; n < 10000; ++n)
|
||||
{
|
||||
boost::minstd_rand r;
|
||||
boost::min_rand r;
|
||||
tester<long, int>()(r);
|
||||
tester<long, signed char>()(r);
|
||||
tester<long, long>()(r);
|
||||
@ -583,308 +365,117 @@ test_main( int , char * [] )
|
||||
tester<unsigned long, unsigned long>()(r);
|
||||
tester<unsigned int, unsigned int>()(r);
|
||||
tester<unsigned int, unsigned char>()(r);
|
||||
|
||||
tester_left<long, int>()(r);
|
||||
tester_left<long, signed char>()(r);
|
||||
tester_left<int, signed char>()(r);
|
||||
|
||||
tester_left<unsigned long, unsigned int>()(r);
|
||||
tester_left<unsigned long, unsigned char>()(r);
|
||||
tester_left<unsigned int, unsigned char>()(r);
|
||||
}
|
||||
|
||||
cout << "Did random tester loop." << endl;
|
||||
|
||||
MyInt i1(1);
|
||||
MyInt i2(2);
|
||||
MyInt i;
|
||||
|
||||
BOOST_TEST( i1.value() == 1 );
|
||||
BOOST_TEST( i2.value() == 2 );
|
||||
BOOST_TEST( i.value() == 0 );
|
||||
assert( i1.value() == 1 );
|
||||
assert( i2.value() == 2 );
|
||||
assert( i.value() == 0 );
|
||||
|
||||
cout << "Created MyInt objects.\n";
|
||||
i = i2;
|
||||
assert( i.value() == 2 );
|
||||
assert( i2 == i );
|
||||
assert( i1 != i2 );
|
||||
assert( i1 < i2 );
|
||||
assert( i1 <= i2 );
|
||||
assert( i <= i2 );
|
||||
assert( i2 > i1 );
|
||||
assert( i2 >= i1 );
|
||||
assert( i2 >= i );
|
||||
|
||||
PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) );
|
||||
|
||||
BOOST_TEST( i2 == i );
|
||||
BOOST_TEST( i1 != i2 );
|
||||
BOOST_TEST( i1 < i2 );
|
||||
BOOST_TEST( i1 <= i2 );
|
||||
BOOST_TEST( i <= i2 );
|
||||
BOOST_TEST( i2 > i1 );
|
||||
BOOST_TEST( i2 >= i1 );
|
||||
BOOST_TEST( i2 >= i );
|
||||
|
||||
PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) );
|
||||
PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) );
|
||||
PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) );
|
||||
PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) );
|
||||
PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) );
|
||||
PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) );
|
||||
PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) );
|
||||
PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) );
|
||||
PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) );
|
||||
PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) );
|
||||
PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) );
|
||||
PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) );
|
||||
|
||||
PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) );
|
||||
PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) );
|
||||
i = i1 + i2; assert( i.value() == 3 );
|
||||
i = i + i2; assert( i.value() == 5 );
|
||||
i = i - i1; assert( i.value() == 4 );
|
||||
i = i * i2; assert( i.value() == 8 );
|
||||
i = i / i2; assert( i.value() == 4 );
|
||||
i = i % (i - i1); assert( i.value() == 1 );
|
||||
i = i2 + i2; assert( i.value() == 4 );
|
||||
i = i1 | i2 | i; assert( i.value() == 7 );
|
||||
i = i & i2; assert( i.value() == 2 );
|
||||
i = i + i1; assert( i.value() == 3 );
|
||||
i = i ^ i1; assert( i.value() == 2 );
|
||||
i = (i+i1)*(i2|i1); assert( i.value() == 9 );
|
||||
|
||||
cout << "Performed tests on MyInt objects.\n";
|
||||
|
||||
MyLong j1(1);
|
||||
MyLong j2(2);
|
||||
MyLong j;
|
||||
|
||||
BOOST_TEST( j1.value() == 1 );
|
||||
BOOST_TEST( j2.value() == 2 );
|
||||
BOOST_TEST( j.value() == 0 );
|
||||
assert( j1.value() == 1 );
|
||||
assert( j2.value() == 2 );
|
||||
assert( j.value() == 0 );
|
||||
|
||||
cout << "Created MyLong objects.\n";
|
||||
|
||||
PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) );
|
||||
j = j2;
|
||||
assert( j.value() == 2 );
|
||||
|
||||
BOOST_TEST( j2 == j );
|
||||
BOOST_TEST( 2 == j );
|
||||
BOOST_TEST( j2 == 2 );
|
||||
BOOST_TEST( j == j2 );
|
||||
BOOST_TEST( j1 != j2 );
|
||||
BOOST_TEST( j1 != 2 );
|
||||
BOOST_TEST( 1 != j2 );
|
||||
BOOST_TEST( j1 < j2 );
|
||||
BOOST_TEST( 1 < j2 );
|
||||
BOOST_TEST( j1 < 2 );
|
||||
BOOST_TEST( j1 <= j2 );
|
||||
BOOST_TEST( 1 <= j2 );
|
||||
BOOST_TEST( j1 <= j );
|
||||
BOOST_TEST( j <= j2 );
|
||||
BOOST_TEST( 2 <= j2 );
|
||||
BOOST_TEST( j <= 2 );
|
||||
BOOST_TEST( j2 > j1 );
|
||||
BOOST_TEST( 2 > j1 );
|
||||
BOOST_TEST( j2 > 1 );
|
||||
BOOST_TEST( j2 >= j1 );
|
||||
BOOST_TEST( 2 >= j1 );
|
||||
BOOST_TEST( j2 >= 1 );
|
||||
BOOST_TEST( j2 >= j );
|
||||
BOOST_TEST( 2 >= j );
|
||||
BOOST_TEST( j2 >= 2 );
|
||||
assert( j2 == j );
|
||||
assert( 2 == j );
|
||||
assert( j2 == 2 );
|
||||
assert( j == j2 );
|
||||
assert( j1 != j2 );
|
||||
assert( j1 != 2 );
|
||||
assert( 1 != j2 );
|
||||
assert( j1 < j2 );
|
||||
assert( 1 < j2 );
|
||||
assert( j1 < 2 );
|
||||
assert( j1 <= j2 );
|
||||
assert( 1 <= j2 );
|
||||
assert( j1 <= j );
|
||||
assert( j <= j2 );
|
||||
assert( 2 <= j2 );
|
||||
assert( j <= 2 );
|
||||
assert( j2 > j1 );
|
||||
assert( 2 > j1 );
|
||||
assert( j2 > 1 );
|
||||
assert( j2 >= j1 );
|
||||
assert( 2 >= j1 );
|
||||
assert( j2 >= 1 );
|
||||
assert( j2 >= j );
|
||||
assert( 2 >= j );
|
||||
assert( j2 >= 2 );
|
||||
|
||||
BOOST_TEST( (j1 + 2) == 3 );
|
||||
BOOST_TEST( (1 + j2) == 3 );
|
||||
PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) );
|
||||
assert( (j1 + 2) == 3 );
|
||||
assert( (1 + j2) == 3 );
|
||||
j = j1 + j2; assert( j.value() == 3 );
|
||||
|
||||
BOOST_TEST( (j + 2) == 5 );
|
||||
BOOST_TEST( (3 + j2) == 5 );
|
||||
PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) );
|
||||
assert( (j + 2) == 5 );
|
||||
assert( (3 + j2) == 5 );
|
||||
j = j + j2; assert( j.value() == 5 );
|
||||
|
||||
BOOST_TEST( (j - 1) == 4 );
|
||||
PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) );
|
||||
assert( (j - 1) == 4 );
|
||||
j = j - j1; assert( j.value() == 4 );
|
||||
|
||||
BOOST_TEST( (j * 2) == 8 );
|
||||
BOOST_TEST( (4 * j2) == 8 );
|
||||
PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) );
|
||||
assert( (j * 2) == 8 );
|
||||
assert( (4 * j2) == 8 );
|
||||
j = j * j2; assert( j.value() == 8 );
|
||||
|
||||
BOOST_TEST( (j / 2) == 4 );
|
||||
PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) );
|
||||
assert( (j / 2) == 4 );
|
||||
j = j / j2; assert( j.value() == 4 );
|
||||
|
||||
BOOST_TEST( (j % 3) == 1 );
|
||||
PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) );
|
||||
assert( (j % 3) == 1 );
|
||||
j = j % (j - j1); assert( j.value() == 1 );
|
||||
|
||||
PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) );
|
||||
j = j2 + j2; assert( j.value() == 4 );
|
||||
|
||||
BOOST_TEST( (1 | j2 | j) == 7 );
|
||||
BOOST_TEST( (j1 | 2 | j) == 7 );
|
||||
BOOST_TEST( (j1 | j2 | 4) == 7 );
|
||||
PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) );
|
||||
assert( (1 | j2 | j) == 7 );
|
||||
assert( (j1 | 2 | j) == 7 );
|
||||
assert( (j1 | j2 | 4) == 7 );
|
||||
j = j1 | j2 | j; assert( j.value() == 7 );
|
||||
|
||||
BOOST_TEST( (7 & j2) == 2 );
|
||||
BOOST_TEST( (j & 2) == 2 );
|
||||
PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) );
|
||||
assert( (7 & j2) == 2 );
|
||||
assert( (j & 2) == 2 );
|
||||
j = j & j2; assert( j.value() == 2 );
|
||||
|
||||
PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) );
|
||||
j = j | j1; assert( j.value() == 3 );
|
||||
|
||||
BOOST_TEST( (3 ^ j1) == 2 );
|
||||
BOOST_TEST( (j ^ 1) == 2 );
|
||||
PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) );
|
||||
assert( (3 ^ j1) == 2 );
|
||||
assert( (j ^ 1) == 2 );
|
||||
j = j ^ j1; assert( j.value() == 2 );
|
||||
|
||||
PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) );
|
||||
|
||||
BOOST_TEST( (j1 << 2) == 4 );
|
||||
BOOST_TEST( (j2 << 1) == 4 );
|
||||
PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) );
|
||||
|
||||
BOOST_TEST( (j >> 2) == 1 );
|
||||
BOOST_TEST( (j2 >> 1) == 1 );
|
||||
PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) );
|
||||
j = (j+j1)*(j2|j1); assert( j.value() == 9 );
|
||||
|
||||
cout << "Performed tests on MyLong objects.\n";
|
||||
|
||||
MyChar k1(1);
|
||||
MyChar k2(2);
|
||||
MyChar k;
|
||||
|
||||
BOOST_TEST( k1.value() == 1 );
|
||||
BOOST_TEST( k2.value() == 2 );
|
||||
BOOST_TEST( k.value() == 0 );
|
||||
|
||||
cout << "Created MyChar objects.\n";
|
||||
|
||||
PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) );
|
||||
|
||||
BOOST_TEST( k2 == k );
|
||||
BOOST_TEST( k1 != k2 );
|
||||
BOOST_TEST( k1 < k2 );
|
||||
BOOST_TEST( k1 <= k2 );
|
||||
BOOST_TEST( k <= k2 );
|
||||
BOOST_TEST( k2 > k1 );
|
||||
BOOST_TEST( k2 >= k1 );
|
||||
BOOST_TEST( k2 >= k );
|
||||
|
||||
cout << "Performed tests on MyChar objects.\n";
|
||||
|
||||
MyShort l1(1);
|
||||
MyShort l2(2);
|
||||
MyShort l;
|
||||
|
||||
BOOST_TEST( l1.value() == 1 );
|
||||
BOOST_TEST( l2.value() == 2 );
|
||||
BOOST_TEST( l.value() == 0 );
|
||||
|
||||
cout << "Created MyShort objects.\n";
|
||||
|
||||
PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) );
|
||||
|
||||
BOOST_TEST( l2 == l );
|
||||
BOOST_TEST( 2 == l );
|
||||
BOOST_TEST( l2 == 2 );
|
||||
BOOST_TEST( l == l2 );
|
||||
BOOST_TEST( l1 != l2 );
|
||||
BOOST_TEST( l1 != 2 );
|
||||
BOOST_TEST( 1 != l2 );
|
||||
BOOST_TEST( l1 < l2 );
|
||||
BOOST_TEST( 1 < l2 );
|
||||
BOOST_TEST( l1 < 2 );
|
||||
BOOST_TEST( l1 <= l2 );
|
||||
BOOST_TEST( 1 <= l2 );
|
||||
BOOST_TEST( l1 <= l );
|
||||
BOOST_TEST( l <= l2 );
|
||||
BOOST_TEST( 2 <= l2 );
|
||||
BOOST_TEST( l <= 2 );
|
||||
BOOST_TEST( l2 > l1 );
|
||||
BOOST_TEST( 2 > l1 );
|
||||
BOOST_TEST( l2 > 1 );
|
||||
BOOST_TEST( l2 >= l1 );
|
||||
BOOST_TEST( 2 >= l1 );
|
||||
BOOST_TEST( l2 >= 1 );
|
||||
BOOST_TEST( l2 >= l );
|
||||
BOOST_TEST( 2 >= l );
|
||||
BOOST_TEST( l2 >= 2 );
|
||||
|
||||
cout << "Performed tests on MyShort objects.\n";
|
||||
|
||||
MyDoubleInt di1(1);
|
||||
MyDoubleInt di2(2.);
|
||||
MyDoubleInt half(0.5);
|
||||
MyDoubleInt di;
|
||||
MyDoubleInt tmp;
|
||||
|
||||
BOOST_TEST( di1.value() == 1 );
|
||||
BOOST_TEST( di2.value() == 2 );
|
||||
BOOST_TEST( di2.value() == 2 );
|
||||
BOOST_TEST( di.value() == 0 );
|
||||
|
||||
cout << "Created MyDoubleInt objects.\n";
|
||||
|
||||
PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) );
|
||||
|
||||
BOOST_TEST( di2 == di );
|
||||
BOOST_TEST( 2 == di );
|
||||
BOOST_TEST( di == 2 );
|
||||
BOOST_TEST( di1 < di2 );
|
||||
BOOST_TEST( 1 < di2 );
|
||||
BOOST_TEST( di1 <= di2 );
|
||||
BOOST_TEST( 1 <= di2 );
|
||||
BOOST_TEST( di2 > di1 );
|
||||
BOOST_TEST( di2 > 1 );
|
||||
BOOST_TEST( di2 >= di1 );
|
||||
BOOST_TEST( di2 >= 1 );
|
||||
BOOST_TEST( di1 / di2 == half );
|
||||
BOOST_TEST( di1 / 2 == half );
|
||||
BOOST_TEST( 1 / di2 == half );
|
||||
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=2) == half) );
|
||||
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=di2) == half) );
|
||||
BOOST_TEST( di1 * di2 == di2 );
|
||||
BOOST_TEST( di1 * 2 == di2 );
|
||||
BOOST_TEST( 1 * di2 == di2 );
|
||||
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=2) == di2) );
|
||||
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=di2) == di2) );
|
||||
BOOST_TEST( di2 - di1 == di1 );
|
||||
BOOST_TEST( di2 - 1 == di1 );
|
||||
BOOST_TEST( 2 - di1 == di1 );
|
||||
PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=1) == di1) );
|
||||
PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=di1) == di1) );
|
||||
BOOST_TEST( di1 + di1 == di2 );
|
||||
BOOST_TEST( di1 + 1 == di2 );
|
||||
BOOST_TEST( 1 + di1 == di2 );
|
||||
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=1) == di2) );
|
||||
PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=di1) == di2) );
|
||||
|
||||
cout << "Performed tests on MyDoubleInt objects.\n";
|
||||
|
||||
MyLongInt li1(1);
|
||||
MyLongInt li2(2);
|
||||
MyLongInt li;
|
||||
MyLongInt tmp2;
|
||||
|
||||
BOOST_TEST( li1.value() == 1 );
|
||||
BOOST_TEST( li2.value() == 2 );
|
||||
BOOST_TEST( li.value() == 0 );
|
||||
|
||||
cout << "Created MyLongInt objects.\n";
|
||||
|
||||
PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) );
|
||||
|
||||
BOOST_TEST( li2 == li );
|
||||
BOOST_TEST( 2 == li );
|
||||
BOOST_TEST( li == 2 );
|
||||
BOOST_TEST( li1 < li2 );
|
||||
BOOST_TEST( 1 < li2 );
|
||||
BOOST_TEST( li1 <= li2 );
|
||||
BOOST_TEST( 1 <= li2 );
|
||||
BOOST_TEST( li2 > li1 );
|
||||
BOOST_TEST( li2 > 1 );
|
||||
BOOST_TEST( li2 >= li1 );
|
||||
BOOST_TEST( li2 >= 1 );
|
||||
BOOST_TEST( li1 % li2 == li1 );
|
||||
BOOST_TEST( li1 % 2 == li1 );
|
||||
BOOST_TEST( 1 % li2 == li1 );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=2) == li1) );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=li2) == li1) );
|
||||
BOOST_TEST( li1 / li2 == 0 );
|
||||
BOOST_TEST( li1 / 2 == 0 );
|
||||
BOOST_TEST( 1 / li2 == 0 );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=2) == 0) );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=li2) == 0) );
|
||||
BOOST_TEST( li1 * li2 == li2 );
|
||||
BOOST_TEST( li1 * 2 == li2 );
|
||||
BOOST_TEST( 1 * li2 == li2 );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=2) == li2) );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=li2) == li2) );
|
||||
BOOST_TEST( li2 - li1 == li1 );
|
||||
BOOST_TEST( li2 - 1 == li1 );
|
||||
BOOST_TEST( 2 - li1 == li1 );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=1) == li1) );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=li1) == li1) );
|
||||
BOOST_TEST( li1 + li1 == li2 );
|
||||
BOOST_TEST( li1 + 1 == li2 );
|
||||
BOOST_TEST( 1 + li1 == li2 );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=1) == li2) );
|
||||
PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=li1) == li2) );
|
||||
|
||||
cout << "Performed tests on MyLongInt objects.\n";
|
||||
|
||||
return boost::exit_success;
|
||||
std::cout << "0 errors detected\n";
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,177 +0,0 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Permutation Iterator Adaptor Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<h1>Permutation Iterator Adaptor</h1>
|
||||
<p>Defined in header <a href="../../boost/permutation_iterator.hpp">boost/permutation_iterator.hpp</a></p>
|
||||
<p>The permutation iterator adaptor provides an iterator to a permutation of a given range.
|
||||
(<a href="http://www.cut-the-knot.com/do_you_know/permutation.html">see definition of permutation</a>).
|
||||
The adaptor takes two arguments
|
||||
<ul>
|
||||
<li>an iterator to the range V on which the <a href="http://www.cut-the-knot.com/do_you_know/permutation.html">permutation</a> will be applied</li>
|
||||
<li>the reindexing scheme that defines how the elements of V will be permuted.</li>
|
||||
</ul>
|
||||
|
||||
<p>Note that the permutation iterator is not limited to strict permutations of the given range V.
|
||||
The distance between begin and end of the reindexing iterators is allowed to be smaller compared to the
|
||||
size of the range V, in which case the permutation iterator only provides a permutation of a subrange of V.
|
||||
The indexes neither need to be unique. In this same context, it must be noted that the past the end permutation iterator is
|
||||
completely defined by means of the past-the-end iterator to the indices</p>
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <class IndexIterator>
|
||||
class permutation_iterator_policies;
|
||||
|
||||
template <class ElementIterator, class IndexIterator>
|
||||
class permutation_iterator_generator;
|
||||
|
||||
template <class ElementIterator, class IndexIterator>
|
||||
typename permutation_iterator_generator<ElementIterator, IndexIterator>::type
|
||||
make_permutation_iterator(ElementIterator& base, IndexIterator& indexing);
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<h2>The Permutation Iterator Generator Class Template</h2>
|
||||
|
||||
<p>The <code>permutation_iterator_generator</code> is a helper class whose purpose
|
||||
is to construct a permutation iterator <strong>type</strong>. This class has
|
||||
two template arguments, the first being the iterator type over the range V, the
|
||||
second being the type of the iterator over the indices.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class ElementIterator, class IndexIterator>
|
||||
class permutation_iterator_generator
|
||||
{
|
||||
public:
|
||||
typedef <a href="iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...> type; // the resulting permutation iterator type
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<table border>
|
||||
<tr>
|
||||
<th>Parameter</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><tt>ElementIterator</tt></td>
|
||||
<td>The iterator over the elements to be permuted. This type must be a model
|
||||
of <a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">RandomAccessIterator</a></td>
|
||||
</td>
|
||||
|
||||
<tr>
|
||||
<td><tt>IndexIterator</tt></td>
|
||||
<td>The iterator over the new indexing scheme. This type must at least be a model
|
||||
of <a href="http://www.sgi.com/tech/stl/ForwardIterator.html">ForwardIterator</a>.
|
||||
The <code>IndexIterator::value_type</code> must be convertible to the
|
||||
<code>ElementIterator::difference_type</code>.</td>
|
||||
</table>
|
||||
|
||||
<h3>Concept Model</h3>
|
||||
The permutation iterator is always a model of the same concept as the IndexIterator.
|
||||
|
||||
<h3>Members</h3>
|
||||
The permutation iterator implements the member functions
|
||||
and operators required for the
|
||||
<a href="http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access Iterator</a>
|
||||
concept. However, the permutation iterator can only meet the complexity guarantees
|
||||
of the same concept as the IndexIterator. Thus for instance, although the permutation
|
||||
iterator provides <code>operator+=(distance)</code>, this operation will take linear time
|
||||
in case the IndexIterator is a model of ForwardIterator instead of amortized constant time.
|
||||
|
||||
<br>
|
||||
|
||||
<h2><a name="make_generator_iterator">The Permutation Iterator Object Generator</a></h2>
|
||||
|
||||
The <code>make_permutation_iterator()</code> function provides a
|
||||
convenient way to create permutation iterator objects. The function
|
||||
saves the user the trouble of explicitly writing out the iterator
|
||||
types.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class ElementIterator, class IndexIterator >
|
||||
typename permutation_iterator_generator<ElementIterator, IndexIterator>::type
|
||||
make_permutation_iterator(ElementIterator& base, IndexIterator& indices);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h2>Example</h2>
|
||||
<blockquote>
|
||||
<pre>
|
||||
using namespace boost;
|
||||
int i = 0;
|
||||
|
||||
typedef std::vector< int > element_range_type;
|
||||
typedef std::list< int > index_type;
|
||||
|
||||
static const int element_range_size = 10;
|
||||
static const int index_size = 4;
|
||||
|
||||
element_range_type elements( element_range_size );
|
||||
for(element_range_type::iterator el_it = elements.begin() ; el_it != elements.end() ; ++el_it) *el_it = std::distance(elements.begin(), el_it);
|
||||
|
||||
index_type indices( index_size );
|
||||
for(index_type::iterator i_it = indices.begin() ; i_it != indices.end() ; ++i_it ) *i_it = element_range_size - index_size + std::distance(indices.begin(), i_it);
|
||||
std::reverse( indices.begin(), indices.end() );
|
||||
|
||||
typedef permutation_iterator_generator< element_range_type::iterator, index_type::iterator >::type permutation_type;
|
||||
permutation_type begin = make_permutation_iterator( elements.begin(), indices.begin() );
|
||||
permutation_type it = begin;
|
||||
permutation_type end = make_permutation_iterator( elements.begin(), indices.end() );
|
||||
|
||||
std::cout << "The original range is : ";
|
||||
std::copy( elements.begin(), elements.end(), std::ostream_iterator< int >( std::cout, " " ) );
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "The reindexing scheme is : ";
|
||||
std::copy( indices.begin(), indices.end(), std::ostream_iterator< int >( std::cout, " " ) );
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "The permutated range is : ";
|
||||
std::copy( begin, end, std::ostream_iterator< int >( std::cout, " " ) );
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "Elements at even indices in the permutation : ";
|
||||
it = begin;
|
||||
for(i = 0; i < index_size / 2 ; ++i, it+=2 ) std::cout << *it << " ";
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "Permutation backwards : ";
|
||||
it = begin + (index_size);
|
||||
assert( it != begin );
|
||||
for( ; it-- != begin ; ) std::cout << *it << " ";
|
||||
std::cout << "\n";
|
||||
|
||||
std::cout << "Iterate backward with stride 2 : ";
|
||||
it = begin + (index_size - 1);
|
||||
for(i = 0 ; i < index_size / 2 ; ++i, it-=2 ) std::cout << *it << " ";
|
||||
std::cout << "\n";
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<br><br><br><hr>
|
||||
Thanks: The permutation iterator is only a small addition to the superb iterator adaptors
|
||||
library of David Abrahams and Jeremy Siek.
|
||||
<br><br>
|
||||
|
||||
Copyright 2001 Toon Knapen.
|
||||
|
||||
</body>
|
||||
</html>
|
@ -371,7 +371,7 @@ Betty
|
||||
</pre>
|
||||
|
||||
<hr>
|
||||
<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>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><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"
|
||||
|
115
ref_ct_test.cpp
115
ref_ct_test.cpp
@ -1,115 +0,0 @@
|
||||
// compile-time test for "boost/ref.hpp" header content
|
||||
// see 'ref_test.cpp' for run-time part
|
||||
|
||||
#include <boost/ref.hpp>
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
namespace {
|
||||
|
||||
template< typename T, typename U >
|
||||
void ref_test(boost::reference_wrapper<U>)
|
||||
{
|
||||
typedef typename boost::reference_wrapper<U>::type type;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<U,type>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T,type>::value));
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
void assignable_test(T x)
|
||||
{
|
||||
x = x;
|
||||
}
|
||||
|
||||
template< bool R, typename T >
|
||||
void is_reference_wrapper_test(T)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(boost::is_reference_wrapper<T>::value == R);
|
||||
}
|
||||
|
||||
template< typename R, typename Ref >
|
||||
void cxx_reference_test(Ref)
|
||||
{
|
||||
BOOST_STATIC_ASSERT((boost::is_same<R,Ref>::value));
|
||||
}
|
||||
|
||||
template< typename R, typename Ref >
|
||||
void unwrap_reference_test(Ref)
|
||||
{
|
||||
typedef typename boost::unwrap_reference<Ref>::type type;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<R,type>::value));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
int i = 0;
|
||||
int& ri = i;
|
||||
|
||||
int const ci = 0;
|
||||
int const& rci = ci;
|
||||
|
||||
// 'ref/cref' functions test
|
||||
ref_test<int>(boost::ref(i));
|
||||
ref_test<int>(boost::ref(ri));
|
||||
ref_test<int const>(boost::ref(ci));
|
||||
ref_test<int const>(boost::ref(rci));
|
||||
|
||||
ref_test<int const>(boost::cref(i));
|
||||
ref_test<int const>(boost::cref(ri));
|
||||
ref_test<int const>(boost::cref(ci));
|
||||
ref_test<int const>(boost::cref(rci));
|
||||
|
||||
// test 'assignable' requirement
|
||||
assignable_test(boost::ref(i));
|
||||
assignable_test(boost::ref(ri));
|
||||
assignable_test(boost::cref(i));
|
||||
assignable_test(boost::cref(ci));
|
||||
assignable_test(boost::cref(rci));
|
||||
|
||||
// 'is_reference_wrapper' test
|
||||
is_reference_wrapper_test<true>(boost::ref(i));
|
||||
is_reference_wrapper_test<true>(boost::ref(ri));
|
||||
is_reference_wrapper_test<true>(boost::cref(i));
|
||||
is_reference_wrapper_test<true>(boost::cref(ci));
|
||||
is_reference_wrapper_test<true>(boost::cref(rci));
|
||||
|
||||
is_reference_wrapper_test<false>(i);
|
||||
is_reference_wrapper_test<false, int&>(ri);
|
||||
is_reference_wrapper_test<false>(ci);
|
||||
is_reference_wrapper_test<false, int const&>(rci);
|
||||
|
||||
// ordinary references/function template arguments deduction test
|
||||
cxx_reference_test<int>(i);
|
||||
cxx_reference_test<int>(ri);
|
||||
cxx_reference_test<int>(ci);
|
||||
cxx_reference_test<int>(rci);
|
||||
|
||||
cxx_reference_test<int&, int&>(i);
|
||||
cxx_reference_test<int&, int&>(ri);
|
||||
cxx_reference_test<int const&, int const&>(i);
|
||||
cxx_reference_test<int const&, int const&>(ri);
|
||||
cxx_reference_test<int const&, int const&>(ci);
|
||||
cxx_reference_test<int const&, int const&>(rci);
|
||||
|
||||
// 'unwrap_reference' test
|
||||
unwrap_reference_test<int>(boost::ref(i));
|
||||
unwrap_reference_test<int>(boost::ref(ri));
|
||||
unwrap_reference_test<int const>(boost::cref(i));
|
||||
unwrap_reference_test<int const>(boost::cref(ci));
|
||||
unwrap_reference_test<int const>(boost::cref(rci));
|
||||
|
||||
unwrap_reference_test<int>(i);
|
||||
unwrap_reference_test<int>(ri);
|
||||
unwrap_reference_test<int>(ci);
|
||||
unwrap_reference_test<int>(rci);
|
||||
unwrap_reference_test<int&, int&>(i);
|
||||
unwrap_reference_test<int&, int&>(ri);
|
||||
unwrap_reference_test<int const&, int const&>(i);
|
||||
unwrap_reference_test<int const&, int const&>(ri);
|
||||
unwrap_reference_test<int const&, int const&>(ci);
|
||||
unwrap_reference_test<int const&, int const&>(rci);
|
||||
|
||||
return 0;
|
||||
}
|
74
ref_test.cpp
74
ref_test.cpp
@ -1,74 +0,0 @@
|
||||
|
||||
// run-time test for "boost/ref.hpp" header content
|
||||
// see 'ref_ct_test.cpp' for compile-time part
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__ICL)
|
||||
# pragma warning(disable: 4786) // identifier truncated in debug info
|
||||
# pragma warning(disable: 4710) // function not inlined
|
||||
# pragma warning(disable: 4711) // function selected for automatic inline expansion
|
||||
# pragma warning(disable: 4514) // unreferenced inline removed
|
||||
#endif
|
||||
|
||||
#include <boost/ref.hpp>
|
||||
|
||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
|
||||
# pragma warning(push, 3)
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
#define BOOST_INCLUDE_MAIN
|
||||
#include <boost/test/test_tools.hpp>
|
||||
|
||||
namespace {
|
||||
using namespace boost;
|
||||
|
||||
template <class T>
|
||||
struct ref_wrapper
|
||||
{
|
||||
// Used to verify implicit conversion
|
||||
static T* get_pointer(T& x)
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
static T const* get_const_pointer(T const& x)
|
||||
{
|
||||
return &x;
|
||||
}
|
||||
|
||||
template <class Arg>
|
||||
static T* passthru(Arg x)
|
||||
{
|
||||
return get_pointer(x);
|
||||
}
|
||||
|
||||
template <class Arg>
|
||||
static T const* cref_passthru(Arg x)
|
||||
{
|
||||
return get_const_pointer(x);
|
||||
}
|
||||
|
||||
static void test(T x)
|
||||
{
|
||||
BOOST_TEST(passthru(ref(x)) == &x);
|
||||
BOOST_TEST(&ref(x).get() == &x);
|
||||
|
||||
BOOST_TEST(cref_passthru(cref(x)) == &x);
|
||||
BOOST_TEST(&cref(x).get() == &x);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace unnamed
|
||||
|
||||
int test_main(int, char * [])
|
||||
{
|
||||
ref_wrapper<int>::test(1);
|
||||
ref_wrapper<int const>::test(1);
|
||||
return 0;
|
||||
}
|
@ -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 -->19 Aug 2001<!--webbot bot="Timestamp" endspan i-checksum="14767" -->
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->08 Mar 2001<!--webbot bot="Timestamp" endspan i-checksum="14892" -->
|
||||
|
||||
|
||||
<p>© Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell
|
||||
|
@ -10,32 +10,23 @@
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
char letters_[] = "hello world!";
|
||||
const int N = sizeof(letters_)/sizeof(char) - 1;
|
||||
#ifdef BOOST_NO_STD_ITERATOR_TRAITS
|
||||
// Assume there won't be proper iterator traits for pointers. This
|
||||
// is just a wrapper for char* which has the right traits.
|
||||
typedef boost::iterator_adaptor<char*, boost::default_iterator_policies, char> base_iterator;
|
||||
#else
|
||||
typedef char* base_iterator;
|
||||
#endif
|
||||
base_iterator letters(letters_);
|
||||
|
||||
char letters[] = "hello world!";
|
||||
const int N = sizeof(letters)/sizeof(char) - 1;
|
||||
std::cout << "original sequence of letters:\t"
|
||||
<< letters_ << std::endl;
|
||||
<< letters << std::endl;
|
||||
|
||||
std::sort(letters, letters + N);
|
||||
|
||||
// Use reverse_iterator_generator to print a sequence
|
||||
// of letters in reverse order.
|
||||
|
||||
boost::reverse_iterator_generator<base_iterator>::type
|
||||
boost::reverse_iterator_generator<char*>::type
|
||||
reverse_letters_first(letters + N),
|
||||
reverse_letters_last(letters);
|
||||
|
||||
std::cout << "letters in descending order:\t";
|
||||
std::copy(reverse_letters_first, reverse_letters_last,
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl;
|
||||
|
||||
// Use make_reverse_iterator() to print the sequence
|
||||
@ -43,8 +34,8 @@ int main(int, char*[])
|
||||
|
||||
std::cout << "letters in ascending order:\t";
|
||||
std::copy(boost::make_reverse_iterator(reverse_letters_last),
|
||||
boost::make_reverse_iterator(reverse_letters_first),
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
boost::make_reverse_iterator(reverse_letters_first),
|
||||
std::ostream_iterator<char>(std::cout));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
|
10
tie.html
10
tie.html
@ -23,13 +23,7 @@
|
||||
<TT>tie</TT>
|
||||
</H1>
|
||||
|
||||
<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>
|
||||
<P>
|
||||
<PRE>
|
||||
template <class A, class B>
|
||||
tied<A,B> tie(A& a, B& b);
|
||||
@ -130,7 +124,7 @@ The output is:
|
||||
<TABLE>
|
||||
<TR valign=top>
|
||||
<TD nowrap>Copyright © 2000</TD><TD>
|
||||
<a HREF="../../people/jeremy_siek.htm">Jeremy Siek</a>,
|
||||
<A HREF=http://www.boost.org/people/jeremy_siek.htm>Jeremy Siek</A>,
|
||||
Univ.of Notre Dame (<A
|
||||
HREF="mailto:jsiek@lsc.nd.edu">jsiek@lsc.nd.edu</A>)<br>
|
||||
<A HREF=http://www.lsc.nd.edu/~llee1>Lie-Quan Lee</A>, Univ.of Notre Dame (<A HREF="mailto:llee1@lsc.nd.edu">llee1@lsc.nd.edu</A>)<br>
|
||||
|
@ -14,22 +14,19 @@
|
||||
//
|
||||
// 3 successfully inserted.
|
||||
// 9 was already in the set.
|
||||
// There were 2 occurrences of 4.
|
||||
// There were 2 occurances of 4.
|
||||
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <iterator> // std::distance
|
||||
// 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>
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
int
|
||||
main(int, char*[])
|
||||
{
|
||||
{
|
||||
typedef std::set<int> SetT;
|
||||
SetT::iterator i;
|
||||
SetT::iterator i, end;
|
||||
bool inserted;
|
||||
|
||||
int vals[5] = { 5, 2, 4, 9, 1 };
|
||||
@ -42,9 +39,9 @@ main(int, char*[])
|
||||
for (int k = 0; k < 2; ++k) {
|
||||
boost::tie(i,inserted) = s.insert(new_vals[k]);
|
||||
if (!inserted)
|
||||
std::cout << *i << " was already in the set." << std::endl;
|
||||
std::cout << *i << " was already in the set." << std::endl;
|
||||
else
|
||||
std::cout << *i << " successfully inserted." << std::endl;
|
||||
std::cout << *i << " successfully inserted." << std::endl;
|
||||
}
|
||||
}
|
||||
{
|
||||
@ -56,7 +53,7 @@ main(int, char*[])
|
||||
|
||||
boost::tie(i,end) = std::equal_range(vals, vals + 6, 4);
|
||||
std::cout << "There were " << std::distance(i,end)
|
||||
<< " occurrences of " << *i << "." << std::endl;
|
||||
<< " occurances of " << *i << "." << std::endl;
|
||||
// Footnote: of course one would normally just use std::count()
|
||||
// to get this information, but that would spoil the example :)
|
||||
}
|
||||
|
75
tmpw2001-paper/Makefile
Normal file
75
tmpw2001-paper/Makefile
Normal file
@ -0,0 +1,75 @@
|
||||
# -*- makefile -*-
|
||||
|
||||
DVIPS = dvips
|
||||
LATEX = pdflatex
|
||||
LATEXOUT = pdf
|
||||
RESULT = pdf
|
||||
|
||||
#LATEX = latex
|
||||
#LATEXOUT = dvi
|
||||
#RESULT = ps
|
||||
|
||||
.SUFFIXES: .tex .dvi .ps .pdf .c .lg .eps
|
||||
|
||||
.c.lg:
|
||||
lgrind -i -o $*.lg -a -lc++ $*.c
|
||||
|
||||
.eps.pdf:
|
||||
epstopdf $*.eps
|
||||
|
||||
.tex.pdf:
|
||||
@ if test ! -f $*.ind; then echo "" > $*.ind; fi
|
||||
@ $(LATEX) $*
|
||||
@ if ( grep 'Writing index file' $*.log > /dev/null ); \
|
||||
then makeindex $* ; $(LATEX) $* ; fi
|
||||
@ if ( grep 'LaTeX Warning: Label(s) may' $*.log > /dev/null ); \
|
||||
then $(LATEX) $* ; fi
|
||||
@ if ( grep 'LaTeX Warning: Citation' $*.log > /dev/null ); \
|
||||
then bibtex $* ; $(LATEX) $* ; fi
|
||||
@ if ( grep 'LaTeX Warning: Label(s) may' $*.log > /dev/null ); \
|
||||
then $(LATEX) $* ; fi
|
||||
@ if ( grep 'LaTeX Warning: Label(s) may' $*.log > /dev/null ); \
|
||||
then $(LATEX) $* ; fi
|
||||
@ if ( grep 'LaTeX Warning: Label(s) may' $*.log > /dev/null ); \
|
||||
then $(LATEX) $* ; fi
|
||||
|
||||
.dvi.ps:
|
||||
$(DVIPS) -o $*.ps $*
|
||||
|
||||
.ps.pdf:
|
||||
distill -v -maxsubsetpct 99 -subsetfonts on -pairs $*.ps $*.pdf
|
||||
|
||||
|
||||
SRCCODE =
|
||||
|
||||
|
||||
#
|
||||
# Default rule
|
||||
#
|
||||
|
||||
default: iter-adaptor.$(RESULT)
|
||||
|
||||
|
||||
#
|
||||
# LaTeX stuff
|
||||
#
|
||||
TEX = iter-adaptor.tex
|
||||
|
||||
iter-adaptor.dvi: $(TEX) $(SRCCODELG)
|
||||
iter-adaptor.ps: iter-adaptor.dvi
|
||||
iter-adaptor.pdf: $(PDFPICT) $(TEX) $(SRCCODELG)
|
||||
|
||||
dist: iter-adaptor.ps iter-adaptor.pdf
|
||||
mkdir -p iter-adaptor
|
||||
cp $(TEX) $(SRCCODELG) $(EPS) $(PS) \
|
||||
iter-adaptor.bbl iter-adaptor.ps iter-adaptor.pdf \
|
||||
iter-adaptor
|
||||
tar cvf - ./iter-adaptor | gzip > iter-adaptor.tar.gz
|
||||
|
||||
#
|
||||
# Standard rules
|
||||
#
|
||||
|
||||
clean:
|
||||
/bin/rm -f *.dvi *.o *.ps *.pdf *.log *.blg *.bbl *.aux *~ *.out *.ind
|
||||
|
36
tmpw2001-paper/defs.tex
Normal file
36
tmpw2001-paper/defs.tex
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
\usepackage{times}
|
||||
|
||||
\newif\ifpdf
|
||||
\ifx\pdfoutput\undefined
|
||||
\pdffalse
|
||||
\else
|
||||
\pdfoutput=1
|
||||
\pdftrue
|
||||
\fi
|
||||
|
||||
\ifpdf
|
||||
\usepackage[
|
||||
pdftex,
|
||||
colorlinks=true,
|
||||
linkcolor=blue,filecolor=blue,pagecolor=blue,urlcolor=blue
|
||||
]{hyperref}
|
||||
\fi
|
||||
|
||||
\ifpdf
|
||||
\newcommand{\concept}[1]{\hyperref[concept:#1]{\textsf{#1}}}
|
||||
\newcommand{\stlconcept}[1]{\href{http://www.sgi.com/tech/stl/#1.html}{\textsf{#1}}}
|
||||
\newcommand{\link}[2]{\hyperref[#1]{#2}}
|
||||
\else
|
||||
\newcommand{\concept}[1]{\textsf{#1}}
|
||||
\newcommand{\stlconcept}[1]{\textsf{#1}}
|
||||
\newcommand{\href}[2]{#2}
|
||||
\newcommand{\link}[2]{#2}
|
||||
\fi
|
||||
|
||||
\newcommand{\code}[1]{{\small \texttt{#1}}}
|
||||
|
||||
\newcommand{\Note}[1]{\marginpar{\begin{flushleft}%
|
||||
{%%\tiny %%\footnotesize
|
||||
{\bf Note:} #1}%
|
||||
\end{flushleft}}}
|
1231
tmpw2001-paper/iter-adaptor.tex
Normal file
1231
tmpw2001-paper/iter-adaptor.tex
Normal file
File diff suppressed because it is too large
Load Diff
102
tmpw2001-paper/netobjectdays.cls
Normal file
102
tmpw2001-paper/netobjectdays.cls
Normal file
@ -0,0 +1,102 @@
|
||||
% Paper Formatting according to requirements of Net.Objectdays 2000
|
||||
\LoadClass[10pt]{article}
|
||||
\pagestyle{empty}
|
||||
% ---------------------------------------------------------------------
|
||||
\textheight193mm
|
||||
\textwidth122mm
|
||||
\oddsidemargin44mm
|
||||
\hoffset-1in \voffset-1in
|
||||
\topmargin52mm
|
||||
\headsep0pt
|
||||
\headheight0pt
|
||||
% ---------------------------------------------------------------------
|
||||
\renewcommand\maketitle{\par
|
||||
\begingroup
|
||||
\renewcommand\thefootnote{\@fnsymbol\c@footnote}%
|
||||
\def\@makefnmark{\rlap{\@textsuperscript{\normalfont\@thefnmark}}}%
|
||||
\long\def\@makefntext##1{\parindent 1em\noindent
|
||||
\hb@xt@1.8em{%
|
||||
\hss\@textsuperscript{\normalfont\@thefnmark}}##1}%
|
||||
\if@twocolumn
|
||||
\ifnum \col@number=\@ne
|
||||
\@maketitle
|
||||
\else
|
||||
\twocolumn[\@maketitle]%
|
||||
\fi
|
||||
\else
|
||||
\newpage
|
||||
\global\@topnum\z@ % Prevents figures from going at top of page.
|
||||
\@maketitle
|
||||
\fi
|
||||
\thispagestyle{empty}\@thanks
|
||||
\endgroup
|
||||
\setcounter{footnote}{0}%
|
||||
\global\let\thanks\relax
|
||||
\global\let\maketitle\relax
|
||||
\global\let\@maketitle\relax
|
||||
\global\let\@thanks\@empty
|
||||
\global\let\@author\@empty
|
||||
\global\let\@date\@empty
|
||||
\global\let\@title\@empty
|
||||
\global\let\title\relax
|
||||
\global\let\author\relax
|
||||
\global\let\date\relax
|
||||
\global\let\and\relax
|
||||
}
|
||||
\date{}
|
||||
\def\@maketitle{%
|
||||
\newpage
|
||||
\null
|
||||
\vskip 2em%
|
||||
\begin{center}%
|
||||
\let \footnote \thanks
|
||||
{\Large \textbf{\@title} \par}%
|
||||
\vskip 1.5em%
|
||||
{\large
|
||||
\lineskip .5em%
|
||||
{\normalsize
|
||||
\begin{tabular}[t]{c}%
|
||||
\@author
|
||||
\end{tabular}\par}}%
|
||||
\vskip 1em%
|
||||
{\large \@date}%
|
||||
\end{center}%
|
||||
\par
|
||||
\vskip 1.5em}
|
||||
\renewcommand\section{\@startsection {section}{1}{\z@}%
|
||||
{-3.5ex \@plus -1ex \@minus -.2ex}%
|
||||
{2.3ex \@plus.2ex}%
|
||||
{\normalfont\large\bfseries}}
|
||||
\renewcommand\subsection{\@startsection{subsection}{2}{\z@}%
|
||||
{-3.25ex\@plus -1ex \@minus -.2ex}%
|
||||
{1.5ex \@plus .2ex}%
|
||||
{\normalfont\normalsize\bfseries}}
|
||||
\renewcommand\subsubsection{\@startsection{subsubsection}{3}{\z@}%
|
||||
{-3.25ex\@plus -1ex \@minus -.2ex}%
|
||||
{1.5ex \@plus .2ex}%
|
||||
{\normalfont\normalsize\bfseries}}
|
||||
\renewcommand\paragraph{\@startsection{paragraph}{4}{\z@}%
|
||||
{3.25ex \@plus1ex \@minus.2ex}%
|
||||
{-1em}%
|
||||
{\normalfont\normalsize\bfseries}}
|
||||
\renewcommand\subparagraph{\@startsection{subparagraph}{5}{\parindent}%
|
||||
{3.25ex \@plus1ex \@minus .2ex}%
|
||||
{-1em}%
|
||||
|
||||
{\normalfont\normalsize\bfseries}}
|
||||
\renewcommand{\figurename}{Fig}
|
||||
\renewcommand{\tablename}{Tab}
|
||||
\long\def\@makecaption#1#2{%
|
||||
\vskip\abovecaptionskip
|
||||
\sbox\@tempboxa{{\small\textbf{#1.} #2}}%
|
||||
\ifdim \wd\@tempboxa >\hsize
|
||||
{\small\textbf{#1.} #2}\par
|
||||
\else
|
||||
\global \@minipagefalse
|
||||
\hb@xt@\hsize{\hfil\box\@tempboxa\hfil}%
|
||||
\fi
|
||||
\vskip\belowcaptionskip}
|
||||
\renewenvironment{abstract}
|
||||
{\list{}{\leftmargin1cm\rightmargin\leftmargin}%
|
||||
\item\relax{\small \textbf{Abstract.}}}
|
||||
{\endlist}
|
124
tmpw2001-paper/refs.bib
Normal file
124
tmpw2001-paper/refs.bib
Normal file
@ -0,0 +1,124 @@
|
||||
|
||||
@TechReport{stepa.lee-1994:the.s:TR,
|
||||
author = "A. A. Stepanov and M. Lee",
|
||||
title = "{The Standard Template Library}",
|
||||
institution = "ISO Programming Language C++ Project",
|
||||
year = "1994",
|
||||
number = "X3J16/94-0095, WG21/N0482",
|
||||
month = may,
|
||||
}
|
||||
|
||||
@Book{ austern99:_gener_progr_stl,
|
||||
author = "Matthew H. Austern",
|
||||
title = "Generic Programming and the {STL}",
|
||||
publisher = "Addison-Wesley",
|
||||
year = 1999,
|
||||
series = "Professional computing series"
|
||||
}
|
||||
|
||||
@Book{koenig97:_rumin_cpp,
|
||||
author = {Andrew Koenig and Barbara Moo},
|
||||
title = {Ruminations on {C++}},
|
||||
publisher = {Addison Wesley},
|
||||
year = 1997
|
||||
}
|
||||
|
||||
@Book{iso98:_cpp_final_draft_standard,
|
||||
author = "International Organization for Standardization
|
||||
(ISO)",
|
||||
title = "ISO/IEC Final Draft International Standard 14882:
|
||||
Programming Language C++",
|
||||
year = 1998,
|
||||
address = "1 rue de Varemb\'e, Case postale 56, CH-1211
|
||||
Gen\`eve 20, Switzerland"
|
||||
}
|
||||
|
||||
@Book{alexandrescu01:_modern_cpp_design,
|
||||
author = {Andrei Alexandrescu},
|
||||
title = {Modern {C++} Design},
|
||||
publisher = {Addison Wesley},
|
||||
year = 2001
|
||||
}
|
||||
|
||||
@BOOK { Barton94,
|
||||
AUTHOR = "John Barton and Lee Nackman",
|
||||
TITLE = "Scientific and Engineering {C++}",
|
||||
PUBLISHER = "Addison-Wesley",
|
||||
YEAR = 1994
|
||||
}
|
||||
|
||||
@Book{gamma95:_design_patterns,
|
||||
author = {Erich Gamma and Richard Helm and Ralph Johnson and John Vlissides},
|
||||
title = {Design Patterns: Elements of Reusable Object-Oriented Software},
|
||||
publisher = {Addison-Welsey},
|
||||
year = 1995,
|
||||
series = {Professional Computing}
|
||||
}
|
||||
|
||||
@Book{stroustrup00:_cpp_prog_lang,
|
||||
author = {Bjarne Stroustrup},
|
||||
title = {The {C++} Programming Language},
|
||||
publisher = {Addison-Wesley},
|
||||
year = 2000,
|
||||
edition = {Special}
|
||||
}
|
||||
|
||||
@Article{alexandrescu98:_compound_iters,
|
||||
author = {Andrei Alexandrescu},
|
||||
title = {Compound iterators of {STL}},
|
||||
journal = {{C/C++} Users Journal},
|
||||
year = 1998,
|
||||
volume = 16,
|
||||
number = 10,
|
||||
pages = {79-82},
|
||||
month = October
|
||||
}
|
||||
|
||||
@Article{becker98:_smart_iteraters,
|
||||
author = {Thomas Becker},
|
||||
title = {Smart Iterators and STL},
|
||||
journal = {{C/C++} Users Journal},
|
||||
year = 1998,
|
||||
volume = 16,
|
||||
number = 9,
|
||||
month = {September}
|
||||
}
|
||||
|
||||
@InBook{siek99:_scitools,
|
||||
author = {Jeremy G. Siek and Andrew Lumsdaine},
|
||||
title = {Modern Software Tools for Scientific Computing},
|
||||
chapter = {A Modern Framework for Portable High Performance
|
||||
Numerical Linear Algebra},
|
||||
publisher = {Birkhauser},
|
||||
year = 1999,
|
||||
}
|
||||
|
||||
@TechReport{siek01:_improved_iter_cat,
|
||||
author = {Jeremy Siek},
|
||||
title = {Improved Iterator Categories and Requirements},
|
||||
institution = {ISO IEC JTC1/SC22/WG21 - C++},
|
||||
year = 2001,
|
||||
number = {N1297}
|
||||
}
|
||||
|
||||
@Book{mehlhorn99:_leda,
|
||||
author = {K. Mehlhorn and St. N\"aher},
|
||||
title = {The LEDA Platform of Combinatorial and Geometric Computing},
|
||||
publisher = {Cambridge University Press},
|
||||
year = 1999
|
||||
}
|
||||
|
||||
@Book{ knu94:sgb,
|
||||
author = {D. E. Knuth},
|
||||
title = {Stanford GraphBase: a platform for combinatorial computing},
|
||||
publisher = {ACM Press},
|
||||
year = {1994}
|
||||
}
|
||||
|
||||
@Misc{czarnecki00:_named_param,
|
||||
author = {Krzysztof Czarnecki and Ulrich Eisenecker},
|
||||
title = {Named Parameters for Configuration Generators},
|
||||
howpublished = {http://www.generative-programming.org/namedparams/},
|
||||
year = 2000
|
||||
}
|
||||
|
249
tmpw2001-paper/tmpw00.bib
Normal file
249
tmpw2001-paper/tmpw00.bib
Normal file
@ -0,0 +1,249 @@
|
||||
|
||||
|
||||
|
||||
@InProceedings{TMPW00:Eisenecker,
|
||||
AUTHOR = "Ulrich W. Eisenecker and Frank Blinn and Krzysztof Czarnecki",
|
||||
TITLE = "A Solution to the Constructor-Problem of Mixin-Based Programming in {C++}",
|
||||
BOOKTITLE = "First Workshop on {C++} Template Programming,
|
||||
Erfurt, Germany",
|
||||
MONTH = "October 10",
|
||||
YEAR = "2000",
|
||||
URL = "http://oonumerics.org/tmpw00/",
|
||||
ABSTRACT =
|
||||
"Mixin-Based Programming in C++ is a powerful programming style
|
||||
based on the parameterized inheritance idiom and the composition
|
||||
of C++ templates. Type expressions describing specific inheritance
|
||||
hierarchies can be composed either automatically using generative
|
||||
programming idioms in C++ or manually. Unfortunately, the mixin-based
|
||||
C++ programming techniques published to date do not adequately support
|
||||
optional and alternative mixin classes with constructors expecting
|
||||
varying numbers of arguments, which are common in practice. This
|
||||
is because the varying base class constructors do not provide a
|
||||
uniform interface on which the constructors of the derived classes
|
||||
could rely. This paper discusses several partial solutions to this
|
||||
problem that were proposed to date and presents a new, complete
|
||||
solution. The new solution uses generative programming techniques to
|
||||
automatically generate the appropriate constructors, and this way it
|
||||
avoids the overhead and clumsiness of instantiating composed mixin
|
||||
classes in the client code using the partial solutions. In fact,
|
||||
the new solution allows users to instantiate automatically composed
|
||||
mixin classes with the simplicity of instantiating concrete classes
|
||||
from traditional class hierarchies. Finally, the new solution does
|
||||
not suffer from the scalability problems of the partial solutions."
|
||||
}
|
||||
|
||||
|
||||
@InProceedings{TMPW00:Berti,
|
||||
AUTHOR = "Guntram Berti",
|
||||
TITLE = "Generic Components for Grid Data Structures and Algorithms with {C++}",
|
||||
BOOKTITLE = "First Workshop on {C++} Template Programming,
|
||||
Erfurt, Germany",
|
||||
MONTH = "October 10",
|
||||
YEAR = "2000",
|
||||
URL = "http://oonumerics.org/tmpw00/",
|
||||
ABSTRACT =
|
||||
"Grids are fundamental data structures for representing
|
||||
geometric structures or their subdivisions. We propose a strategy
|
||||
for decoupling algorithms working on grids from the details of
|
||||
grid representations, using a generic programming approach in C++.
|
||||
Functionality of grid data structures is captured by a small set of
|
||||
primitives, divided into combinatorial and geometric ones. Special
|
||||
attention is paid to the generic implementation of grid functions, which
|
||||
correspond to the notion of mappings from grid elements (e. g. vertices)
|
||||
to entities of a given type. Experiments indicate that the overhead
|
||||
of the generic formulation is low and can be completely eliminated in
|
||||
some cases."
|
||||
}
|
||||
|
||||
|
||||
@InProceedings{TMPW00:Veldhuizen,
|
||||
AUTHOR = "Todd L. Veldhuizen",
|
||||
TITLE = "Five compilation models for {C++} templates",
|
||||
BOOKTITLE = "First Workshop on {C++} Template Programming,
|
||||
Erfurt, Germany",
|
||||
MONTH = "October 10",
|
||||
YEAR = "2000",
|
||||
URL = "http://oonumerics.org/tmpw00/",
|
||||
ABSTRACT =
|
||||
"This paper proposes an alternate structure for C++ compilers.
|
||||
Type analysis is removed from the compiler and replaced with a
|
||||
`type system library' which is treated as source code by the
|
||||
compiler. Type computations are embedded in the intermediate
|
||||
language of the compiler, and partial evaluation is used to drive
|
||||
type analysis and template instantiation. By making simple changes to
|
||||
the behavior of the partial evaluator, a wide range of compilation
|
||||
models is achieved, each with a distinct tradeoff of compile time, code
|
||||
size, and code speed. These models range from pure dynamic typing --
|
||||
ideal for scripting C++ -- to profile-directed template instantiation.
|
||||
This approach may solve several serious problems in compiling C++:
|
||||
it achieves separate compilation of templates, allows template
|
||||
code to be distributed in binary form by deferring template instantiation
|
||||
until run time, and reduces the code bloat associated with
|
||||
templates."
|
||||
}
|
||||
|
||||
|
||||
@InProceedings{TMPW00:Baus,
|
||||
AUTHOR = "Christopher Baus and Thomas Becker",
|
||||
TITLE = "Custom Iterators for the {STL}",
|
||||
BOOKTITLE = "First Workshop on {C++} Template Programming,
|
||||
Erfurt, Germany",
|
||||
MONTH = "October 10",
|
||||
YEAR = "2000",
|
||||
URL = "http://oonumerics.org/tmpw00/",
|
||||
ABSTRACT =
|
||||
"We discuss several kinds of custom iterators for use with the STL
|
||||
that are substantially different from the iterators that come with
|
||||
the STL. We present class templates that implement these custom
|
||||
iterators in a generic manner."
|
||||
}
|
||||
|
||||
|
||||
@InProceedings{TMPW00:Weiser,
|
||||
AUTHOR = "Martin Weiser and Gary Powell",
|
||||
TITLE = "The {View Template Library}",
|
||||
BOOKTITLE = "First Workshop on {C++} Template Programming,
|
||||
Erfurt, Germany",
|
||||
MONTH = "October 10",
|
||||
YEAR = "2000",
|
||||
URL = "http://oonumerics.org/tmpw00/",
|
||||
ABSTRACT =
|
||||
"Views are container adaptors providing access to different
|
||||
on the fly generated representations of the data in the container they
|
||||
are applied to. The concept fits nicely into the framework defined by
|
||||
the STL. This paper explains design, usage, and implementation of the
|
||||
View Template Library, the currently most advanced implementation of
|
||||
the views concept."
|
||||
}
|
||||
|
||||
|
||||
@InProceedings{TMPW00:Striegnitz,
|
||||
AUTHOR = "J{\"o}rg Striegnitz and Stephen A. Smith",
|
||||
TITLE = "An Expression Template aware Lambda Function",
|
||||
BOOKTITLE = "First Workshop on {C++} Template Programming,
|
||||
Erfurt, Germany",
|
||||
MONTH = "October 10",
|
||||
YEAR = "2000",
|
||||
URL = "http://oonumerics.org/tmpw00/",
|
||||
ABSTRACT =
|
||||
"Template libraries such as the STL contain several generic algorithms
|
||||
that expect functions as arguments and thereby cause frequent use of
|
||||
function objects. User-defined function objects are awkward because
|
||||
they must be declared as a class in namespace scope before they may
|
||||
be used. In this paper, we describe a lambda function for C++, which
|
||||
allows users to define function objects on the fly, without writing class
|
||||
declarations. We show that, by using expression templates, the lambda
|
||||
function can be implemented without hurting the runtime performance of a
|
||||
program. Expression templates can also help to overcome the performance
|
||||
penalties that may arise when using expressions over user-defined
|
||||
types. Thus, we based our approach on PETE which is a framework
|
||||
that simplifies the addition of expression template functionality to
|
||||
user-defined classes."
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@InProceedings{TMPW00:McNamara,
|
||||
AUTHOR = "Brian McNamara and Yannis Smaragdakis",
|
||||
TITLE = "Static Interfaces in {C++}",
|
||||
BOOKTITLE = "First Workshop on {C++} Template Programming,
|
||||
Erfurt, Germany",
|
||||
MONTH = "October 10",
|
||||
YEAR = "2000",
|
||||
URL = "http://oonumerics.org/tmpw00/",
|
||||
ABSTRACT =
|
||||
"We present an extensible framework for defining and
|
||||
using ``static interfaces'' in C++. Static interfaces are especially
|
||||
useful as constraints on template parameters. That is, in addition to the
|
||||
usual template $class T$, template definitions can specify that T ``isa''
|
||||
Foo, for some static interface named Foo. These ``isa-constraints'' can be
|
||||
based on either inheritance (named conformance: T publicly inherits Foo),
|
||||
members (structural conformance: T has these member functions with these
|
||||
signatures), or both. The constraint mechanism imposes no space or time
|
||||
overheads at runtime; virtual functions are conspicuously absent from
|
||||
our framework.
|
||||
|
||||
We demonstrate two key utilities of static interfaces. First,
|
||||
constraints enable better error messages with template code. By applying
|
||||
static interfaces as constraints, instantiating a template with the
|
||||
wrong type is an error that can be caught at the instantiation point,
|
||||
rather than later (typically in the bowels of the implementation).
|
||||
Authors of template classes and template functions can also dispatch
|
||||
``custom error messages'' to report named constraint violations by
|
||||
clients, making debugging easier. We show examples of the improvement of
|
||||
error messages when constraints are applied to STL code.
|
||||
|
||||
Second, constraints enable automatic compile-time dispatch of different
|
||||
implementations of class or function templates based on the named
|
||||
conformance properties of the template types. For example, $Set<T>$ can be
|
||||
written to automatically choose the most efficient implementation: use a
|
||||
hashtable implementation if ``T isa Hashable'', or else a binary search
|
||||
tree if ``T isa LessThanComparable'' , or else a linked-list if merely ``T
|
||||
isa EqualityComparable''. This dispatch can be completely hidden from
|
||||
clients of Set, who just use $Set<T>$ as usual."
|
||||
}
|
||||
|
||||
|
||||
@InProceedings{TMPW00:Siek,
|
||||
AUTHOR = "Jeremy Siek and Andrew Lumsdaine",
|
||||
TITLE = "Concept Checking: Binding Parametric Polymorphism in {C++}",
|
||||
BOOKTITLE = "First Workshop on {C++} Template Programming,
|
||||
Erfurt, Germany",
|
||||
MONTH = "October 10",
|
||||
YEAR = "2000",
|
||||
URL = "http://oonumerics.org/tmpw00/",
|
||||
ABSTRACT =
|
||||
"Generic programming in C++ is characterized by the use of template
|
||||
parameters to represent abstract data types (or ``concepts'').
|
||||
However, the C++ language itself does not provide a mechanism for
|
||||
explicitly handling concepts. As a result, it can be difficult to
|
||||
insure that a concrete type meets the requirements of the concept it
|
||||
is supposed to represent. Error messages resulting from incorrect
|
||||
use of a concrete type can be particularly difficult to decipher.
|
||||
In this paper we present techniques to check parameters in generic
|
||||
C++ libraries. Our techniques use standard C++ and introduce no
|
||||
run-time overhead."
|
||||
}
|
||||
|
||||
|
||||
@InProceedings{TMPW00:Kuehl,
|
||||
AUTHOR = "Dietmar K{\"u}hl",
|
||||
TITLE = "{STL} and {OO} Don't Easily Mix",
|
||||
BOOKTITLE = "First Workshop on {C++} Template Programming,
|
||||
Erfurt, Germany",
|
||||
MONTH = "October 10",
|
||||
YEAR = "2000",
|
||||
URL = "http://oonumerics.org/tmpw00/",
|
||||
ABSTRACT =
|
||||
"The STL is a powerful tool for many kinds of processing. Unfortunately,
|
||||
using polymorphic objects with the STL seems not to work: Polymorphic
|
||||
objects stored in STL containers either get sliced (i.e. only the base
|
||||
part is copied or assigned but not the derived part) or, when storing
|
||||
pointers to them instead, are not destroyed. Applying algorithms to
|
||||
such containers often results in the wrong thing or complex predicate
|
||||
objects are needed. This article shows how to overcome at least some
|
||||
of these problems using some adaptors and also outlines a possible
|
||||
implementation of STL for better integration with polymorphic objects.
|
||||
The improved integration just acknowledges the distinction between the
|
||||
object and the entity used to maintain it."
|
||||
}
|
||||
|
||||
|
||||
@InProceedings{TMPW00:Eichelberger,
|
||||
AUTHOR = "H. Eichelberger and J. Wolff v. Gudenberg",
|
||||
TITLE = "{UML} Description of the {STL}",
|
||||
BOOKTITLE = "First Workshop on {C++} Template Programming,
|
||||
Erfurt, Germany",
|
||||
MONTH = "October 10",
|
||||
YEAR = "2000",
|
||||
URL = "http://oonumerics.org/tmpw00/eichelberger.pdf",
|
||||
ABSTRACT =
|
||||
"In this paper we show how the specification of the
|
||||
Standard Template Library STL and its implementation can be described
|
||||
by UML diagrams. We define appropriate stereotypes to
|
||||
describe STL concepts like containers, iterators, function
|
||||
objects and global algorithms. For the graphical description of the
|
||||
implementation of the STL we extend the UML metamodel."
|
||||
}
|
||||
|
@ -211,7 +211,7 @@ iterator always returns by-value.
|
||||
|
||||
|
||||
<hr>
|
||||
<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>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><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"
|
||||
|
@ -18,15 +18,15 @@ namespace boost {
|
||||
template <class Operation>
|
||||
class binder1st
|
||||
: public std::unary_function<typename Operation::second_argument_type,
|
||||
typename Operation::result_type> {
|
||||
typename Operation::result_type> {
|
||||
protected:
|
||||
Operation op;
|
||||
typename Operation::first_argument_type value;
|
||||
public:
|
||||
binder1st() { } // this had to be added!
|
||||
binder1st(const Operation& x,
|
||||
const typename Operation::first_argument_type& y)
|
||||
: op(x), value(y) {}
|
||||
const typename Operation::first_argument_type& y)
|
||||
: op(x), value(y) {}
|
||||
typename Operation::result_type
|
||||
operator()(const typename Operation::second_argument_type& x) const {
|
||||
return op(value, x);
|
||||
@ -66,8 +66,8 @@ main(int, char*[])
|
||||
std::cout << "adding 4 to each element in the array:" << std::endl;
|
||||
|
||||
std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus<int>(), 4)),
|
||||
boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
boost::make_transform_iterator(x + N, boost::bind1st(std::plus<int>(), 4)),
|
||||
std::ostream_iterator<int>(std::cout, " "));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
|
49
utility.htm
49
utility.htm
@ -16,13 +16,10 @@
|
||||
<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>
|
||||
<li>Class <a href="#Class noncopyable">noncopyable</a></li>
|
||||
<li>Function template <a href="#addressof">addressof()</a></li>
|
||||
<li>Function template <a href="tie.html">tie()</a> and supporting class tied.</li>
|
||||
</ul>
|
||||
<h2> Function templates <a name="checked_delete">checked_delete</a>() and
|
||||
@ -134,55 +131,11 @@ emphasize that it is to be used only as a base class. Dave Abrahams notes
|
||||
concern about the effect on compiler optimization of adding (even trivial inline)
|
||||
destructor declarations. He says "Probably this concern is misplaced, because
|
||||
noncopyable will be used mostly for classes which own resources and thus have non-trivial destruction semantics."</p>
|
||||
<h2><a name="addressof">Function template addressof()</a></h2>
|
||||
<p>Function <strong>addressof()</strong> returns the address of an object.</p>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <typename T> inline T* addressof(T& v);
|
||||
template <typename T> inline const T* addressof(const T& v);
|
||||
template <typename T> inline volatile T* addressof(volatile T& v);
|
||||
template <typename T> inline const volatile T* addressof(const volatile T& v);
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
|
||||
<p>C++ allows programmers to replace the unary
|
||||
<strong>operator&()</strong> class member used to get the address of
|
||||
an object. Getting the real address of an object requires ugly
|
||||
casting tricks to avoid invoking the overloaded
|
||||
<strong>operator&()</strong>. Function <strong>addressof()</strong>
|
||||
provides a wrapper around the necessary code to make it easy to get an
|
||||
object's real address.
|
||||
</p>
|
||||
|
||||
<p>The program <a href="addressof_test.cpp">addressof_test.cpp</a> can be
|
||||
used to verify that <b>addressof()</b> works as expected.</p>
|
||||
|
||||
<p>Contributed by Brad King based on ideas from discussion with Doug Gregor.</p>
|
||||
<h3>Example</h3>
|
||||
<blockquote>
|
||||
<pre>#include <boost/utility.hpp>
|
||||
|
||||
struct useless_type {};
|
||||
class nonaddressable {
|
||||
useless_type operator&() const;
|
||||
};
|
||||
|
||||
void f() {
|
||||
nonaddressable x;
|
||||
nonaddressable* xp = boost::addressof(x);
|
||||
// nonaddressable* xpe = &x; /* error */
|
||||
}</pre>
|
||||
</blockquote>
|
||||
|
||||
<h2>Class templates for the Base-from-Member Idiom</h2>
|
||||
<p>See <a href="base_from_member.html">separate documentation</a>.</p>
|
||||
<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
|
||||
-->10 September, 2001<!--webbot bot="Timestamp" endspan i-checksum="39328"
|
||||
-->22 May, 2001<!--webbot bot="Timestamp" endspan i-checksum="13960"
|
||||
-->
|
||||
</p>
|
||||
<p><EFBFBD> Copyright boost.org 1999. Permission to copy, use, modify, sell and
|
||||
|
Reference in New Issue
Block a user