From 411758cf10cf5309d4d737453648381e538002d6 Mon Sep 17 00:00:00 2001 From: nobody Date: Thu, 16 May 2002 13:26:17 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create tag 'RC_1_28_0_last_merge'. [SVN r13948] --- Assignable.html | 116 -- CopyConstructible.html | 210 --- LessThanComparable.html | 212 --- MultiPassInputIterator.html | 92 -- addressof_test.cpp | 46 - assert_test.cpp | 33 - base_from_member.html | 341 ----- base_from_member_test.cpp | 597 -------- binary_search_test.cpp | 249 ---- call_traits.htm | 764 ---------- call_traits_test.cpp | 430 ------ checked_delete_test.cpp | 31 - compressed_pair.htm | 98 -- compressed_pair_test.cpp | 401 ------ counting_iterator.htm | 325 ----- counting_iterator_example.cpp | 55 - counting_iterator_test.cpp | 269 ---- current_function_test.cpp | 32 - filter_iterator.htm | 273 ---- filter_iterator_example.cpp | 61 - fun_out_iter_example.cpp | 41 - function_output_iterator.htm | 169 --- generator_iterator.htm | 150 -- half_open_range_test.cpp | 366 ----- include/boost/assert.hpp | 52 - include/boost/call_traits.hpp | 23 - include/boost/checked_delete.hpp | 60 - include/boost/compressed_pair.hpp | 23 - include/boost/current_function.hpp | 56 - include/boost/detail/call_traits.hpp | 158 --- include/boost/detail/compressed_pair.hpp | 435 ------ include/boost/detail/ob_compressed_pair.hpp | 509 ------- include/boost/generator_iterator.hpp | 73 - include/boost/operators.hpp | 937 ------------- include/boost/ref.hpp | 162 --- include/boost/utility.hpp | 63 - include/boost/utility/addressof.hpp | 31 - include/boost/utility/base_from_member.hpp | 59 - include/boost/utility_fwd.hpp | 34 - index.html | 34 - indirect_iterator.htm | 444 ------ indirect_iterator_example.cpp | 62 - indirect_iterator_test.cpp | 151 -- iter_adaptor_fail_expected1.cpp | 27 - iter_adaptor_fail_expected2.cpp | 28 - iter_traits_gen_test.cpp | 61 - iterator_adaptor_examples.cpp | 46 - iterator_adaptor_test.cpp | 449 ------ iterator_adaptors.pdf | Bin 84856 -> 0 bytes iterator_adaptors.ppt | Bin 103936 -> 0 bytes iterator_traits_test.cpp | 215 --- iterators_test.cpp | 342 ----- noncopyable_test.cpp | 38 - numeric_traits_test.cpp | 387 ------ operators.htm | 1387 ------------------- operators_test.cpp | 890 ------------ permutation_iterator.htm | 177 --- projection_iterator.htm | 391 ------ projection_iterator_example.cpp | 96 -- ref_ct_test.cpp | 115 -- ref_test.cpp | 74 - reverse_iterator.htm | 331 ----- reverse_iterator_example.cpp | 51 - tie.html | 143 -- tie_example.cpp | 64 - transform_iterator.htm | 223 --- transform_iterator_example.cpp | 76 - transform_iterator_test.cpp | 54 - utility.htm | 193 --- 69 files changed, 14585 deletions(-) delete mode 100644 Assignable.html delete mode 100644 CopyConstructible.html delete mode 100644 LessThanComparable.html delete mode 100644 MultiPassInputIterator.html delete mode 100644 addressof_test.cpp delete mode 100644 assert_test.cpp delete mode 100644 base_from_member.html delete mode 100644 base_from_member_test.cpp delete mode 100644 binary_search_test.cpp delete mode 100644 call_traits.htm delete mode 100644 call_traits_test.cpp delete mode 100644 checked_delete_test.cpp delete mode 100644 compressed_pair.htm delete mode 100644 compressed_pair_test.cpp delete mode 100644 counting_iterator.htm delete mode 100644 counting_iterator_example.cpp delete mode 100644 counting_iterator_test.cpp delete mode 100644 current_function_test.cpp delete mode 100644 filter_iterator.htm delete mode 100644 filter_iterator_example.cpp delete mode 100644 fun_out_iter_example.cpp delete mode 100644 function_output_iterator.htm delete mode 100644 generator_iterator.htm delete mode 100644 half_open_range_test.cpp delete mode 100644 include/boost/assert.hpp delete mode 100644 include/boost/call_traits.hpp delete mode 100644 include/boost/checked_delete.hpp delete mode 100644 include/boost/compressed_pair.hpp delete mode 100644 include/boost/current_function.hpp delete mode 100644 include/boost/detail/call_traits.hpp delete mode 100644 include/boost/detail/compressed_pair.hpp delete mode 100644 include/boost/detail/ob_compressed_pair.hpp delete mode 100644 include/boost/generator_iterator.hpp delete mode 100644 include/boost/operators.hpp delete mode 100644 include/boost/ref.hpp delete mode 100644 include/boost/utility.hpp delete mode 100644 include/boost/utility/addressof.hpp delete mode 100644 include/boost/utility/base_from_member.hpp delete mode 100644 include/boost/utility_fwd.hpp delete mode 100644 index.html delete mode 100644 indirect_iterator.htm delete mode 100644 indirect_iterator_example.cpp delete mode 100644 indirect_iterator_test.cpp delete mode 100644 iter_adaptor_fail_expected1.cpp delete mode 100644 iter_adaptor_fail_expected2.cpp delete mode 100644 iter_traits_gen_test.cpp delete mode 100644 iterator_adaptor_examples.cpp delete mode 100644 iterator_adaptor_test.cpp delete mode 100644 iterator_adaptors.pdf delete mode 100644 iterator_adaptors.ppt delete mode 100644 iterator_traits_test.cpp delete mode 100644 iterators_test.cpp delete mode 100644 noncopyable_test.cpp delete mode 100644 numeric_traits_test.cpp delete mode 100644 operators.htm delete mode 100644 operators_test.cpp delete mode 100644 permutation_iterator.htm delete mode 100644 projection_iterator.htm delete mode 100644 projection_iterator_example.cpp delete mode 100644 ref_ct_test.cpp delete mode 100644 ref_test.cpp delete mode 100644 reverse_iterator.htm delete mode 100644 reverse_iterator_example.cpp delete mode 100644 tie.html delete mode 100644 tie_example.cpp delete mode 100644 transform_iterator.htm delete mode 100644 transform_iterator_example.cpp delete mode 100644 transform_iterator_test.cpp delete mode 100644 utility.htm diff --git a/Assignable.html b/Assignable.html deleted file mode 100644 index a13357d..0000000 --- a/Assignable.html +++ /dev/null @@ -1,116 +0,0 @@ - - - -Assignable - - -C++ Boost - -
-

Assignable

- -

Description

-A type is Assignable if it is possible to assign one object of the type -to another object of that type. - - -

Notation

- - - - - - - - - - - - - - - - -
-T - -is type that is a model of Assignable -
-t - -is an object of type T -
-u - -is an object of type T or possibly const T -
-

Definitions

-

Valid expressions

- - - - - - - - - - - - - - -
-Name - -Expression - -Return type - -Semantics -
-Assignment - -t = u - -T& - -t is equivalent to u -
- - - -

Models

- - - -

See also

-DefaultConstructible -and -CopyConstructible - -
-
- - -
Copyright © 2000 -Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu) -
- - - diff --git a/CopyConstructible.html b/CopyConstructible.html deleted file mode 100644 index 85ee88a..0000000 --- a/CopyConstructible.html +++ /dev/null @@ -1,210 +0,0 @@ - - - -Copy Constructible - - -C++ Boost - -
-

Copy Constructible

- -

Description

-A type is Copy Constructible if it is possible to copy objects of that -type. - -

Notation

- - - - - - - - - - - - - - - - -
-T - -is type that is a model of Copy Constructible -
-t - -is an object of type T -
-u - -is an object of type const T -
-

Definitions

-

Valid expressions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Name - -Expression - -Return type - -Semantics -
-Copy constructor - -T(t) - -T - -t is equivalent to T(t) -
-Copy constructor - -
-T(u)
-
-
-T - -u is equivalent to T(u) -
-Destructor - -
-t.~T()
-
-
-T - -  -
-Address Operator - -
-&t
-
-
-T* - -denotes the address of t -
-Address Operator - -
-&u
-
-
-T* - -denotes the address of u -
- - - -

Models

- - - -

Concept Checking Class

- -
-  template <class T>
-  struct CopyConstructibleConcept
-  {
-    void constraints() {
-      T a(b);            // require copy constructor
-      T* ptr = &a;       // require address of operator
-      const_constraints(a);
-      ignore_unused_variable_warning(ptr);
-    }
-    void const_constraints(const T& a) {
-      T c(a);            // require const copy constructor
-      const T* ptr = &a; // require const address of operator
-      ignore_unused_variable_warning(c);
-      ignore_unused_variable_warning(ptr);
-    }
-    T b;
-  };
-
- -

See also

-Default Constructible -and -Assignable - -
-
- - -
Copyright © 2000 -Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu) -
- - - diff --git a/LessThanComparable.html b/LessThanComparable.html deleted file mode 100644 index 0799962..0000000 --- a/LessThanComparable.html +++ /dev/null @@ -1,212 +0,0 @@ - - - - -LessThanComparable - - -C++ Boost - -
-

LessThanComparable

- -

Description

-A type is LessThanComparable if it is ordered: it must -be possible to compare two objects of that type using operator<, and -operator< must be a strict weak ordering relation. - - -

Refinement of

-

Associated types

-

Notation

- - - - - - - - - -
-X - -A type that is a model of LessThanComparable -
-x, y, z - -Object of type X -
-

Definitions

-Consider the relation !(x < y) && !(y < x). If this relation is -transitive (that is, if !(x < y) && !(y < x) && !(y < z) && !(z < y) -implies !(x < z) && !(z < x)), then it satisfies the mathematical -definition of an equivalence relation. In this case, operator< -is a strict weak ordering. -

-If operator< is a strict weak ordering, and if each equivalence class -has only a single element, then operator< is a total ordering. -

Valid expressions

- - - - - - - - - - - - - -
-Name - -Expression - -Type requirements - -Return type -
-Less - -x < y - -  - -Convertible to bool -
- - - -

Expression semantics

- - - - - - - - - - - - - -
-Name - -Expression - -Precondition - -Semantics - -Postcondition -
-Less - -x < y - -x and y are in the domain of < - -  -
- - -

Complexity guarantees

-

Invariants

- - - - - - - - - - - - - -
-Irreflexivity - -x < x must be false. -
-Antisymmetry - -x < y implies !(y < x) [2] -
-Transitivity - -x < y and y < z implies x < z [3] -
-

Models

- -

Notes

-

[1] -Only operator< is fundamental; the other inequality operators -are essentially syntactic sugar. -

[2] -Antisymmetry is a theorem, not an axiom: it follows from -irreflexivity and transitivity. -

[3] -Because of irreflexivity and transitivity, operator< always -satisfies the definition of a partial ordering. The definition of -a strict weak ordering is stricter, and the definition of a -total ordering is stricter still. -

See also

-EqualityComparable, StrictWeakOrdering - - - -
-
- - -
Copyright © 2000 -Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu) -
- - - diff --git a/MultiPassInputIterator.html b/MultiPassInputIterator.html deleted file mode 100644 index 6e66916..0000000 --- a/MultiPassInputIterator.html +++ /dev/null @@ -1,92 +0,0 @@ - - - -MultiPassInputIterator - -C++ Boost - -
- -

- -Multi-Pass Input Iterator -

- -This concept is a refinement of Input Iterator, -adding the requirements that the iterator can be used to make multiple -passes through a range, and that if it1 == it2 and -it1 is dereferenceable then ++it1 == ++it2. The -Multi-Pass Input Iterator is very similar to the Forward Iterator. The -only difference is that a Forward Iterator -requires the reference type to be value_type&, whereas -MultiPassInputIterator is like Input Iterator -in that the reference type merely has to be convertible to -value_type. - - -

Design Notes

- -comments by Valentin Bonnard: - -

I think that introducing Multi-Pass Input Iterator isn't the right -solution. Do you also want to define Multi-Pass Bidirectionnal Iterator -and Multi-Pass Random Access Iterator ? I don't, definitly. It only -confuses the issue. The problem lies into the existing hierarchy of -iterators, which mixes movabillity, modifiabillity and lvalue-ness, -and these are clearly independant. - -

The terms Forward, Bidirectionnal and Random Access are about -movabillity and shouldn't be used to mean anything else. In a -completly orthogonal way, iterators can be immutable, mutable, or -neither. Lvalueness of iterators is also orthogonal with -immutabillity. With these clean concepts, your Multi-Pass Input Iterator -is just called a Forward Iterator. - -

-Other translations are:
-std::Forward Iterator -> ForwardIterator & Lvalue Iterator
-std::Bidirectionnal Iterator -> Bidirectionnal Iterator & Lvalue Iterator
-std::Random Access Iterator -> Random Access Iterator & Lvalue Iterator
- -

-Note that in practice the only operation not allowed on my -Forward Iterator which is allowed on std::Forward Iterator is -&*it. I think that &* is rarely needed in generic code. - -

-reply by Jeremy Siek: - -

-The above analysis by Valentin is right on. Of course, there is -the problem with backward compatibility. The current STL implementations -are based on the old definition of Forward Iterator. The right course -of action is to get Forward Iterator, etc. changed in the C++ standard. -Once that is done we can drop Multi-Pass Input Iterator. - - -
-


- - -
Copyright © 2000 -Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu) -
- - - diff --git a/addressof_test.cpp b/addressof_test.cpp deleted file mode 100644 index 62d988c..0000000 --- a/addressof_test.cpp +++ /dev/null @@ -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 -#include - -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(px)); - - volatile nonaddressable& vx = *px; - BOOST_TEST(boost::addressof(vx) == static_cast(px)); - - const volatile nonaddressable& cvx = *px; - BOOST_TEST(boost::addressof(cvx) == static_cast(px)); - - return 0; -} diff --git a/assert_test.cpp b/assert_test.cpp deleted file mode 100644 index 5813e25..0000000 --- a/assert_test.cpp +++ /dev/null @@ -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 -#include - -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); -} diff --git a/base_from_member.html b/base_from_member.html deleted file mode 100644 index 0376130..0000000 --- a/base_from_member.html +++ /dev/null @@ -1,341 +0,0 @@ - - - -Boost: Base-from-Member Idiom Documentation - - - -

C++ BoostBase-from-Member Idiom

- -

The class template boost::base_from_member provides -a workaround for a class that needs to initialize a base class with a -member. The class template is in boost/utility/base_from_member.hpp -which is included in boost/utility.hpp. -The class template is forward declared in boost/utility_fwd.hpp.

- -

There is test/example code in base_from_member_test.cpp.

- -

Contents

- - - -

Rationale

- -

When developing a class, sometimes a base class needs to be -initialized with a member of the current class. As a naïve -example:

- -
-#include <streambuf>  // for std::streambuf
-#include <ostream>    // for std::ostream
-
-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 )
-        {}
-    //...
-};
-
- -

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.

- -

A custom base class can be made for this idiom:

- -
-#include <streambuf>  // for std::streambuf
-#include <ostream>    // for std::ostream
-
-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 )
-        {}
-    //...
-};
-
- -

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.

- -

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.

- -

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.

- -

Synopsis

- -
-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 );
-};
-
- -

The class template has a first template parameter -MemberType representing the type of the based-member. -It has a last template parameter UniqueID, that is an -int, 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 member that the derived class can use -for later base classes (or itself).

- -

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.

- -

Usage

- -

With the starting example, the fdoutbuf sub-object needs -to be encapsulated in a base class that is inheirited before -std::ostream.

- -
-#include <boost/utility/base_from_member.hpp>
-
-#include <streambuf>  // for std::streambuf
-#include <ostream>    // for std::ostream
-
-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 )
-        {}
-    //...
-};
-
- -

The base-from-member idiom is an implementation detail, so it -should not be visible to the clients (or any derived classes) of -fdostream. Due to the initialization order, the -fdoutbuf sub-object will get initialized before the -std::ostream sub-object does, making the former -sub-object safe to use in the latter sub-object's construction. Since the -fdoutbuf 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.

- -

Example

- -

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.

- -
-#include <boost/utility/base_from_member.hpp>
-
-#include <cstddef>  // for NULL
-
-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 )
-{
-    //...
-}
-
- -

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 typedefs -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 an_int boost::base_from_member<an_int, -0> :: *) instead of a pointer to the member (having a type of -an_int *). The new problem is fixed by qualifying the -sub-object with "this->," and is needed just -for pointers, and not for references or values.

- -

There are some argument conversions in the initialization. The -constructor argument for pbase0_type is converted from -double to float. The first constructor -argument for pbase2_type is converted from int -to double. The second constructor argument for -pbase3_type 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 switcher's constructor.

- -

Credits

- -

Contributors

- -
-
Ed Brey -
Suggested some interface changes. - -
Ron Klatchko (ron@crl.com) -
Invented the idiom of how to use a class member for initializing - a base class. - -
Dietmar Kuehl -
Popularized the base-from-member idiom in his - IOStream - example classes. - -
Daryle Walker -
Started the library. Contributed the test file base_from_member_test.cpp. -
- -
- -

Revised: 22 August 2001

- -

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.

- - - diff --git a/base_from_member_test.cpp b/base_from_member_test.cpp deleted file mode 100644 index 82f0d43..0000000 --- a/base_from_member_test.cpp +++ /dev/null @@ -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 // for BOOST_TEST, main - -#include // for BOOST_NO_MEMBER_TEMPLATES -#include // for boost::exit_success -#include // for boost::noncopyable - -#include // for boost::base_from_member - -#include // for std::binary_function, std::less -#include // for std::cout (std::ostream, std::endl indirectly) -#include // for std::set -#include // for std::type_info -#include // for std::pair, std::make_pair -#include // 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 -{ - 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 set_type; - - typedef std::vector error_record_type; - typedef std::vector< std::pair > 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 - , public base_class -{ - typedef boost::base_from_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 - , private boost::base_from_member - , private boost::base_from_member - , public base_class -{ - typedef boost::base_from_member pbase_type0; - typedef boost::base_from_member pbase_type1; - typedef boost::base_from_member 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(&obj), &(typeid( obj )) ); -} - -// Compare two object IDs -bool -object_id_compare::operator () -( - object_id const & a, - object_id const & b -) const -{ - std::less 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(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(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(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(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(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(this) << '.' << std::endl; - #endif -} diff --git a/binary_search_test.cpp b/binary_search_test.cpp deleted file mode 100644 index 700a887..0000000 --- a/binary_search_test.cpp +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#include // for rand(). Would use cstdlib but VC6.4 doesn't put it in std:: -#include -#include -#include - -#if defined(__SGI_STL_PORT) ? defined(__SGI_STL_OWN_IOSTREAMS) : (!defined(__GNUC__) || __GNUC__ > 2) -# define USE_SSTREAM -#endif - -#ifdef USE_SSTREAM -# include -#else -# include -#endif - -namespace { - -typedef std::vector string_vector; - -const std::size_t sequence_length = 1000; - -unsigned random_number() -{ - return static_cast(::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 -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 - 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 void sort_by_value(T&); - -template <> -void sort_by_value(std::vector& v) -{ - std::sort(v.begin(), v.end(), cmp()); -} - -template -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) && !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& result) -{ - std::vector 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& l) -{ - l.sort(cmp()); -} -# endif - -// A way to select the comparisons with/without a Compare parameter for testing. -template struct searches -{ - template - static Iterator lower_bound(Iterator start, Iterator finish, Key key, Compare cmp) - { return boost::detail::lower_bound(start, finish, key, cmp); } - - template - static Iterator upper_bound(Iterator start, Iterator finish, Key key, Compare cmp) - { return boost::detail::upper_bound(start, finish, key, cmp); } - - template - static std::pair equal_range(Iterator start, Iterator finish, Key key, Compare cmp) - { return boost::detail::equal_range(start, finish, key, cmp); } - - template - 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 -{ - template - static Iterator lower_bound(Iterator start, Iterator finish, Key key, no_compare) - { return boost::detail::lower_bound(start, finish, key); } - - template - static Iterator upper_bound(Iterator start, Iterator finish, Key key, no_compare) - { return boost::detail::upper_bound(start, finish, key); } - - template - static std::pair equal_range(Iterator start, Iterator finish, Key key, no_compare) - { return boost::detail::equal_range(start, finish, key); } - - template - static bool binary_search(Iterator start, Iterator finish, Key key, no_compare) - { return boost::detail::binary_search(start, finish, key); } -}; - -template -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::lower_bound(start, finish, key, cmp); - const const_iterator u = searches::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 - range = searches::equal_range(start, finish, key, cmp); - assert(range.first == l); - assert(range.second == u); - - bool found = searches::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 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 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; -} diff --git a/call_traits.htm b/call_traits.htm deleted file mode 100644 index 2c4f836..0000000 --- a/call_traits.htm +++ /dev/null @@ -1,764 +0,0 @@ - - - - - - -Call Traits - - - - -

Header -<boost/call_traits.hpp>

- -

All of the contents of <boost/call_traits.hpp> are -defined inside namespace boost.

- -

The template class call_traits<T> encapsulates the -"best" method to pass a parameter of some type T to or -from a function, and consists of a collection of typedefs defined -as in the table below. The purpose of call_traits is to ensure -that problems like "references to references" -never occur, and that parameters are passed in the most efficient -manner possible (see examples). In each -case if your existing practice is to use the type defined on the -left, then replace it with the call_traits defined type on the -right.

- -

Note that for compilers that do not support either partial -specialization or member templates, no benefit will occur from -using call_traits: the call_traits defined types will always be -the same as the existing practice in this case. In addition if -only member templates and not partial template specialisation is -support by the compiler (for example Visual C++ 6) then -call_traits can not be used with array types (although it can be -used to solve the reference to reference problem).

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Existing practice

-

call_traits equivalent

-

Description

-

Notes

-

T
- (return by value)

-

call_traits<T>::value_type

-
Defines a type that - represents the "value" of type T. Use this for - functions that return by value, or possibly for stored - values of type T.

2

-

T&
- (return value)

-

call_traits<T>::reference

-
Defines a type that - represents a reference to type T. Use for functions that - would normally return a T&.

1

-

const - T&
- (return value)

-

call_traits<T>::const_reference

-
Defines a type that - represents a constant reference to type T. Use for - functions that would normally return a const T&.

1

-

const - T&
- (function parameter)

-

call_traits<T>::param_type

-
Defines a type that - represents the "best" way to pass a parameter - of type T to a function.

1,3

-
- -

Notes:

- -
    -
  1. If T is already reference type, then call_traits is - defined such that references to - references do not occur (requires partial - specialization).
  2. -
  3. If T is an array type, then call_traits defines value_type - as a "constant pointer to type" rather than an - "array of type" (requires partial - specialization). Note that if you are using value_type as - a stored value then this will result in storing a "constant - pointer to an array" rather than the array itself. - This may or may not be a good thing depending upon what - you actually need (in other words take care!).
  4. -
  5. If T is a small built in type or a pointer, then param_type - is defined as T const, instead of T - const&. This can improve the ability of the - compiler to optimize loops in the body of the function if - they depend upon the passed parameter, the semantics of - the passed parameter is otherwise unchanged (requires - partial specialization).
  6. -
- -

 

- -

Copy constructibility

- -

The following table defines which call_traits types can always -be copy-constructed from which other types, those entries marked -with a '?' are true only if and only if T is copy constructible:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 

To:

-
From:

T

-

value_type

-

reference

-

const_reference

-

param_type

-
T

?

-

?

-

Y

-

Y

-

Y

-
value_type

?

-

?

-

N

-

N

-

Y

-
reference

?

-

?

-

Y

-

Y

-

Y

-
const_reference

?

-

N

-

N

-

Y

-

Y

-
param_type

?

-

?

-

N

-

N

-

Y

-
- -

 

- -

If T is an assignable type the following assignments are -possible:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 

To:

-
From:

T

-

value_type

-

reference

-

const_reference

-

param_type

-
T

Y

-

Y

-

-

-

-

-

-

-
value_type

Y

-

Y

-

-

-

-

-

-

-
reference

Y

-

Y

-

-

-

-

-

-

-
const_reference

Y

-

Y

-

-

-

-

-

-

-
param_type

Y

-

Y

-

-

-

-

-

-

-
- -

 

- -

Examples

- -

The following table shows the effect that call_traits has on -various types, the table assumes that the compiler supports -partial specialization: if it doesn't then all types behave in -the same way as the entry for "myclass", and -call_traits can not be used with reference or array types.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 

Call_traits type:

-

Original type T

-

value_type

-

reference

-

const_reference

-

param_type

-

Applies to:

-

myclass

-

myclass

-

myclass&

-

const - myclass&

-

myclass - const&

-

All user - defined types.

-

int

-

int

-

int&

-

const - int&

-

int const

-

All small - built-in types.

-

int*

-

int*

-

int*&

-

int*const&

-

int* const

-

All - pointer types.

-

int&

-

int&

-

int&

-

const - int&

-

int&

-

All - reference types.

-

const int&

-

const - int&

-

const - int&

-

const - int&

-

const - int&

-

All - constant-references.

-

int[3]

-

const int*

-

int(&)[3]

-

const int(&)[3]

-

const int* - const

-

All array - types.

-

const int[3]

-

const int*

-

const int(&)[3]

-

const int(&)[3]

-

const int* - const

-

All - constant-array types.

-
- -

 

- -

Example 1:

- -

The following class is a trivial class that stores some type T -by value (see the call_traits_test.cpp -file), the aim is to illustrate how each of the available -call_traits typedefs may be used:

- -
template <class T>
-struct contained
-{
-   // define our typedefs first, arrays are stored by value
-   // so value_type is not the same as result_type:
-   typedef typename boost::call_traits<T>::param_type       param_type;
-   typedef typename boost::call_traits<T>::reference        reference;
-   typedef typename boost::call_traits<T>::const_reference  const_reference;
-   typedef T                                                value_type;
-   typedef typename boost::call_traits<T>::value_type       result_type;
-
-   // stored value:
-   value_type v_;
-   
-   // constructors:
-   contained() {}
-   contained(param_type p) : v_(p){}
-   // return byval:
-   result_type value() { return v_; }
-   // return by_ref:
-   reference get() { return v_; }
-   const_reference const_get()const { return v_; }
-   // pass value:
-   void call(param_type p){}
-
-};
- -

Example 2 (the reference to reference -problem):

- -

Consider the definition of std::binder1st:

- -
template <class Operation> 
-class binder1st : 
-   public unary_function<typename Operation::second_argument_type, typename Operation::result_type> 
-{ 
-protected: 
-   Operation op; 
-   typename Operation::first_argument_type value; 
-public: 
-   binder1st(const Operation& x, const typename Operation::first_argument_type& y); 
-   typename Operation::result_type operator()(const typename Operation::second_argument_type& x) const; 
-}; 
- -

Now consider what happens in the relatively common case that -the functor takes its second argument as a reference, that -implies that Operation::second_argument_type is a -reference type, operator() will now end up taking a -reference to a reference as an argument, and that is not -currently legal. The solution here is to modify operator() -to use call_traits:

- -
typename Operation::result_type operator()(typename call_traits<typename Operation::second_argument_type>::param_type x) const;
- -

Now in the case that Operation::second_argument_type -is a reference type, the argument is passed as a reference, and -the no "reference to reference" occurs.

- -

Example 3 (the make_pair problem):

- -

If we pass the name of an array as one (or both) arguments to std::make_pair, -then template argument deduction deduces the passed parameter as -"const reference to array of T", this also applies to -string literals (which are really array literals). Consequently -instead of returning a pair of pointers, it tries to return a -pair of arrays, and since an array type is not copy-constructible -the code fails to compile. One solution is to explicitly cast the -arguments to make_pair to pointers, but call_traits provides a -better (i.e. automatic) solution (and one that works safely even -in generic code where the cast might do the wrong thing):

- -
template <class T1, class T2>
-std::pair<
-   typename boost::call_traits<T1>::value_type, 
-   typename boost::call_traits<T2>::value_type> 
-      make_pair(const T1& t1, const T2& t2)
-{
-   return std::pair<
-      typename boost::call_traits<T1>::value_type, 
-      typename boost::call_traits<T2>::value_type>(t1, t2);
-}
- -

Here, the deduced argument types will be automatically -degraded to pointers if the deduced types are arrays, similar -situations occur in the standard binders and adapters: in -principle in any function that "wraps" a temporary -whose type is deduced. Note that the function arguments to -make_pair are not expressed in terms of call_traits: doing so -would prevent template argument deduction from functioning.

- -

Example 4 (optimising fill):

- -

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 fill_example.cpp), -a version of std::fill is optimized in two ways: if the type -passed is a single byte built-in type then std::memset is used to -effect the fill, otherwise a conventional C++ implemention is -used, but with the passed parameter "optimized" using -call_traits:

- -
namespace detail{
-
-template <bool opt>
-struct filler
-{
-   template <typename I, typename T>
-   static void do_fill(I first, I last, typename boost::call_traits<T>::param_type val);
-   {
-      while(first != last)
-      {
-         *first = val;
-         ++first;
-      }
-   }
-};
-
-template <>
-struct filler<true>
-{
-   template <typename I, typename T>
-   static void do_fill(I first, I last, T val)
-   {
-      memset(first, val, last-first);
-   }
-};
-
-}
-
-template <class I, class T>
-inline void fill(I first, I last, const T& val)
-{
-   enum{ can_opt = boost::is_pointer<I>::value
-                   && boost::is_arithmetic<T>::value
-                   && (sizeof(T) == 1) };
-   typedef detail::filler<can_opt> filler_t;
-   filler_t::template do_fill<I,T>(first, last, val);
-}
- -

Footnote: the reason that this is "optimal" for -small built-in types is that with the value passed as "T -const" instead of "const T&" the compiler is -able to tell both that the value is constant and that it is free -of aliases. With this information the compiler is able to cache -the passed value in a register, unroll the loop, or use -explicitly parallel instructions: if any of these are supported. -Exactly how much mileage you will get from this depends upon your -compiler - we could really use some accurate benchmarking -software as part of boost for cases like this.

- -

Note that the function arguments to fill are not expressed in -terms of call_traits: doing so would prevent template argument -deduction from functioning. Instead fill acts as a "thin -wrapper" that is there to perform template argument -deduction, the compiler will optimise away the call to fill all -together, replacing it with the call to filler<>::do_fill, -which does use call_traits.

- -

Rationale

- -

The following notes are intended to briefly describe the -rational behind choices made in call_traits.

- -

All user-defined types follow "existing practice" -and need no comment.

- -

Small built-in types (what the standard calls fundamental -types [3.9.1]) differ from existing practice only in the param_type -typedef. In this case passing "T const" is compatible -with existing practice, but may improve performance in some cases -(see Example 4), in any case this should never -be any worse than existing practice.

- -

Pointers follow the same rational as small built-in types.

- -

For reference types the rational follows Example -2 - references to references are not allowed, so the -call_traits members must be defined such that these problems do -not occur. There is a proposal to modify the language such that -"a reference to a reference is a reference" (issue #106, -submitted by Bjarne Stroustrup), call_traits<T>::value_type -and call_traits<T>::param_type both provide the same effect -as that proposal, without the need for a language change (in -other words it's a workaround).

- -

For array types, a function that takes an array as an argument -will degrade the array type to a pointer type: this means that -the type of the actual parameter is different from its declared -type, something that can cause endless problems in template code -that relies on the declared type of a parameter. For example:

- -
template <class T>
-struct A
-{
-   void foo(T t);
-};
- -

In this case if we instantiate -A<int[2]> then the declared type of the parameter passed to -member function foo is int[2], but it's actual type is const int*, -if we try to use the type T within the function body, then there -is a strong likelyhood that our code will not compile:

- -
template <class T>
-void A<T>::foo(T t)
-{
-   T dup(t); // doesn't compile for case that T is an array.
-}
- -

By using call_traits the degradation from array to pointer is -explicit, and the type of the parameter is the same as it's -declared type:

- -
template <class T>
-struct A
-{
-   void foo(typename call_traits<T>::value_type t);
-};
-
-template <class T>
-void A<T>::foo(typename call_traits<T>::value_type t)
-{
-   typename call_traits<T>::value_type dup(t); // OK even if T is an array type.
-}
- -

For value_type (return by value), again only a pointer may be -returned, not a copy of the whole array, and again call_traits -makes the degradation explicit. The value_type member is useful -whenever an array must be explicitly degraded to a pointer - Example 3 provides the test case (Footnote: the -array specialisation for call_traits is the least well understood -of all the call_traits specialisations, if the given semantics -cause specific problems for you, or don't solve a particular -array-related problem, then I would be interested to hear about -it. Most people though will probably never need to use this -specialisation).

- -
- -

Revised 01 September 2000

- -

© Copyright boost.org 2000. Permission to copy, use, modify, -sell and distribute this document is granted provided this -copyright notice appears in all copies. This document is provided -"as is" without express or implied warranty, and with -no claim as to its suitability for any purpose.

- -

Based on contributions by Steve Cleary, Beman Dawes, Howard -Hinnant and John Maddock.

- -

Maintained by John -Maddock, the latest version of this file can be found at www.boost.org, and the boost -discussion list at www.yahoogroups.com/list/boost.

- -

.

- -

 

- -

 

- - diff --git a/call_traits_test.cpp b/call_traits_test.cpp deleted file mode 100644 index 52f1f40..0000000 --- a/call_traits_test.cpp +++ /dev/null @@ -1,430 +0,0 @@ - // boost::compressed_pair test program - - // (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and - // distribute this software is granted provided this copyright notice appears - // in all copies. This software is provided "as is" without express or implied - // warranty, and with no claim as to its suitability for any purpose. - -// standalone test program for -// 18 Mar 2002: -// Changed some names to prevent conflicts with some new type_traits additions. -// 03 Oct 2000: -// Enabled extra tests for VC6. - -#include -#include -#include -#include -#include -#include - -#include - -// a way prevent warnings for unused variables -template inline void unused_variable(const T&) {} - -// -// struct contained models a type that contains a type (for example std::pair) -// arrays are contained by value, and have to be treated as a special case: -// -template -struct contained -{ - // define our typedefs first, arrays are stored by value - // so value_type is not the same as result_type: - typedef typename boost::call_traits::param_type param_type; - typedef typename boost::call_traits::reference reference; - typedef typename boost::call_traits::const_reference const_reference; - typedef T value_type; - typedef typename boost::call_traits::value_type result_type; - - // stored value: - value_type v_; - - // constructors: - contained() {} - contained(param_type p) : v_(p){} - // return byval: - result_type value()const { return v_; } - // return by_ref: - reference get() { return v_; } - const_reference const_get()const { return v_; } - // pass value: - void call(param_type){} - -}; - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -struct contained -{ - typedef typename boost::call_traits::param_type param_type; - typedef typename boost::call_traits::reference reference; - typedef typename boost::call_traits::const_reference const_reference; - typedef T value_type[N]; - typedef typename boost::call_traits::value_type result_type; - - value_type v_; - - contained(param_type p) - { - std::copy(p, p+N, v_); - } - // return byval: - result_type value()const { return v_; } - // return by_ref: - reference get() { return v_; } - const_reference const_get()const { return v_; } - void call(param_type){} -}; -#endif - -template -contained::value_type> test_wrap_type(const T& t) -{ - typedef typename boost::call_traits::value_type ct; - return contained(t); -} - -namespace test{ - -template -std::pair< - typename boost::call_traits::value_type, - typename boost::call_traits::value_type> - make_pair(const T1& t1, const T2& t2) -{ - return std::pair< - typename boost::call_traits::value_type, - typename boost::call_traits::value_type>(t1, t2); -} - -} // namespace test - -using namespace std; - -// -// struct call_traits_checker: -// verifies behaviour of contained example: -// -template -struct call_traits_checker -{ - typedef typename boost::call_traits::param_type param_type; - void operator()(param_type); -}; - -template -void call_traits_checker::operator()(param_type p) -{ - T t(p); - contained c(t); - cout << "checking contained<" << typeid(T).name() << ">..." << endl; - assert(t == c.value()); - assert(t == c.get()); - assert(t == c.const_get()); -#ifndef __ICL - //cout << "typeof contained<" << typeid(T).name() << ">::v_ is: " << typeid(&contained::v_).name() << endl; - cout << "typeof contained<" << typeid(T).name() << ">::value() is: " << typeid(&contained::value).name() << endl; - cout << "typeof contained<" << typeid(T).name() << ">::get() is: " << typeid(&contained::get).name() << endl; - cout << "typeof contained<" << typeid(T).name() << ">::const_get() is: " << typeid(&contained::const_get).name() << endl; - cout << "typeof contained<" << typeid(T).name() << ">::call() is: " << typeid(&contained::call).name() << endl; - cout << endl; -#endif -} - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -struct call_traits_checker -{ - typedef typename boost::call_traits::param_type param_type; - void operator()(param_type t) - { - contained c(t); - cout << "checking contained<" << typeid(T[N]).name() << ">..." << endl; - unsigned int i = 0; - for(i = 0; i < N; ++i) - assert(t[i] == c.value()[i]); - for(i = 0; i < N; ++i) - assert(t[i] == c.get()[i]); - for(i = 0; i < N; ++i) - assert(t[i] == c.const_get()[i]); - - cout << "typeof contained<" << typeid(T[N]).name() << ">::v_ is: " << typeid(&contained::v_).name() << endl; - cout << "typeof contained<" << typeid(T[N]).name() << ">::value is: " << typeid(&contained::value).name() << endl; - cout << "typeof contained<" << typeid(T[N]).name() << ">::get is: " << typeid(&contained::get).name() << endl; - cout << "typeof contained<" << typeid(T[N]).name() << ">::const_get is: " << typeid(&contained::const_get).name() << endl; - cout << "typeof contained<" << typeid(T[N]).name() << ">::call is: " << typeid(&contained::call).name() << endl; - cout << endl; - } -}; -#endif - -// -// check_wrap: -template -void check_wrap(const W& w, const U& u) -{ - cout << "checking " << typeid(W).name() << "..." << endl; - assert(w.value() == u); -} - -// -// check_make_pair: -// verifies behaviour of "make_pair": -// -template -void check_make_pair(T c, U u, V v) -{ - cout << "checking std::pair<" << typeid(c.first).name() << ", " << typeid(c.second).name() << ">..." << endl; - assert(c.first == u); - assert(c.second == v); - cout << endl; -} - - -struct comparible_UDT -{ - int i_; - comparible_UDT() : i_(2){} - comparible_UDT(const comparible_UDT& other) : i_(other.i_){} - comparible_UDT& operator=(const comparible_UDT& other) - { - i_ = other.i_; - return *this; - } - bool operator == (const comparible_UDT& v){ return v.i_ == i_; } -}; - -int main(int argc, char *argv[ ]) -{ - call_traits_checker c1; - comparible_UDT u; - c1(u); - call_traits_checker c2; - int i = 2; - c2(i); - int* pi = &i; - int a[2] = {1,2}; -#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) && !defined(__ICL) - call_traits_checker c3; - c3(pi); - call_traits_checker c4; - c4(i); - call_traits_checker c5; - c5(i); -#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__MWERKS__) && !defined(__SUNPRO_CC) - call_traits_checker c6; - c6(a); -#endif -#endif - - check_wrap(test_wrap_type(2), 2); -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) - check_wrap(test_wrap_type(a), a); - check_make_pair(test::make_pair(a, a), a, a); -#endif - - // cv-qualifiers applied to reference types should have no effect - // declare these here for later use with is_reference and remove_reference: - typedef int& r_type; - typedef const r_type cr_type; - - type_test(comparible_UDT, boost::call_traits::value_type) - type_test(comparible_UDT&, boost::call_traits::reference) - type_test(const comparible_UDT&, boost::call_traits::const_reference) - type_test(const comparible_UDT&, boost::call_traits::param_type) - type_test(int, boost::call_traits::value_type) - type_test(int&, boost::call_traits::reference) - type_test(const int&, boost::call_traits::const_reference) - type_test(const int, boost::call_traits::param_type) - type_test(int*, boost::call_traits::value_type) - type_test(int*&, boost::call_traits::reference) - type_test(int*const&, boost::call_traits::const_reference) - type_test(int*const, boost::call_traits::param_type) -#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) - type_test(int&, boost::call_traits::value_type) - type_test(int&, boost::call_traits::reference) - type_test(const int&, boost::call_traits::const_reference) - type_test(int&, boost::call_traits::param_type) -#if !(defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1))) - type_test(int&, boost::call_traits::value_type) - type_test(int&, boost::call_traits::reference) - type_test(const int&, boost::call_traits::const_reference) - type_test(int&, boost::call_traits::param_type) -#else - std::cout << "Your compiler cannot instantiate call_traits, skipping four tests (4 errors)" << std::endl; - failures += 4; - test_count += 4; -#endif - type_test(const int&, boost::call_traits::value_type) - type_test(const int&, boost::call_traits::reference) - type_test(const int&, boost::call_traits::const_reference) - type_test(const int&, boost::call_traits::param_type) -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - type_test(const int*, boost::call_traits::value_type) - type_test(int(&)[3], boost::call_traits::reference) - type_test(const int(&)[3], boost::call_traits::const_reference) - type_test(const int*const, boost::call_traits::param_type) - type_test(const int*, boost::call_traits::value_type) - type_test(const int(&)[3], boost::call_traits::reference) - type_test(const int(&)[3], boost::call_traits::const_reference) - type_test(const int*const, boost::call_traits::param_type) - // test with abstract base class: - type_test(test_abc1, boost::call_traits::value_type) - type_test(test_abc1&, boost::call_traits::reference) - type_test(const test_abc1&, boost::call_traits::const_reference) - type_test(const test_abc1&, boost::call_traits::param_type) -#else - std::cout << "You're compiler does not support partial template specialiation, skipping 8 tests (8 errors)" << std::endl; - failures += 12; - test_count += 12; -#endif -#else - std::cout << "You're compiler does not support partial template specialiation, skipping 20 tests (20 errors)" << std::endl; - failures += 24; - test_count += 24; -#endif - // test with an incomplete type: - type_test(incomplete_type, boost::call_traits::value_type) - type_test(incomplete_type&, boost::call_traits::reference) - type_test(const incomplete_type&, boost::call_traits::const_reference) - type_test(const incomplete_type&, boost::call_traits::param_type) - - return check_result(argc, argv); -} - -// -// define call_traits tests to check that the assertions in the docs do actually work -// this is an instantiate only set of tests: -// -template -struct call_traits_test -{ - typedef ::boost::call_traits ct; - typedef typename ct::param_type param_type; - typedef typename ct::reference reference; - typedef typename ct::const_reference const_reference; - typedef typename ct::value_type value_type; - static void assert_construct(param_type val); -}; - -template -void call_traits_test::assert_construct(typename call_traits_test::param_type val) -{ - // - // this is to check that the call_traits assertions are valid: - T t(val); - value_type v(t); - reference r(t); - const_reference cr(t); - param_type p(t); - value_type v2(v); - value_type v3(r); - value_type v4(p); - reference r2(v); - reference r3(r); - const_reference cr2(v); - const_reference cr3(r); - const_reference cr4(cr); - const_reference cr5(p); - param_type p2(v); - param_type p3(r); - param_type p4(p); - - unused_variable(v2); - unused_variable(v3); - unused_variable(v4); - unused_variable(r2); - unused_variable(r3); - unused_variable(cr2); - unused_variable(cr3); - unused_variable(cr4); - unused_variable(cr5); - unused_variable(p2); - unused_variable(p3); - unused_variable(p4); -} -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -struct call_traits_test -{ - typedef ::boost::call_traits ct; - typedef typename ct::param_type param_type; - typedef typename ct::reference reference; - typedef typename ct::const_reference const_reference; - typedef typename ct::value_type value_type; - static void assert_construct(param_type val); -}; - -template -void call_traits_test::assert_construct(typename boost::call_traits::param_type val) -{ - // - // this is to check that the call_traits assertions are valid: - T t; - value_type v(t); - value_type v5(val); - reference r = t; - const_reference cr = t; - reference r2 = r; - #ifndef __BORLANDC__ - // C++ Builder buglet: - const_reference cr2 = r; - #endif - param_type p(t); - value_type v2(v); - const_reference cr3 = cr; - value_type v3(r); - value_type v4(p); - param_type p2(v); - param_type p3(r); - param_type p4(p); - - unused_variable(v2); - unused_variable(v3); - unused_variable(v4); - unused_variable(v5); -#ifndef __BORLANDC__ - unused_variable(r2); - unused_variable(cr2); -#endif - unused_variable(cr3); - unused_variable(p2); - unused_variable(p3); - unused_variable(p4); -} -#endif //BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -// -// now check call_traits assertions by instantiating call_traits_test: -template struct call_traits_test; -template struct call_traits_test; -template struct call_traits_test; -#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) -template struct call_traits_test; -template struct call_traits_test; -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) && !defined(__SUNPRO_CC) -template struct call_traits_test; -#endif -#endif - -#ifdef BOOST_MSVC -unsigned int expected_failures = 14; -#elif defined(__SUNPRO_CC) -#if(__SUNPRO_CC <= 0x520) -unsigned int expected_failures = 18; -#elif(__SUNPRO_CC < 0x530) -unsigned int expected_failures = 17; -#else -unsigned int expected_failures = 6; -#endif -#elif defined(__BORLANDC__) -unsigned int expected_failures = 2; -#elif (defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1))) -unsigned int expected_failures = 4; -#elif defined(__HP_aCC) -unsigned int expected_failures = 24; -#else -unsigned int expected_failures = 0; -#endif - diff --git a/checked_delete_test.cpp b/checked_delete_test.cpp deleted file mode 100644 index f9107c8..0000000 --- a/checked_delete_test.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// Boost checked_delete test program ---------------------------------------// - -// (C) Copyright Beman Dawes 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 -// 21 May 01 Initial version (Beman Dawes) - -#include // for checked_delete - -// This program demonstrates compiler errors when trying to delete an -// incomplete type. - -namespace -{ - class Incomplete; -} - -int main() -{ - Incomplete * p; - boost::checked_delete(p); // should cause compile time error - Incomplete ** pa; - boost::checked_array_delete(pa); // should cause compile time error - return 0; -} // main diff --git a/compressed_pair.htm b/compressed_pair.htm deleted file mode 100644 index e6f321f..0000000 --- a/compressed_pair.htm +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - -Header - - - - - -

Header -<boost/compressed_pair.hpp>

- -

All of the contents of <boost/compressed_pair.hpp> are -defined inside namespace boost.

- -

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.

- -
template <class T1, class T2>
-class compressed_pair
-{
-public:
-	typedef T1                                                 first_type;
-	typedef T2                                                 second_type;
-	typedef typename call_traits<first_type>::param_type       first_param_type;
-	typedef typename call_traits<second_type>::param_type      second_param_type;
-	typedef typename call_traits<first_type>::reference        first_reference;
-	typedef typename call_traits<second_type>::reference       second_reference;
-	typedef typename call_traits<first_type>::const_reference  first_const_reference;
-	typedef typename call_traits<second_type>::const_reference second_const_reference;
-
-	         compressed_pair() : base() {}
-	         compressed_pair(first_param_type x, second_param_type y);
-	explicit compressed_pair(first_param_type x);
-	explicit compressed_pair(second_param_type y);
-
-	compressed_pair& operator=(const compressed_pair&);
-
-	first_reference       first();
-	first_const_reference first() const;
-
-	second_reference       second();
-	second_const_reference second() const;
-
-	void swap(compressed_pair& y);
-};
- -

The two members of the pair can be accessed using the member -functions first() and second(). Note that not all member -functions can be instantiated for all template parameter types. -In particular compressed_pair can be instantiated for reference -and array types, however in these cases the range of constructors -that can be used are limited. If types T1 and T2 are the same -type, then there is only one version of the single-argument -constructor, and this constructor initialises both values in the -pair to the passed value.

- -

Note that compressed_pair can not be instantiated if either of -the template arguments is a union type, unless there is compiler -support for boost::is_union, or if boost::is_union is specialised -for the union type.

- -

Finally, a word of caution for Visual C++ 6 users: if either -argument is an empty type, then assigning to that member will -produce memory corruption, unless the empty type has a "do -nothing" assignment operator defined. This is due to a bug -in the way VC6 generates implicit assignment operators.

- -
- -

Revised 08 May 2001

- -

© Copyright boost.org 2000. Permission to copy, use, modify, -sell and distribute this document is granted provided this -copyright notice appears in all copies. This document is provided -"as is" without express or implied warranty, and with -no claim as to its suitability for any purpose.

- -

Based on contributions by Steve Cleary, Beman Dawes, Howard -Hinnant and John Maddock.

- -

Maintained by John -Maddock, the latest version of this file can be found at www.boost.org, and the boost -discussion list at www.yahoogroups.com/list/boost.

- -

 

- - diff --git a/compressed_pair_test.cpp b/compressed_pair_test.cpp deleted file mode 100644 index 25a2cb4..0000000 --- a/compressed_pair_test.cpp +++ /dev/null @@ -1,401 +0,0 @@ - // boost::compressed_pair test program - - // (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and - // distribute this software is granted provided this copyright notice appears - // in all copies. This software is provided "as is" without express or implied - // warranty, and with no claim as to its suitability for any purpose. - -// standalone test program for -// Revised 03 Oct 2000: -// Enabled tests for VC6. - -#include -#include -#include - -#include -#include -#define BOOST_INCLUDE_MAIN -#include - -using namespace boost; - -namespace boost { -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -template <> struct is_empty -{ static const bool value = true; }; -template <> struct is_empty -{ static const bool value = true; }; -template <> struct is_POD -{ static const bool value = true; }; -#else -template <> struct is_empty -{ enum{ value = true }; }; -template <> struct is_empty -{ enum{ value = true }; }; -template <> struct is_POD -{ enum{ value = true }; }; -#endif -} - -struct non_empty1 -{ - int i; - non_empty1() : i(1){} - non_empty1(int v) : i(v){} - friend bool operator==(const non_empty1& a, const non_empty1& b) - { return a.i == b.i; } -}; - -struct non_empty2 -{ - int i; - non_empty2() : i(3){} - non_empty2(int v) : i(v){} - friend bool operator==(const non_empty2& a, const non_empty2& b) - { return a.i == b.i; } -}; - -#ifdef __GNUC__ -using std::swap; -#endif - -template -struct compressed_pair_tester -{ - // define the types we need: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - // define our test proc: - static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); -}; - -template -void compressed_pair_tester::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) -{ -#ifndef __GNUC__ - // gcc 2.90 can't cope with function scope using - // declarations, and generates an internal compiler error... - using std::swap; -#endif - // default construct: - boost::compressed_pair cp1; - // first param construct: - boost::compressed_pair cp2(p1); - cp2.second() = p2; - BOOST_TEST(cp2.first() == p1); - BOOST_TEST(cp2.second() == p2); - // second param construct: - boost::compressed_pair cp3(p2); - cp3.first() = p1; - BOOST_TEST(cp3.second() == p2); - BOOST_TEST(cp3.first() == p1); - // both param construct: - boost::compressed_pair cp4(p1, p2); - BOOST_TEST(cp4.first() == p1); - BOOST_TEST(cp4.second() == p2); - boost::compressed_pair cp5(p3, p4); - BOOST_TEST(cp5.first() == p3); - BOOST_TEST(cp5.second() == p4); - // check const members: - const boost::compressed_pair& cpr1 = cp4; - BOOST_TEST(cpr1.first() == p1); - BOOST_TEST(cpr1.second() == p2); - - // copy construct: - boost::compressed_pair cp6(cp4); - BOOST_TEST(cp6.first() == p1); - BOOST_TEST(cp6.second() == p2); - // assignment: - cp1 = cp4; - BOOST_TEST(cp1.first() == p1); - BOOST_TEST(cp1.second() == p2); - cp1 = cp5; - BOOST_TEST(cp1.first() == p3); - BOOST_TEST(cp1.second() == p4); - // swap: - cp4.swap(cp5); - BOOST_TEST(cp4.first() == p3); - BOOST_TEST(cp4.second() == p4); - BOOST_TEST(cp5.first() == p1); - BOOST_TEST(cp5.second() == p2); - swap(cp4,cp5); - BOOST_TEST(cp4.first() == p1); - BOOST_TEST(cp4.second() == p2); - BOOST_TEST(cp5.first() == p3); - BOOST_TEST(cp5.second() == p4); -} - -// -// tests for case where one or both -// parameters are reference types: -// -template -struct compressed_pair_reference_tester -{ - // define the types we need: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - // define our test proc: - static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); -}; - -template -void compressed_pair_reference_tester::test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4) -{ -#ifndef __GNUC__ - // gcc 2.90 can't cope with function scope using - // declarations, and generates an internal compiler error... - using std::swap; -#endif - // both param construct: - boost::compressed_pair cp4(p1, p2); - BOOST_TEST(cp4.first() == p1); - BOOST_TEST(cp4.second() == p2); - boost::compressed_pair cp5(p3, p4); - BOOST_TEST(cp5.first() == p3); - BOOST_TEST(cp5.second() == p4); - // check const members: - const boost::compressed_pair& cpr1 = cp4; - BOOST_TEST(cpr1.first() == p1); - BOOST_TEST(cpr1.second() == p2); - - // copy construct: - boost::compressed_pair cp6(cp4); - BOOST_TEST(cp6.first() == p1); - BOOST_TEST(cp6.second() == p2); - // assignment: - // VC6 bug: - // When second() is an empty class, VC6 performs the - // assignment by doing a memcpy - even though the empty - // class is really a zero sized base class, the result - // is that the memory of first() gets trampled over. - // Similar arguments apply to the case that first() is - // an empty base class. - // Strangely the problem is dependent upon the compiler - // settings - some generate the problem others do not. - cp4.first() = p3; - cp4.second() = p4; - BOOST_TEST(cp4.first() == p3); - BOOST_TEST(cp4.second() == p4); -} -// -// supplimentary tests for case where first arg only is a reference type: -// -template -struct compressed_pair_reference1_tester -{ - // define the types we need: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - // define our test proc: - static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); -}; - -template -void compressed_pair_reference1_tester::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) -{ -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - // first param construct: - boost::compressed_pair cp2(p1); - cp2.second() = p2; - BOOST_TEST(cp2.first() == p1); - BOOST_TEST(cp2.second() == p2); -#endif -} -// -// supplimentary tests for case where second arg only is a reference type: -// -template -struct compressed_pair_reference2_tester -{ - // define the types we need: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - // define our test proc: - static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); -}; - -template -void compressed_pair_reference2_tester::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) -{ -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - // second param construct: - boost::compressed_pair cp3(p2); - cp3.first() = p1; - BOOST_TEST(cp3.second() == p2); - BOOST_TEST(cp3.first() == p1); -#endif -} - -// -// tests for where one or the other parameter is an array: -// -template -struct compressed_pair_array1_tester -{ - // define the types we need: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - // define our test proc: - static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); -}; - -template -void compressed_pair_array1_tester::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) -{ - // default construct: - boost::compressed_pair cp1; - // second param construct: - boost::compressed_pair cp3(p2); - cp3.first()[0] = p1[0]; - BOOST_TEST(cp3.second() == p2); - BOOST_TEST(cp3.first()[0] == p1[0]); - // check const members: - const boost::compressed_pair& cpr1 = cp3; - BOOST_TEST(cpr1.first()[0] == p1[0]); - BOOST_TEST(cpr1.second() == p2); - - BOOST_TEST(sizeof(T1) == sizeof(cp1.first())); -} - -template -struct compressed_pair_array2_tester -{ - // define the types we need: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - // define our test proc: - static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); -}; - -template -void compressed_pair_array2_tester::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) -{ - // default construct: - boost::compressed_pair cp1; - // first param construct: - boost::compressed_pair cp2(p1); - cp2.second()[0] = p2[0]; - BOOST_TEST(cp2.first() == p1); - BOOST_TEST(cp2.second()[0] == p2[0]); - // check const members: - const boost::compressed_pair& cpr1 = cp2; - BOOST_TEST(cpr1.first() == p1); - BOOST_TEST(cpr1.second()[0] == p2[0]); - - BOOST_TEST(sizeof(T2) == sizeof(cp1.second())); -} - -template -struct compressed_pair_array_tester -{ - // define the types we need: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - // define our test proc: - static void test(first_param_type p1, second_param_type p2, first_param_type p3, second_param_type p4); -}; - -template -void compressed_pair_array_tester::test(first_param_type p1, second_param_type p2, first_param_type, second_param_type) -{ - // default construct: - boost::compressed_pair cp1; - cp1.first()[0] = p1[0]; - cp1.second()[0] = p2[0]; - BOOST_TEST(cp1.first()[0] == p1[0]); - BOOST_TEST(cp1.second()[0] == p2[0]); - // check const members: - const boost::compressed_pair& cpr1 = cp1; - BOOST_TEST(cpr1.first()[0] == p1[0]); - BOOST_TEST(cpr1.second()[0] == p2[0]); - - BOOST_TEST(sizeof(T1) == sizeof(cp1.first())); - BOOST_TEST(sizeof(T2) == sizeof(cp1.second())); -} - -int test_main(int, char **) -{ - // declare some variables to pass to the tester: - non_empty1 ne1(2); - non_empty1 ne2(3); - non_empty2 ne3(4); - non_empty2 ne4(5); - empty_POD_UDT e1; - empty_UDT e2; - - // T1 != T2, both non-empty - compressed_pair_tester::test(ne1, ne3, ne2, ne4); - // T1 != T2, T2 empty - compressed_pair_tester::test(ne1, e1, ne2, e1); - // T1 != T2, T1 empty - compressed_pair_tester::test(e1, ne3, e1, ne4); - // T1 != T2, both empty - compressed_pair_tester::test(e1, e2, e1, e2); - // T1 == T2, both non-empty - compressed_pair_tester::test(ne1, ne1, ne2, ne2); - // T1 == T2, both empty - compressed_pair_tester::test(e2, e2, e2, e2); - - - // test references: - - // T1 != T2, both non-empty - compressed_pair_reference_tester::test(ne1, ne3, ne2, ne4); - compressed_pair_reference_tester::test(ne1, ne3, ne2, ne4); - compressed_pair_reference1_tester::test(ne1, ne3, ne2, ne4); - compressed_pair_reference2_tester::test(ne1, ne3, ne2, ne4); - // T1 != T2, T2 empty - compressed_pair_reference_tester::test(ne1, e1, ne2, e1); - compressed_pair_reference1_tester::test(ne1, e1, ne2, e1); - // T1 != T2, T1 empty - compressed_pair_reference_tester::test(e1, ne3, e1, ne4); - compressed_pair_reference2_tester::test(e1, ne3, e1, ne4); - // T1 == T2, both non-empty - compressed_pair_reference_tester::test(ne1, ne1, ne2, ne2); - - // tests arrays: - non_empty1 nea1[2]; - non_empty1 nea2[2]; - non_empty2 nea3[2]; - non_empty2 nea4[2]; - nea1[0] = non_empty1(5); - nea2[0] = non_empty1(6); - nea3[0] = non_empty2(7); - nea4[0] = non_empty2(8); - - // T1 != T2, both non-empty - compressed_pair_array1_tester::test(nea1, ne3, nea2, ne4); - compressed_pair_array2_tester::test(ne1, nea3, ne2, nea4); - compressed_pair_array_tester::test(nea1, nea3, nea2, nea4); - // T1 != T2, T2 empty - compressed_pair_array1_tester::test(nea1, e1, nea2, e1); - // T1 != T2, T1 empty - compressed_pair_array2_tester::test(e1, nea3, e1, nea4); - // T1 == T2, both non-empty - compressed_pair_array_tester::test(nea1, nea1, nea2, nea2); - return 0; -} - - -unsigned int expected_failures = 0; - - - - - diff --git a/counting_iterator.htm b/counting_iterator.htm deleted file mode 100644 index 0f6cb64..0000000 --- a/counting_iterator.htm +++ /dev/null @@ -1,325 +0,0 @@ - - - - - - -Counting Iterator Adaptor Documentation - - - - -c++boost.gif (8819 bytes) - -

Counting Iterator Adaptor

- -Defined in header -boost/counting_iterator.hpp - -

-How would you fill up a vector with the numbers zero -through one hundred using std::copy()? The -only iterator operation missing from builtin integer types is an -operator*() that returns the current -value of the integer. The counting iterator adaptor adds this crucial piece of -functionality to whatever type it wraps. One can use the -counting iterator adaptor not only with integer types, but with any -type that is Incrementable (see type requirements below). The -following pseudo-code shows the general idea of how the -counting iterator is implemented. -

- -
-  // inside a hypothetical counting_iterator class...
-  typedef Incrementable value_type;
-  value_type counting_iterator::operator*() const {
-    return this->base; // no dereference!
-  }
-
- -All of the other operators of the counting iterator behave in the same -fashion as the Incrementable base type. - -

Synopsis

- -
-namespace boost {
-  template <class Incrementable>
-  struct counting_iterator_traits;
-
-  template <class Incrementable>
-  struct counting_iterator_generator;
-
-  template <class Incrementable>
-  typename counting_iterator_generator<Incrementable>::type
-  make_counting_iterator(Incrementable x);
-}
-
- -
- -

The Counting Iterator Type -Generator

- -The class template counting_iterator_generator<Incrementable> is a type generator for counting iterators. - -
-template <class Incrementable>
-class counting_iterator_generator
-{
-public:
-    typedef iterator_adaptor<...> type;
-};
-
- -

Example

- -In this example we use the counting iterator generator to create a -counting iterator, and count from zero to four. - -
-#include <boost/config.hpp>
-#include <iostream>
-#include <boost/counting_iterator.hpp>
-
-int main(int, char*[])
-{
-  // Example of using counting_iterator_generator
-  std::cout << "counting from 0 to 4:" << std::endl;
-  boost::counting_iterator_generator<int>::type first(0), last(4);
-  std::copy(first, last, std::ostream_iterator<int>(std::cout, " "));
-  std::cout << std::endl;
-
-  // to be continued...
-
-The output from this part is: -
-counting from 0 to 4:
-0 1 2 3 
-
- -

Template Parameters

- - - - - - - - - - - -
ParameterDescription
IncrementableThe type being wrapped by the adaptor.
- -

Model of

- -If the Incrementable type has all of the functionality of a -Random -Access Iterator except the operator*(), then the counting -iterator will be a model of Random -Access Iterator. If the Incrementable type has less -functionality, then the counting iterator will have correspondingly -less functionality. - -

Type Requirements

- -The Incrementable type must be Default -Constructible, Copy -Constructible, and Assignable. -Also, the Incrementable type must provide access to an -associated difference_type and iterator_category -through the counting_iterator_traits -class. - -

-Furthermore, if you wish to create a counting iterator that is a Forward -Iterator, then the following expressions must be valid: -

-Incrementable i, j;
-++i         // pre-increment
-i == j      // operator equal
-
-If you wish to create a counting iterator that is a -Bidirectional Iterator, then pre-decrement is also required: -
---i
-
-If you wish to create a counting iterator that is a Random -Access Iterator, then these additional expressions are also required: -
-counting_iterator_traits<Incrementable>::difference_type n;
-i += n
-n = i - j
-i < j
-
- - - -

Members

- -The counting iterator type implements the member functions and -operators required of the Random -Access Iterator concept. In addition it has the following -constructor: - -
-counting_iterator_generator::type(const Incrementable& i)
-
- -

-


-

- - -

The Counting Iterator Object Generator

- -
-template <class Incrementable>
-typename counting_iterator_generator<Incrementable>::type
-make_counting_iterator(Incrementable base);
-
- -An object -generator function that provides a convenient way to create counting -iterators.

- - - -

Example

- -In this example we count from negative five to positive five, this -time using the make_counting_iterator() function to save some -typing. - -
-  // continuing from previous example...
-
-  std::cout << "counting from -5 to 4:" << std::endl;
-  std::copy(boost::make_counting_iterator(-5),
-	    boost::make_counting_iterator(5),
-	    std::ostream_iterator<int>(std::cout, " "));
-  std::cout << std::endl;
-
-  // to be continued...
-
-The output from this part is: -
-counting from -5 to 4:
--5 -4 -3 -2 -1 0 1 2 3 4 
-
- -In the next example we create an array of numbers, and then create a -second array of pointers, where each pointer is the address of a -number in the first array. The counting iterator makes it easy to do -this since dereferencing a counting iterator that is wrapping an -iterator over the array of numbers just returns a pointer to the -current location in the array. We then use the indirect iterator adaptor to print -out the number in the array by accessing the numbers through the array -of pointers. - -
-  // continuing from previous example...
-
-  const int N = 7;
-  std::vector<int> numbers;
-  // Fill "numbers" array with [0,N)
-  std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N),
-	    std::back_inserter(numbers));
-
-  std::vector<std::vector<int>::iterator> pointers;
-
-  // Use counting iterator to fill in the array of pointers.
-  std::copy(boost::make_counting_iterator(numbers.begin()),
-	    boost::make_counting_iterator(numbers.end()),
-	    std::back_inserter(pointers));
-
-  // Use indirect iterator to print out numbers by accessing
-  // them through the array of pointers.
-  std::cout << "indirectly printing out the numbers from 0 to " 
-	    << N << std::endl;
-  std::copy(boost::make_indirect_iterator(pointers.begin()),
-	    boost::make_indirect_iterator(pointers.end()),
-	    std::ostream_iterator<int>(std::cout, " "));
-  std::cout << std::endl;
-
-The output is: -
-indirectly printing out the numbers from 0 to 7
-0 1 2 3 4 5 6 
-
- -
- -

Counting Iterator Traits

- -The counting iterator adaptor needs to determine the appropriate -difference_type and iterator_category to use based on the -Incrementable type supplied by the user. The -counting_iterator_traits class provides these types. If the -Incrementable type is an integral type or an iterator, these types -will be correctly deduced by the counting_iterator_traits provided by -the library. Otherwise, the user must specialize -counting_iterator_traits for her type or add nested typedefs to -her type to fulfill the needs of - -std::iterator_traits. - -

The following pseudocode describes how the counting_iterator_traits are determined: - -

-template <class Incrementable>
-struct counting_iterator_traits
-{
-  if (numeric_limits<Incrementable>::is_specialized) {
-    if (!numeric_limits<Incrementable>::is_integer)
-       COMPILE_TIME_ERROR;
-
-    if (!numeric_limits<Incrementable>::is_bounded
-        && numeric_limits<Incrementable>::is_signed) {
-        typedef Incrementable difference_type;
-    }
-    else if (numeric_limits<Incrementable>::is_integral) {
-        typedef next-larger-signed-type-or-intmax_t difference_type;
-    }
-    typedef std::random_access_iterator_tag iterator_category;   
-  } else {
-    typedef std::iterator_traits<Incrementable>::difference_type difference_type;
-    typedef std::iterator_traits<Incrementable>::iterator_category iterator_category;
-  }
-};
-
- -

The italicized sections above are implementation details, but it is important -to know that the difference_type for integral types is selected so that -it can always represent the difference between two values if such a built-in -integer exists. On platforms with a working std::numeric_limits -implementation, the difference_type for any variable-length signed -integer type T is T itself. - -


-

Revised 19 Aug 2001

-

© Copyright Jeremy Siek 2000. Permission to copy, use, -modify, sell and distribute this document is granted provided this copyright -notice appears in all copies. This document is provided "as is" -without express or implied warranty, and with no claim as to its suitability for -any purpose.

- - - - - - - diff --git a/counting_iterator_example.cpp b/counting_iterator_example.cpp deleted file mode 100644 index 3817069..0000000 --- a/counting_iterator_example.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - - -#include -#include -#include -#include -#include -#include - -int main(int, char*[]) -{ - // Example of using counting_iterator_generator - std::cout << "counting from 0 to 4:" << std::endl; - boost::counting_iterator_generator::type first(0), last(4); - std::copy(first, last, std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; - - // Example of using make_counting_iterator() - std::cout << "counting from -5 to 4:" << std::endl; - std::copy(boost::make_counting_iterator(-5), - boost::make_counting_iterator(5), - std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; - - // Example of using counting iterator to create an array of pointers. - const int N = 7; - std::vector numbers; - // Fill "numbers" array with [0,N) - std::copy(boost::make_counting_iterator(0), boost::make_counting_iterator(N), - std::back_inserter(numbers)); - - std::vector::iterator> pointers; - - // VC6 gets an internal compiler error on this -#if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200) - // Use counting iterator to fill in the array of pointers. - std::copy(boost::make_counting_iterator(numbers.begin()), - boost::make_counting_iterator(numbers.end()), - std::back_inserter(pointers)); - - // Use indirect iterator to print out numbers by accessing - // them through the array of pointers. - std::cout << "indirectly printing out the numbers from 0 to " - << N << std::endl; - std::copy(boost::make_indirect_iterator(pointers.begin()), - boost::make_indirect_iterator(pointers.end()), - std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; -#endif - return 0; -} diff --git a/counting_iterator_test.cpp b/counting_iterator_test.cpp deleted file mode 100644 index 5aa6c53..0000000 --- a/counting_iterator_test.cpp +++ /dev/null @@ -1,269 +0,0 @@ -// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears in -// all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// See http://www.boost.org for most recent version including documentation. -// -// Revision History -// 16 Feb 2001 Added a missing const. Made the tests run (somewhat) with -// plain MSVC again. (David Abrahams) -// 11 Feb 2001 #if 0'd out use of counting_iterator on non-numeric types in -// MSVC without STLport, so that the other tests may proceed -// (David Abrahams) -// 04 Feb 2001 Added use of iterator_tests.hpp (David Abrahams) -// 28 Jan 2001 Removed not_an_iterator detritus (David Abrahams) -// 24 Jan 2001 Initial revision (David Abrahams) - -#include -#ifdef BOOST_MSVC -# pragma warning(disable:4786) // identifier truncated in debug info -#endif - -#include -#include -#include -#include -#include -#include -#include -#ifndef __BORLANDC__ -# include -#endif -#include -#include -#include -#ifndef BOOST_NO_LIMITS -# include -#endif -#ifndef BOOST_NO_SLIST -# include -#endif - -template struct is_numeric -{ - enum { value = -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - std::numeric_limits::is_specialized -#else - // Causes warnings with GCC, but how else can I detect numeric types at - // compile-time? - (boost::is_convertible::value && - boost::is_convertible::value) -#endif - }; -}; - -// Special tests for RandomAccess CountingIterators. -template -void category_test( - CountingIterator start, - CountingIterator finish, - std::random_access_iterator_tag) -{ - typedef typename - boost::detail::iterator_traits::difference_type - difference_type; - difference_type distance = boost::detail::distance(start, finish); - - // Pick a random position internal to the range - difference_type offset = (unsigned)rand() % distance; - assert(offset >= 0); - CountingIterator internal = start; - std::advance(internal, offset); - - // Try some binary searches on the range to show that it's ordered - assert(std::binary_search(start, finish, *internal)); - - // #including tuple crashed borland, so I had to give up on tie(). - std::pair xy( - std::equal_range(start, finish, *internal)); - CountingIterator x = xy.first, y = xy.second; - - assert(boost::detail::distance(x, y) == 1); - - // Show that values outside the range can't be found - assert(!std::binary_search(start, boost::prior(finish), *finish)); - - // Do the generic random_access_iterator_test - typedef typename CountingIterator::value_type value_type; - std::vector v; - for (value_type z = *start; z != *finish; ++z) - v.push_back(z); - if (v.size() >= 2) - { - // Note that this test requires a that the first argument is - // dereferenceable /and/ a valid iterator prior to the first argument - boost::random_access_iterator_test(start + 1, v.size() - 1, v.begin() + 1); - } -} - -// Special tests for bidirectional CountingIterators -template -void category_test(CountingIterator start, CountingIterator finish, std::bidirectional_iterator_tag) -{ - if (finish != start - && finish != boost::next(start) - && finish != boost::next(boost::next(start))) - { - // Note that this test requires a that the first argument is - // dereferenceable /and/ a valid iterator prior to the first argument - boost::bidirectional_iterator_test(boost::next(start), boost::next(*start), boost::next(boost::next(*start))); - } -} - -template -void category_test(CountingIterator start, CountingIterator finish, std::forward_iterator_tag) -{ - if (finish != start && finish != boost::next(start)) - boost::forward_iterator_test(start, *start, boost::next(*start)); -} - -template -void test_aux(CountingIterator start, CountingIterator finish) -{ - typedef typename CountingIterator::iterator_category category; - typedef typename CountingIterator::value_type value_type; - - // If it's a RandomAccessIterator we can do a few delicate tests - category_test(start, finish, category()); - - // Okay, brute force... - for (CountingIterator p = start; p != finish && boost::next(p) != finish; ++p) - { - assert(boost::next(*p) == *boost::next(p)); - } - - // prove that a reference can be formed to these values - typedef typename CountingIterator::value_type value; - const value* q = &*start; - (void)q; // suppress unused variable warning -} - -template -void test(Incrementable start, Incrementable finish) -{ - test_aux(boost::make_counting_iterator(start), boost::make_counting_iterator(finish)); -} - -template -void test_integer(Integer* = 0) // default arg works around MSVC bug -{ - Integer start = 0; - Integer finish = 120; - test(start, finish); -} - -template -void test_container(Container* = 0) // default arg works around MSVC bug -{ - Container c(1 + (unsigned)rand() % 1673); - - const typename Container::iterator start = c.begin(); - - // back off by 1 to leave room for dereferenceable value at the end - typename Container::iterator finish = start; - std::advance(finish, c.size() - 1); - - test(start, finish); - - typedef typename Container::const_iterator const_iterator; - test(const_iterator(start), const_iterator(finish)); -} - -class my_int1 { -public: - my_int1() { } - my_int1(int x) : m_int(x) { } - my_int1& operator++() { ++m_int; return *this; } - bool operator==(const my_int1& x) const { return m_int == x.m_int; } -private: - int m_int; -}; - -namespace boost { - template <> - struct counting_iterator_traits { - typedef std::ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; - }; -} - -class my_int2 { -public: - typedef void value_type; - typedef void pointer; - typedef void reference; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - my_int2() { } - my_int2(int x) : m_int(x) { } - my_int2& operator++() { ++m_int; return *this; } - my_int2& operator--() { --m_int; return *this; } - bool operator==(const my_int2& x) const { return m_int == x.m_int; } -private: - int m_int; -}; - -class my_int3 { -public: - typedef void value_type; - typedef void pointer; - typedef void reference; - typedef std::ptrdiff_t difference_type; - typedef std::random_access_iterator_tag iterator_category; - - my_int3() { } - my_int3(int x) : m_int(x) { } - my_int3& operator++() { ++m_int; return *this; } - my_int3& operator+=(std::ptrdiff_t n) { m_int += n; return *this; } - std::ptrdiff_t operator-(const my_int3& x) const { return m_int - x.m_int; } - my_int3& operator--() { --m_int; return *this; } - bool operator==(const my_int3& x) const { return m_int == x.m_int; } - bool operator!=(const my_int3& x) const { return m_int != x.m_int; } - bool operator<(const my_int3& x) const { return m_int < x.m_int; } -private: - int m_int; -}; - -int main() -{ - // Test the built-in integer types. - test_integer(); - test_integer(); - test_integer(); - test_integer(); - test_integer(); - test_integer(); - test_integer(); - test_integer(); - test_integer(); - test_integer(); -#if defined(BOOST_HAS_LONG_LONG) - test_integer(); - test_integer(); -#endif - - // wrapping an iterator or non-built-in integer type causes an INTERNAL - // COMPILER ERROR in MSVC without STLport. I'm clueless as to why. -#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT) - // Test user-defined type. - test_integer(); - test_integer(); - test_integer(); - - // Some tests on container iterators, to prove we handle a few different categories - test_container >(); - test_container >(); -# ifndef BOOST_NO_SLIST - test_container >(); -# endif - - // Also prove that we can handle raw pointers. - int array[2000]; - test(boost::make_counting_iterator(array), boost::make_counting_iterator(array+2000-1)); -#endif - std::cout << "test successful " << std::endl; - return 0; -} diff --git a/current_function_test.cpp b/current_function_test.cpp deleted file mode 100644 index 620a45e..0000000 --- a/current_function_test.cpp +++ /dev/null @@ -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 -#include - -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"); -} diff --git a/filter_iterator.htm b/filter_iterator.htm deleted file mode 100644 index 6c0c973..0000000 --- a/filter_iterator.htm +++ /dev/null @@ -1,273 +0,0 @@ - - - - - - -Filter Iterator Adaptor Documentation - - - - -c++boost.gif (8819 bytes) - -

Filter Iterator Adaptor

- -Defined in header -boost/iterator_adaptors.hpp - - -

-The filter iterator adaptor creates a view of an iterator range in -which some elements of the range are skipped over. A Predicate -function object controls which elements are skipped. When the -predicate is applied to an element, if it returns true then -the element is retained and if it returns false then the -element is skipped over. - - -

Synopsis

- -
-namespace boost {
-  template <class Predicate, class BaseIterator, ...>
-  class filter_iterator_generator;
-
-  template <class Predicate, class BaseIterator>
-  typename filter_iterator_generator<Predicate, BaseIterator>::type
-  make_filter_iterator(BaseIterator first, BaseIterator last, const Predicate& p = Predicate());
-}
-
- -
- -

The Filter Iterator Type -Generator

- -The class filter_iterator_generator is a helper class whose -purpose is to construct a filter iterator type. The template -parameters for this class are the Predicate function object -type and the BaseIterator type that is being wrapped. In -most cases the associated types for the wrapped iterator can be -deduced from std::iterator_traits, but in some situations the -user may want to override these types, so there are also template -parameters for each of the iterator's associated types. - -
-template <class Predicate, class BaseIterator,
-          class Value, class Reference, class Pointer, class Category, class Distance>
-class filter_iterator_generator
-{
-public:
-  typedef iterator_adaptor<...> type; // the resulting filter iterator type 
-}
-
- - -

Example

- -The following example uses filter iterator to print out all the -positive integers in an array. - -
-struct is_positive_number {
-  bool operator()(int x) { return 0 < x; }
-};
-int main() {
-  int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
-  const int N = sizeof(numbers)/sizeof(int);
-
-  typedef boost::filter_iterator_generator<is_positive_number, int*, int>::type FilterIter;
-  is_positive_number predicate;
-  FilterIter::policies_type policies(predicate, numbers + N);
-  FilterIter filter_iter_first(numbers, policies);
-  FilterIter filter_iter_last(numbers + N, policies);
-
-  std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator<int>(std::cout, " "));
-  std::cout << std::endl;
-  return 0;
-}
-
-The output is: -
-4 5 8
-
- - -

Template Parameters

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescription
PredicateThe function object that determines which elements are retained and which elements are skipped. -
BaseIteratorThe iterator type being wrapped. This type must at least be a model - of the InputIterator concept.
ValueThe value_type of the resulting iterator, -unless const. If const, a conforming compiler strips constness for the -value_type. Typically the default for this parameter is the -appropriate type[1].
Default: -std::iterator_traits<BaseIterator>::value_type
ReferenceThe reference type of the resulting iterator, and in -particular, the result type of operator*(). Typically the default for -this parameter is the appropriate type.
Default: If -Value is supplied, Value& is used. Otherwise -std::iterator_traits<BaseIterator>::reference is -used.
PointerThe pointer type of the resulting iterator, and in - particular, the result type of operator->(). - Typically the default for -this parameter is the appropriate type.
-Default: If Value was supplied, then Value*, -otherwise std::iterator_traits<BaseIterator>::pointer.
CategoryThe iterator_category type for the resulting iterator. -Typically the -default for this parameter is the appropriate type. If you override -this parameter, do not use bidirectional_iterator_tag -because filter iterators can not go in reverse.
-Default: std::iterator_traits<BaseIterator>::iterator_category
DistanceThe difference_type for the resulting iterator. Typically the default for -this parameter is the appropriate type.
-Default: std::iterator_traits<BaseIterator>::difference_type
- - -

Model of

- -The filter iterator adaptor (the type -filter_iterator_generator<...>::type) may be a model of InputIterator or ForwardIterator -depending on the adapted iterator type. - - -

Members

- -The filter iterator type implements all of the member functions and -operators required of the ForwardIterator -concept. In addition it has the following constructor: - -
filter_iterator_generator::type(const BaseIterator& it, const Policies& p = Policies())
- -

-The policies type has only one public function, which is its constructor: - -

filter_iterator_generator::policies_type(const Predicate& p, const BaseIterator& end)
- -

-


-

- -

The Make Filter Iterator Function

- -
-template <class Predicate, class BaseIterator>
-typename filter_generator<Predicate, BaseIterator>::type
-make_filter_iterator(BaseIterator first, BaseIterator last, const Predicate& p = Predicate())
-
- -This function provides a convenient way to create filter iterators. - -

Example

- -In this example we print out all numbers in the array that are -greater than negative two. - -
-int main()
-{
-  int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
-  const int N = sizeof(numbers)/sizeof(int);
-
-  std::copy(boost::make_filter_iterator(numbers, numbers + N, 
-					std::bind2nd(std::greater(), -2)),
-	    boost::make_filter_iterator(numbers + N, numbers + N, 
-					std::bind2nd(std::greater(), -2)),
-	    std::ostream_iterator(std::cout, " "));
-  std::cout << std::endl;
-
-}
-
-The output is: -
-0 -1 4 5 8 
-
- -

-In the next example we print the positive numbers using the -make_filter_iterator() function. - -

-struct is_positive_number {
-  bool operator()(int x) { return 0 < x; }
-};
-int main()
-{
-  int numbers[] = { 0, -1, 4, -3, 5, 8, -2 };
-  const int N = sizeof(numbers)/sizeof(int);
-
-  std::copy(boost::make_filter_iterator<is_positive_number>(numbers, numbers + N),
-	    boost::make_filter_iterator<is_positive_number>(numbers + N, numbers + N),
-	    std::ostream_iterator<int>(std::cout, " "));
-  std::cout << std::endl;
-  return 0;
-}
-
-The output is: -
-4 5 8
-
- - -

Notes

- -[1] If the compiler does not support partial -specialization and the wrapped iterator type is a builtin pointer then -the Value type must be explicitly specified (don't use the -default). - - -
-

Revised 09 Mar 2001

-

© Copyright Jeremy Siek 2000. Permission to copy, use, -modify, sell and distribute this document is granted provided this copyright -notice appears in all copies. This document is provided "as is" -without express or implied warranty, and with no claim as to its suitability for -any purpose.

- - - - diff --git a/filter_iterator_example.cpp b/filter_iterator_example.cpp deleted file mode 100644 index bcec35d..0000000 --- a/filter_iterator_example.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Example of using the filter iterator adaptor from -// boost/iterator_adaptors.hpp. - -// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -#include -#include -#include -#include -#include - -struct is_positive_number { - bool operator()(int x) { return 0 < x; } -}; - -int main() -{ - int numbers_[] = { 0, -1, 4, -3, 5, 8, -2 }; - const int N = sizeof(numbers_)/sizeof(int); - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - // 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 base_iterator; -#else - typedef int* base_iterator; -#endif - base_iterator numbers(numbers_); - - // Example using make_filter_iterator() - std::copy(boost::make_filter_iterator(numbers, numbers + N), - boost::make_filter_iterator(numbers + N, numbers + N), - std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; - - // Example using filter_iterator_generator - typedef boost::filter_iterator_generator::type - FilterIter; - is_positive_number predicate; - FilterIter::policies_type policies(predicate, numbers + N); - FilterIter filter_iter_first(numbers, policies); - FilterIter filter_iter_last(numbers + N, policies); - - std::copy(filter_iter_first, filter_iter_last, std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; - - // Another example using make_filter_iterator() - std::copy(boost::make_filter_iterator(numbers, numbers + N, - std::bind2nd(std::greater(), -2)), - boost::make_filter_iterator(numbers + N, numbers + N, - std::bind2nd(std::greater(), -2)), - std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; - - - return 0; -} diff --git a/fun_out_iter_example.cpp b/fun_out_iter_example.cpp deleted file mode 100644 index dc84d39..0000000 --- a/fun_out_iter_example.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// (C) Copyright Jeremy Siek 2001. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// Revision History: - -// 27 Feb 2001 Jeremy Siek -// Initial checkin. - -#include -#include -#include - -#include - -struct string_appender { - string_appender(std::string& s) : m_str(s) { } - void operator()(const std::string& x) const { - m_str += x; - } - std::string& m_str; -}; - -int main(int, char*[]) -{ - std::vector x; - x.push_back("hello"); - x.push_back(" "); - x.push_back("world"); - x.push_back("!"); - - std::string s = ""; - std::copy(x.begin(), x.end(), - boost::make_function_output_iterator(string_appender(s))); - - std::cout << s << std::endl; - - return 0; -} diff --git a/function_output_iterator.htm b/function_output_iterator.htm deleted file mode 100644 index 6061a7b..0000000 --- a/function_output_iterator.htm +++ /dev/null @@ -1,169 +0,0 @@ - - - - - - - - - - Function Output Iterator Adaptor Documentation - - - - - c++boost.gif (8819 bytes) - -

Function Output Iterator Adaptor

- Defined in header boost/function_output_iterator.hpp - -

The function output iterator adaptor makes it easier to create - custom output iterators. The adaptor takes a Unary - Function and creates a model of Output - Iterator. Each item assigned to the output iterator is passed - as an argument to the unary function. The motivation for this - iterator is that creating a C++ Standard conforming output - iterator is non-trivial, particularly because the proper - implementation usually requires a proxy object. On the other hand, - creating a function (or function object) is much simpler. - -

Synopsis

- -
-
-namespace boost {
-  template <class UnaryFunction>
-  class function_output_iterator;
-
-  template <class UnaryFunction>
-  function_output_iterator<UnaryFunction>
-  make_function_output_iterator(const UnaryFunction& f = UnaryFunction())
-}
-
-
- -

Example

- - In this example we create an output iterator that appends - each item onto the end of a string, using the string_appender - function. - -
-
-#include <iostream>
-#include <string>
-#include <vector>
-
-#include <boost/function_output_iterator.hpp>
-
-struct string_appender {
-  string_appender(std::string& s) : m_str(s) { }
-  void operator()(const std::string& x) const {
-    m_str += x;
-  }
-  std::string& m_str;
-};
-
-int main(int, char*[])
-{
-  std::vector<std::string> x;
-  x.push_back("hello");
-  x.push_back(" ");
-  x.push_back("world");
-  x.push_back("!");
-
-  std::string s = "";
-  std::copy(x.begin(), x.end(), 
-            boost::make_function_output_iterator(string_appender(s)));
-  
-  std::cout << s << std::endl;
-
-  return 0;
-}
-
-
- -
- -

The Function Output Iterator Class

- -
-
-template <class UnaryFunction>
-class function_output_iterator;
-
-
- - The function_output_iterator class creates an Output - Iterator out of a - Unary - Function. Each item assigned to the output iterator is passed - as an argument to the unary function. - -

Template Parameters

- - - - - -
Parameter - - Description - -
UnaryFunction - - The function type being wrapped. The return type of the - function is not used, so it can be void. The - function must be a model of Unary - Function.
- -

Concept Model

- The function output iterator class is a model of Output - Iterator. - -

Members

- The function output iterator implements the member functions - and operators required of the Output - Iterator concept. In addition it has the following constructor: -
-explicit function_output_iterator(const UnaryFunction& f = UnaryFunction())
-
-
-
- -
-

The Function Output Iterator Object - Generator

- - The make_function_output_iterator() function provides a - more convenient way to create function output iterator objects. The - function saves the user the trouble of explicitly writing out the - iterator types. If the default argument is used, the function - type must be provided as an explicit template argument. - -
-
-template <class UnaryFunction>
-function_output_iterator<UnaryFunction>
-make_function_output_iterator(const UnaryFunction& f = UnaryFunction())
-
-
- -
- -

© Copyright Jeremy Siek 2001. Permission to copy, use, - modify, sell and distribute this document is granted provided this - copyright notice appears in all copies. This document is provided - "as is" without express or implied warranty, and with no claim as - to its suitability for any purpose. - - - diff --git a/generator_iterator.htm b/generator_iterator.htm deleted file mode 100644 index 752ec28..0000000 --- a/generator_iterator.htm +++ /dev/null @@ -1,150 +0,0 @@ - - - - -Generator Iterator Adaptor Documentation - - - - -c++boost.gif (8819 bytes) - -

Generator Iterator Adaptor

-Defined in header boost/generator_iterator.hpp -

-The generator iterator adaptor makes it easier to create custom input -iterators from 0-ary functions and function objects. The adaptor -takes a -Generator -and creates a model of -Input Iterator. -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 Random Number library. - -

Synopsis

- -
-
-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);
-}
-
-
- -
- -

The Generator Iterator Generator Class

- -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. - -
-template <class Generator>
-class generator_iterator_generator
-{
-public:
-  typedef iterator_adaptor<...> type; // the resulting generator iterator type 
-}
-
- - -

Template Parameters

- - - - - - - - - -
ParameterDescription
Generator -The generator (0-ary function object) type being -wrapped. The return type of the function must be defined as -Generator::result_type. The function object must be a model -of -Generator. -
- -

Concept Model

-The generator iterator class is a model of -Input Iterator. - -

Members

-The generator iterator implements the member functions -and operators required of the -Input Iterator -concept. - -
- -
-

The Generator Iterator Object Generator

- -The make_generator_iterator() function provides a -convenient way to create generator iterator objects. The function -saves the user the trouble of explicitly writing out the iterator -types. - -
-
-template <class Generator>
-typename generator_iterator_generator<Generator>::type
-make_function_output_iterator(Generator & gen);
-
-
- -
- - -

Example

- -The following program shows how generator_iterator -transforms a generator into an input iterator. - -
-
-#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;
-}
-
-
- -
- -Written by Jens Maurer. - - - diff --git a/half_open_range_test.cpp b/half_open_range_test.cpp deleted file mode 100644 index b19b4db..0000000 --- a/half_open_range_test.cpp +++ /dev/null @@ -1,366 +0,0 @@ -// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears in -// all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. -// -// See http://www.boost.org for most recent version including documentation. -// -// Revision History -// 11 Feb 2001 Compile with Borland, re-enable failing tests (David Abrahams) -// 29 Jan 2001 Initial revision (David Abrahams) - -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef BOOST_NO_LIMITS -# include -#endif -#ifndef BOOST_NO_SLIST -# include -#endif - -inline unsigned unsigned_random(unsigned max) -{ - return (max > 0) ? (unsigned)rand() % max : 0; -} - -// Special tests for ranges supporting random access -template -void category_test_1( - const boost::half_open_range& r, std::random_access_iterator_tag) -{ - typedef boost::half_open_range range; - typedef typename range::size_type size_type; - size_type size = r.size(); - - // pick a random offset - size_type offset = unsigned_random(size); - - typename range::value_type x = *(r.begin() + offset); - // test contains(value_type) - assert(r.contains(r.start()) == !r.empty()); - assert(!r.contains(r.finish())); - assert(r.contains(x) == (offset != size)); - - range::const_iterator p = r.find(x); - assert((p == r.end()) == (x == r.finish())); - assert(r.find(r.finish()) == r.end()); - - if (offset != size) - { - assert(x == r[offset]); - assert(x == r.at(offset)); - } - - bool caught_out_of_range = false; - try { - bool never_initialized = x == r.at(size); - (void)never_initialized; - } - catch(std::out_of_range&) - { - caught_out_of_range = true; - } - catch(...) - { - } - assert(caught_out_of_range); -} - -// Those tests must be skipped for other ranges -template -void category_test_1( - const boost::half_open_range&, std::forward_iterator_tag) -{ -} - -unsigned indices[][2] = { {0,0},{0,1},{0,2},{0,3}, - {1,1},{1,2},{1,3}, - {2,2},{2,3}, - {3,3}}; - -template -void category_test_2( - const std::vector& ranges, unsigned i, unsigned j, std::random_access_iterator_tag) -{ - typedef Range range; - const range& ri = ranges[i]; - const range& rj = ranges[j]; - - if (indices[i][0] <= indices[j][0] && indices[i][1] >= indices[j][1]) - assert(ri.contains(rj)); - - if (ri.contains(rj)) - assert((ri & rj) == rj); - assert(boost::intersects(ri, rj) == !(ri & rj).empty()); - - range t1(ri); - t1 &= rj; - assert(t1 == range(indices[i][0] > indices[j][0] ? ri.start() : rj.start(), - indices[i][1] < indices[j][1] ? ri.finish() : rj.finish())); - assert(t1 == (ri & rj)); - - range t2(ri); - t2 |= rj; - - if (ri.empty()) - assert(t2 == rj); - else if (rj.empty()) - assert(t2 == ri); - else - assert(t2 == range(indices[i][0] < indices[j][0] ? ri.start() : rj.start(), - indices[i][1] > indices[j][1] ? ri.finish() : rj.finish())); - assert(t2 == (ri | rj)); - if (i == j) - assert(ri == rj); - - if (ri.empty() || rj.empty()) - assert((ri == rj) == (ri.empty() && rj.empty())); - else - assert((ri == rj) == (ri.start() == rj.start() && ri.finish() == rj.finish())); - - assert((ri == rj) == !(ri != rj)); - - bool same = ri == rj; - bool one_empty = ri.empty() != rj.empty(); - - std::less less; - std::less_equal less_equal; - std::greater greater; - std::greater_equal greater_equal; - - if (same) - { - assert(greater_equal(ri,rj)); - assert(less_equal(ri,rj)); - assert(!greater(ri,rj)); - assert(!less(ri,rj)); - } - else if (one_empty) - { - const range& empty = ri.empty() ? ri : rj; - const range& non_empty = rj.empty() ? ri : rj; - - assert(less(empty,non_empty)); - assert(less_equal(empty,non_empty)); - assert(!greater(empty,non_empty)); - assert(!greater_equal(empty,non_empty)); - assert(!less(non_empty,empty)); - assert(!less_equal(non_empty,empty)); - assert(greater(non_empty,empty)); - assert(greater_equal(non_empty,empty)); - } - else { - if (indices[i][0] < indices[j][0] || - indices[i][0] == indices[j][0] && indices[i][1] < indices[j][1]) - { - assert(!greater_equal(ri,rj)); - assert(less(ri,rj)); - } - - if (indices[i][0] < indices[j][0] || - indices[i][0] == indices[j][0] && indices[i][1] <= indices[j][1]) - { - assert(!greater(ri,rj)); - assert(less_equal(ri,rj)); - } - - if (indices[i][0] > indices[j][0] || - indices[i][0] == indices[j][0] && indices[i][1] > indices[j][1]) - { - assert(!less_equal(ri,rj)); - assert(greater(ri,rj)); - } - - if (indices[i][0] > indices[j][0] || - indices[i][0] == indices[j][0] && indices[i][1] >= indices[j][1]) - { - assert(!less(ri,rj)); - assert(greater_equal(ri,rj)); - } - } -} - - -template -void category_test_2( - const std::vector&, unsigned, unsigned, std::forward_iterator_tag) -{ -} - -template -void category_test_2( - const std::vector >&, unsigned, unsigned, std::bidirectional_iterator_tag) -{ -} - -template -void test_back(Range& x, std::bidirectional_iterator_tag) -{ - assert(x.back() == boost::prior(x.finish())); -} - -template -void test_back(Range& x, std::forward_iterator_tag) -{ -} - -template -boost::half_open_range range_identity(const boost::half_open_range& x) -{ - return x; -} - -template -void test(T x0, T x1, T x2, T x3) -{ - std::vector > ranges; - typedef boost::half_open_range range; - - T bounds[4] = { x0, x1, x2, x3 }; - - const std::size_t num_ranges = sizeof(indices)/sizeof(*indices); - // test construction - for (std::size_t n = 0; n < num_ranges;++n) - { - T start = bounds[indices[n][0]]; - T finish = bounds[indices[n][1]]; - boost::half_open_range r(start, finish); - ranges.push_back(r); - } - - // test implicit conversion from std::pair - range converted = std::pair(x0,x0); - (void)converted; - - // test assignment, equality and inequality - range r00 = range(x0, x0); - assert(r00 == range(x0,x0)); - assert(r00 == range(x1,x1)); // empty ranges are all equal - if (x3 != x0) - assert(r00 != range(x0, x3)); - r00 = range(x0, x3); - assert(r00 == range(x0, x3)); - if (x3 != x0) - assert(r00 != range(x0, x0)); - - typedef typename range::iterator iterator; - typedef typename iterator::iterator_category category; - - for (unsigned i = 0; i < num_ranges; ++i) - { - const range& r = ranges[i]; - - // test begin(), end(), basic iteration. - unsigned count = 0; - for (range::const_iterator p = r.begin(), finish = r.end(); - p != finish; - ++p, ++count) - { - assert(count < 2100); - } - - // test size(), empty(), front(), back() - assert((unsigned)r.size() == count); - if (indices[i][0] == indices[i][1]) - assert(r.empty()); - if (r.empty()) - assert(r.size() == 0); - if (!r.empty()) - { - assert(r.front() == r.start()); - test_back(r, category()); - } - - // test swap - range r1(r); - range r2(x0,x3); - const bool same = r1 == r2; - r1.swap(r2); - assert(r1 == range(x0,x3)); - assert(r2 == r); - if (!same) { - assert(r1 != r); - assert(r2 != range(x0,x3)); - } - - // do individual tests for random-access iterators - category_test_1(r, category()); - } - - for (unsigned j = 0; j < num_ranges; ++j) { - for (unsigned k = 0; k < num_ranges; ++k) { - category_test_2(ranges, j, k, category()); - } - } - -} - -template -void test_integer(Integer* = 0) // default arg works around MSVC bug -{ - Integer a = 0; - Integer b = a + unsigned_random(128 - a); - Integer c = b + unsigned_random(128 - b); - Integer d = c + unsigned_random(128 - c); - - test(a, b, c, d); -} - -template -void test_container(Container* = 0) // default arg works around MSVC bug -{ - Container c(unsigned_random(1673)); - - const typename Container::size_type offset1 = unsigned_random(c.size()); - const typename Container::size_type offset2 = unsigned_random(c.size() - offset1); - typename Container::iterator internal1 = c.begin(); - std::advance(internal1, offset1); - typename Container::iterator internal2 = internal1; - std::advance(internal2, offset2); - - test(c.begin(), internal1, internal2, c.end()); - - typedef typename Container::const_iterator const_iterator; - test(const_iterator(c.begin()), - const_iterator(internal1), - const_iterator(internal2), - const_iterator(c.end())); -} - -int main() -{ - // Test the built-in integer types. - test_integer(); - test_integer(); - test_integer(); - test_integer(); - test_integer(); - test_integer(); - test_integer(); - test_integer(); - test_integer(); - test_integer(); -#if defined(BOOST_HAS_LONG_LONG) - test_integer(); - test_integer(); -#endif - // Some tests on container iterators, to prove we handle a few different categories - test_container >(); - test_container >(); -#ifndef BOOST_NO_SLIST - test_container >(); -#endif - // Also prove that we can handle raw pointers. - int array[2000]; - const std::size_t a = 0; - const std::size_t b = a + unsigned_random(2000 - a); - const std::size_t c = b + unsigned_random(2000 - b); - test(array, array+b, array+c, array+2000); - return 0; -} diff --git a/include/boost/assert.hpp b/include/boost/assert.hpp deleted file mode 100644 index 645404d..0000000 --- a/include/boost/assert.hpp +++ /dev/null @@ -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 - -#ifndef BOOST_ASSERT - -#include - -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 diff --git a/include/boost/call_traits.hpp b/include/boost/call_traits.hpp deleted file mode 100644 index 345a440..0000000 --- a/include/boost/call_traits.hpp +++ /dev/null @@ -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 -#endif - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#include -#else -#include -#endif - -#endif // BOOST_CALL_TRAITS_HPP diff --git a/include/boost/checked_delete.hpp b/include/boost/checked_delete.hpp deleted file mode 100644 index abb2ce0..0000000 --- a/include/boost/checked_delete.hpp +++ /dev/null @@ -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 struct checked_deleter -{ - typedef void result_type; - typedef T * argument_type; - - void operator()(T * x) - { - checked_delete(x); - } -}; - -template 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 diff --git a/include/boost/compressed_pair.hpp b/include/boost/compressed_pair.hpp deleted file mode 100644 index c55ca2d..0000000 --- a/include/boost/compressed_pair.hpp +++ /dev/null @@ -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 -#endif - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#include -#else -#include -#endif - -#endif // BOOST_COMPRESSED_PAIR_HPP diff --git a/include/boost/current_function.hpp b/include/boost/current_function.hpp deleted file mode 100644 index 6d52404..0000000 --- a/include/boost/current_function.hpp +++ /dev/null @@ -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 diff --git a/include/boost/detail/call_traits.hpp b/include/boost/detail/call_traits.hpp deleted file mode 100644 index c1fd918..0000000 --- a/include/boost/detail/call_traits.hpp +++ /dev/null @@ -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 -#endif - -#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP -#include -#endif -#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP -#include -#endif - -namespace boost{ - -namespace detail{ - -template -struct ct_imp2 -{ - typedef const T& param_type; -}; - -template -struct ct_imp2 -{ - typedef const T param_type; -}; - -template -struct ct_imp -{ - typedef const T& param_type; -}; - -template -struct ct_imp -{ - typedef typename ct_imp2::param_type param_type; -}; - -template -struct ct_imp -{ - typedef T const param_type; -}; - -} - -template -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, - // however compiler bugs prevent this - instead pass three bool's to - // ct_imp and add an extra partial specialisation - // of ct_imp to handle the logic. (JM) - typedef typename detail::ct_imp< - T, - ::boost::is_pointer::value, - ::boost::is_arithmetic::value - >::param_type param_type; -}; - -template -struct call_traits -{ - 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 -struct call_traits -{ - typedef T& value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T& param_type; // hh removed const -}; -template -struct call_traits -{ - typedef T& value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T& param_type; // hh removed const -}; -template -struct call_traits -{ - typedef T& value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T& param_type; // hh removed const -}; -#endif -#ifndef __SUNPRO_CC -template -struct call_traits -{ -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 -struct call_traits -{ -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 diff --git a/include/boost/detail/compressed_pair.hpp b/include/boost/detail/compressed_pair.hpp deleted file mode 100644 index 0a74d8a..0000000 --- a/include/boost/detail/compressed_pair.hpp +++ /dev/null @@ -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 -#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP -#include -#endif -#ifndef BOOST_SAME_TRAITS_HPP -#include -#endif -#ifndef BOOST_CALL_TRAITS_HPP -#include -#endif - -namespace boost -{ - -template -class compressed_pair; - - -// compressed_pair - -namespace details -{ - // JM altered 26 Jan 2000: - template - struct compressed_pair_switch; - - template - struct compressed_pair_switch - {static const int value = 0;}; - - template - struct compressed_pair_switch - {static const int value = 3;}; - - template - struct compressed_pair_switch - {static const int value = 1;}; - - template - struct compressed_pair_switch - {static const int value = 2;}; - - template - struct compressed_pair_switch - {static const int value = 4;}; - - template - struct compressed_pair_switch - {static const int value = 5;}; - - template 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 - inline void cp_swap(T& t1, T& t2) - { -#ifndef __GNUC__ - using std::swap; -#endif - swap(t1, t2); - } - - // 0 derive from neither - - template - class compressed_pair_imp - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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& y) - { - cp_swap(first_, y.first()); - cp_swap(second_, y.second()); - } - private: - first_type first_; - second_type second_; - }; - - // 1 derive from T1 - - template - class compressed_pair_imp - : private T1 - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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& y) - { - // no need to swap empty base class: - cp_swap(second_, y.second()); - } - private: - second_type second_; - }; - - // 2 derive from T2 - - template - class compressed_pair_imp - : private T2 - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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& 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 compressed_pair_imp - : private T1, - private T2 - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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&) {} - }; - - // 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 compressed_pair_imp - : private T1 - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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&) {} - private: - }; - - // 5 T1 == T2 and are not empty: //JM - - template - class compressed_pair_imp - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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& y) - { - cp_swap(first_, y.first()); - cp_swap(second_, y.second()); - } - private: - first_type first_; - second_type second_; - }; - -} // details - -template -class compressed_pair - : private ::boost::details::compressed_pair_imp::type, typename remove_cv::type>::value, - ::boost::is_empty::value, - ::boost::is_empty::value>::value> -{ -private: - typedef details::compressed_pair_imp::type, typename remove_cv::type>::value, - ::boost::is_empty::value, - ::boost::is_empty::value>::value> base; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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 compressed_pair - : private details::compressed_pair_imp::type, typename remove_cv::type>::value, - ::boost::is_empty::value, - ::boost::is_empty::value>::value> -{ -private: - typedef details::compressed_pair_imp::type, typename remove_cv::type>::value, - ::boost::is_empty::value, - ::boost::is_empty::value>::value> base; -public: - typedef T first_type; - typedef T second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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& y) { base::swap(y); } -}; - -template -inline -void -swap(compressed_pair& x, compressed_pair& y) -{ - x.swap(y); -} - -} // boost - -#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP - - - diff --git a/include/boost/detail/ob_compressed_pair.hpp b/include/boost/detail/ob_compressed_pair.hpp deleted file mode 100644 index f8efbb1..0000000 --- a/include/boost/detail/ob_compressed_pair.hpp +++ /dev/null @@ -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 -#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP -#include -#endif -#ifndef BOOST_SAME_TRAITS_HPP -#include -#endif -#ifndef BOOST_CALL_TRAITS_HPP -#include -#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 compressed_pair; - -namespace detail{ - -template -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 -struct init_one; - -template <> -struct init_one<1> -{ - template - static void init(const A& a, T1* p1, T2*) - { - *p1 = a; - } -}; - -template <> -struct init_one<2> -{ - template - static void init(const A& a, T1*, T2* p2) - { - *p2 = a; - } -}; - - -// T1 != T2, both non-empty -template -class compressed_pair_0 -{ -private: - T1 _first; - T2 _second; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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 - explicit compressed_pair_0(const A& val) - { - init_one::value>::init(val, &_first, &_second); - } - compressed_pair_0(const ::boost::compressed_pair& 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 compressed_pair_1 : T2 -{ -private: - T1 _first; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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 - explicit compressed_pair_1(const A& val) - { - init_one::value>::init(val, &_first, static_cast(this)); - } - - compressed_pair_1(const ::boost::compressed_pair& x) - : T2(x.second()), _first(x.first()) {} - -#ifdef BOOST_MSVC - // Total weirdness. If the assignment to _first is moved after - // the call to the inherited operator=, then this breaks graph/test/graph.cpp - // by way of iterator_adaptor. - compressed_pair_1& operator=(const compressed_pair_1& x) { - _first = x._first; - T2::operator=(x); - return *this; - } -#endif - - first_reference first() { return _first; } - first_const_reference first() const { return _first; } - - second_reference second() { return *this; } - second_const_reference second() const { return *this; } - - void swap(compressed_pair_1& y) - { - // no need to swap empty base class: - using std::swap; - swap(_first, y._first); - } -}; - -// T1 != T2, T1 empty -template -class compressed_pair_2 : T1 -{ -private: - T2 _second; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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 - explicit compressed_pair_2(const A& val) - { - init_one::value>::init(val, static_cast(this), &_second); - } - compressed_pair_2(const ::boost::compressed_pair& 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 compressed_pair_3 : T1, T2 -{ -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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 - explicit compressed_pair_3(const A& val) - { - init_one::value>::init(val, static_cast(this), static_cast(this)); - } - compressed_pair_3(const ::boost::compressed_pair& 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 compressed_pair_4 : T1 -{ -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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& 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 compressed_pair_5 -{ -private: - T1 _first; - T2 _second; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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& 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 -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_0 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_1 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_2 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_3 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_4 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_5 type; - }; -}; - -template -struct compressed_pair_traits -{ -private: - typedef compressed_pair_chooser::value, is_empty::value, is_same::value> chooser; - typedef typename chooser::template rebind bound_type; -public: - typedef typename bound_type::type type; -}; - -} // namespace detail - -template -class compressed_pair : public detail::compressed_pair_traits::type -{ -private: - typedef typename detail::compressed_pair_traits::type base_type; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair() : base_type() {} - compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {} - template - 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 -inline void swap(compressed_pair& x, compressed_pair& y) -{ - x.swap(y); -} - -#else -// no partial specialisation, no member templates: - -template -class compressed_pair -{ -private: - T1 _first; - T2 _second; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::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 -inline void swap(compressed_pair& x, compressed_pair& y) -{ - x.swap(y); -} - -#endif - -} // boost - -#endif // BOOST_OB_COMPRESSED_PAIR_HPP - - - diff --git a/include/boost/generator_iterator.hpp b/include/boost/generator_iterator.hpp deleted file mode 100644 index 5f4c0a9..0000000 --- a/include/boost/generator_iterator.hpp +++ /dev/null @@ -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 -#include - -namespace boost { - -template -class generator_iterator_policies -{ -public: - generator_iterator_policies() { } - - template - void initialize(Base& base) { - m_value = (*base)(); - } - - // The Iter template argument is necessary for compatibility with a MWCW - // bug workaround - template - void increment(IteratorAdaptor& iter) { - m_value = (*iter.base())(); - } - - template - const typename Generator::result_type& - dereference(const IteratorAdaptor&) const - { return m_value; } - - template - 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 -struct generator_iterator_generator -{ - typedef iterator_adaptor, - typename Generator::result_type, const typename Generator::result_type&, - const typename Generator::result_type*, std::input_iterator_tag, - long> type; -}; - -template -inline typename generator_iterator_generator::type -make_generator_iterator(Generator & gen) -{ - typedef typename generator_iterator_generator::type result_t; - return result_t(&gen); -} - -} // namespace boost - - -#endif // BOOST_ITERATOR_ADAPTOR_GENERATOR_ITERATOR_HPP - diff --git a/include/boost/operators.hpp b/include/boost/operators.hpp deleted file mode 100644 index bd571ec..0000000 --- a/include/boost/operators.hpp +++ /dev/null @@ -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 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 -#include - -#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 -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 -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 -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 -struct equality_comparable1 : B -{ - friend bool operator!=(const T& x, const T& y) { return !(x == y); } -}; - -template -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 -struct multipliable1 : B -{ - friend T operator*(T x, const T& y) { return x *= y; } -}; - -template -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 -struct addable1 : B -{ - friend T operator+(T x, const T& y) { return x += y; } -}; - -template -struct subtractable2 : B -{ - friend T operator-(T x, const U& y) { return x -= y; } -}; - -template -struct subtractable2_left : B -{ - friend T operator-(const U& x, const T& y) - { T result(x); return result -= y; } -}; - -template -struct subtractable1 : B -{ - friend T operator-(T x, const T& y) { return x -= y; } -}; - -template -struct dividable2 : B -{ - friend T operator/(T x, const U& y) { return x /= y; } -}; - -template -struct dividable2_left : B -{ - friend T operator/(const U& x, const T& y) - { T result(x); return result /= y; } -}; - -template -struct dividable1 : B -{ - friend T operator/(T x, const T& y) { return x /= y; } -}; - -template -struct modable2 : B -{ - friend T operator%(T x, const U& y) { return x %= y; } -}; - -template -struct modable2_left : B -{ - friend T operator%(const U& x, const T& y) - { T result(x); return result %= y; } -}; - -template -struct modable1 : B -{ - friend T operator%(T x, const T& y) { return x %= y; } -}; - -template -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 -struct xorable1 : B -{ - friend T operator^(T x, const T& y) { return x ^= y; } -}; - -template -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 -struct andable1 : B -{ - friend T operator&(T x, const T& y) { return x &= y; } -}; - -template -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 -struct orable1 : B -{ - friend T operator|(T x, const T& y) { return x |= y; } -}; - -// incrementable and decrementable contributed by Jeremy Siek - -template -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 -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 -struct dereferenceable : B -{ - P operator->() const - { - return &*static_cast(*this); - } -}; - -template -struct indexable : B -{ - R operator[](I n) const - { - return *(static_cast(*this) + n); - } -}; - -// More operator classes (contributed by Daryle Walker) --------------------// - -template -struct left_shiftable2 : B -{ - friend T operator<<(T x, const U& y) { return x <<= y; } -}; - -template -struct left_shiftable1 : B -{ - friend T operator<<(T x, const T& y) { return x <<= y; } -}; - -template -struct right_shiftable2 : B -{ - friend T operator>>(T x, const U& y) { return x >>= y; } -}; - -template -struct right_shiftable1 : B -{ - friend T operator>>(T x, const T& y) { return x >>= y; } -}; - -template -struct equivalent2 : B -{ - friend bool operator==(const T& x, const U& y) - { - return !(x < y) && !(x > y); - } -}; - -template -struct equivalent1 : B -{ - friend bool operator==(const T&x, const T&y) - { - return !(x < y) && !(y < x); - } -}; - -template -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 -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 -struct totally_ordered2 - : less_than_comparable2 > {}; - -template -struct totally_ordered1 - : less_than_comparable1 > {}; - -template -struct additive2 - : addable2 > {}; - -template -struct additive1 - : addable1 > {}; - -template -struct multiplicative2 - : multipliable2 > {}; - -template -struct multiplicative1 - : multipliable1 > {}; - -template -struct integer_multiplicative2 - : multiplicative2 > {}; - -template -struct integer_multiplicative1 - : multiplicative1 > {}; - -template -struct arithmetic2 - : additive2 > {}; - -template -struct arithmetic1 - : additive1 > {}; - -template -struct integer_arithmetic2 - : additive2 > {}; - -template -struct integer_arithmetic1 - : additive1 > {}; - -template -struct bitwise2 - : xorable2 > > {}; - -template -struct bitwise1 - : xorable1 > > {}; - -template -struct unit_steppable - : incrementable > {}; - -template -struct shiftable2 - : left_shiftable2 > {}; - -template -struct shiftable1 - : left_shiftable1 > {}; - -template -struct ring_operators2 - : additive2 > > {}; - -template -struct ring_operators1 - : additive1 > {}; - -template -struct ordered_ring_operators2 - : ring_operators2 > {}; - -template -struct ordered_ring_operators1 - : ring_operators1 > {}; - -template -struct field_operators2 - : ring_operators2 > > {}; - -template -struct field_operators1 - : ring_operators1 > {}; - -template -struct ordered_field_operators2 - : field_operators2 > {}; - -template -struct ordered_field_operators1 - : field_operators1 > {}; - -template -struct euclidian_ring_operators2 - : ring_operators2 > > > > {}; - -template -struct euclidian_ring_operators1 - : ring_operators1 > > {}; - -template -struct ordered_euclidian_ring_operators2 - : totally_ordered2 > {}; - -template -struct ordered_euclidian_ring_operators1 - : totally_ordered1 > {}; - -template -struct input_iteratable - : equality_comparable1 > > {}; - -template -struct output_iteratable - : incrementable {}; - -template -struct forward_iteratable - : input_iteratable {}; - -template -struct bidirectional_iteratable - : forward_iteratable > {}; - -// 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 -struct random_access_iteratable - : bidirectional_iteratable > > > {}; - -#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 \ - struct template_name : ::template_name {}; - -# define BOOST_IMPORT_TEMPLATE3(template_name) \ - template \ - struct template_name : ::template_name {}; - -# define BOOST_IMPORT_TEMPLATE2(template_name) \ - template \ - struct template_name : ::template_name {}; - -# define BOOST_IMPORT_TEMPLATE1(template_name) \ - template \ - struct template_name : ::template_name {}; - -# 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 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 \ - struct is_chained_base< ::boost::template_name4 > { \ - 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 \ - struct is_chained_base< ::boost::template_name3 > { \ - 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 \ - struct is_chained_base< ::boost::template_name2 > { \ - 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 \ - struct is_chained_base< ::boost::template_name1 > { \ - 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 '1' -// and '2' which must implement the corresponding 1- and 2- -// argument forms. -// -// The template type parameter O == is_chained_base::value is used to -// distinguish whether the 2nd argument to 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 '1' or '2'. -// - -# define BOOST_OPERATOR_TEMPLATE(template_name) \ -template ::value \ - > \ -struct template_name : template_name##2 {}; \ - \ -template \ -struct template_name \ - : template_name##1 {}; \ - \ -template \ -struct template_name \ - : template_name##1 {}; \ - \ -template \ -struct is_chained_base< ::boost::template_name > { \ - 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 \ - struct template_name : template_name##1 {}; - -#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 -struct operators2 - : totally_ordered2 > > {}; - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -struct operators : operators2 {}; - -template struct operators -#else -template struct operators -#endif - : totally_ordered > > > {}; - -// 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 -struct input_iterator_helper - : input_iteratable > {}; - -template -struct output_iterator_helper - : output_iteratable > -{ - T& operator*() { return static_cast(*this); } - T& operator++() { return static_cast(*this); } -}; - -template -struct forward_iterator_helper - : forward_iteratable > {}; - -template -struct bidirectional_iterator_helper - : bidirectional_iteratable > {}; - -template -struct random_access_iterator_helper - : random_access_iteratable > -{ - 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 diff --git a/include/boost/ref.hpp b/include/boost/ref.hpp deleted file mode 100644 index 60a834b..0000000 --- a/include/boost/ref.hpp +++ /dev/null @@ -1,162 +0,0 @@ -#ifndef BOOST_REF_HPP_INCLUDED -# define BOOST_REF_HPP_INCLUDED - -# if _MSC_VER+0 >= 1020 -# pragma once -# endif - -# include -# include - -// -// 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 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 inline reference_wrapper BOOST_REF_CONST ref(T & t) -{ - return reference_wrapper(t); -} - -template inline reference_wrapper BOOST_REF_CONST cref(T const & t) -{ - return reference_wrapper(t); -} - -# undef BOOST_REF_CONST - -# ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -class is_reference_wrapper -{ - public: - BOOST_STATIC_CONSTANT(bool, value = false); -}; - -template -class is_reference_wrapper > -{ - public: - BOOST_STATIC_CONSTANT(bool, value = true); -}; - -template -class unwrap_reference -{ - public: - typedef T type; -}; - -template -class unwrap_reference > -{ - public: - typedef T type; -}; -# else // no partial specialization - -} // namespace boost - -#include - -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 - yes_reference_wrapper_t is_reference_wrapper_test(type< reference_wrapper >); - - template - struct reference_unwrapper - { - template - struct apply - { - typedef T type; - }; - }; - - template<> - struct reference_unwrapper - { - template - struct apply - { - typedef typename T::type type; - }; - }; -} - -template -class is_reference_wrapper -{ - public: - BOOST_STATIC_CONSTANT( - bool, value = ( - sizeof(detail::is_reference_wrapper_test(type())) - == sizeof(detail::yes_reference_wrapper_t))); -}; - -template -class unwrap_reference - : public detail::reference_unwrapper< - is_reference_wrapper::value - >::template apply -{}; - -# endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -} // namespace boost - -#endif // #ifndef BOOST_REF_HPP_INCLUDED diff --git a/include/boost/utility.hpp b/include/boost/utility.hpp deleted file mode 100644 index a6c9464..0000000 --- a/include/boost/utility.hpp +++ /dev/null @@ -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 interface - -#include -#include -#include - -namespace boost -{ -// next() and prior() template functions -----------------------------------// - - // Helper functions for classes like bidirectional iterators not supporting - // operator+ and operator-. - // - // Usage: - // const std::list::iterator p = get_some_iterator(); - // const std::list::iterator prev = boost::prior(p); - - // Contributed by Dave Abrahams - - template - inline T next(T x) { return ++x; } - - template - 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 - diff --git a/include/boost/utility/addressof.hpp b/include/boost/utility/addressof.hpp deleted file mode 100644 index a434b8e..0000000 --- a/include/boost/utility/addressof.hpp +++ /dev/null @@ -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 T* addressof(T& v) -{ - return reinterpret_cast( - &const_cast(reinterpret_cast(v))); -} - -} - -#endif // BOOST_UTILITY_ADDRESSOF_HPP diff --git a/include/boost/utility/base_from_member.hpp b/include/boost/utility/base_from_member.hpp deleted file mode 100644 index 48d1d4a..0000000 --- a/include/boost/utility/base_from_member.hpp +++ /dev/null @@ -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 // 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 diff --git a/include/boost/utility_fwd.hpp b/include/boost/utility_fwd.hpp deleted file mode 100644 index 8e2f040..0000000 --- a/include/boost/utility_fwd.hpp +++ /dev/null @@ -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 -------------------------------// - -template < typename MemberType, int UniqueID = 0 > - class base_from_member; - - -// From ------------------------------------------------// - -class noncopyable; - -// Also has a few function templates - -} // namespace boost - - -#endif // BOOST_UTILITY_FWD_HPP diff --git a/index.html b/index.html deleted file mode 100644 index b6f6875..0000000 --- a/index.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - -Boost Utility Library - - - - -

Boost -Utility Library

-

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.

-

But that doesn't mean there isn't useful stuff here.  Take a look:

-
-

base_from_member
- call_traits.htm
- compressed_pair.htm
- operators.htm
- tie
- utility.htm

-
-
-

Revised -07 May, 2002

-

 

- - - - diff --git a/indirect_iterator.htm b/indirect_iterator.htm deleted file mode 100644 index a318424..0000000 --- a/indirect_iterator.htm +++ /dev/null @@ -1,444 +0,0 @@ - - - - - - - - - - Indirect Iterator Adaptor Documentation - - - - - c++boost.gif (8819 bytes) - -

Indirect Iterator Adaptor

- Defined in header boost/iterator_adaptors.hpp - -

The indirect iterator adaptor augments an iterator by applying an - extra dereference inside of operator*(). For example, this - iterator makes it possible to view a container of pointers or - smart-pointers (e.g. std::list<boost::shared_ptr<foo> - >) as if it were a container of the pointed-to type. The following - pseudo-code shows the basic idea of the indirect iterator: - -

-
-// inside a hypothetical indirect_iterator class...
-typedef std::iterator_traits<BaseIterator>::value_type Pointer;
-typedef std::iterator_traits<Pointer>::reference reference;
-
-reference indirect_iterator::operator*() const {
-  return **this->base_iterator;
-}
-
-
- -

Synopsis

- -
-
-namespace boost {
-  template <class BaseIterator,
-            class Value, class Reference, class Category, class Pointer>
-  struct indirect_iterator_generator;
-  
-  template <class BaseIterator,
-            class Value, class Reference, class ConstReference, 
-            class Category, class Pointer, class ConstPointer>
-  struct indirect_iterator_pair_generator;
-
-  template <class BaseIterator>
-  typename indirect_iterator_generator<BaseIterator>::type
-  make_indirect_iterator(BaseIterator base)  
-}
-
-
-
- -

The Indirect Iterator Type - Generator

- The indirect_iterator_generator template is a generator of - indirect iterator types. The main template parameter for this class is the - BaseIterator type that is being wrapped. In most cases the type of - the elements being pointed to can be deduced using - std::iterator_traits, but in some situations the user may want to - override this type, so there are also template parameters that allow a user - to control the value_type, pointer, and - reference types of the resulting iterators. - -
-
-template <class BaseIterator,
-          class Value, class Reference, class Pointer>
-class indirect_iterator_generator
-{
-public:
-  typedef iterator_adaptor<...> type; // the resulting indirect iterator type 
-};
-
-
- -

Example

- This example uses the indirect_iterator_generator to create - indirect iterators which dereference the pointers stored in the - pointers_to_chars array to access the chars in the - characters array. - -
-
-#include <boost/config.hpp>
-#include <vector>
-#include <iostream>
-#include <iterator>
-#include <boost/iterator_adaptors.hpp>
-
-int main(int, char*[])
-{
-  char characters[] = "abcdefg";
-  const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
-  char* pointers_to_chars[N];                        // at the end.
-  for (int i = 0; i < N; ++i)
-    pointers_to_chars[i] = &characters[i];
-  
-  boost::indirect_iterator_generator<char**, char>::type 
-    indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
-
-  std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
-  std::cout << std::endl;
-  
-  // to be continued...
-
-
- -

Template Parameters

- - - - - - - - -
Parameter - - Description - -
BaseIterator - - The iterator type being wrapped. The value_type - of the base iterator should itself be dereferenceable. - The return type of the operator* for the - value_type should match the Reference type. - -
Value - - The value_type of the resulting iterator, unless const. If - Value is const X, a conforming compiler makes the - value_type non-const X[1]. Note that if the default - is used for Value, then there must be a valid specialization - of iterator_traits for the value type of the base iterator. -
- Default: std::iterator_traits<
-   std::iterator_traits<BaseIterator>::value_type - >::value_type
[2] - -
Reference - - The reference type of the resulting iterator, and in - particular, the result type of operator*().
- Default: Value& - -
Pointer - - The pointer type of the resulting iterator, and in - particular, the result type of operator->().
- Default: Value* - -
Category - The iterator_category type for the resulting iterator.
- Default: - std::iterator_traits<BaseIterator>::iterator_category - -
- -

Concept Model

- The indirect iterator will model whichever standard iterator - concept category is modeled by the base iterator. Thus, if the - base iterator is a model of Random - Access Iterator then so is the resulting indirect iterator. If - the base iterator models a more restrictive concept, the resulting - indirect iterator will model the same concept [3]. - -

Members

- The indirect iterator type implements the member functions and operators - required of the Random Access - Iterator concept. In addition it has the following constructor: -
-explicit indirect_iterator_generator::type(const BaseIterator& it)
-
-
-
- -
- -

- -

The Indirect Iterator Pair - Generator

- Sometimes a pair of const/non-const pair of iterators is - needed, such as when implementing a container. The - indirect_iterator_pair_generator class makes it more convenient to - create this pair of iterator types. - -
-
-  template <class BaseIterator,
-            class Value, class Reference, class ConstReference, 
-            class Category, class Pointer, class ConstPointer>
-  struct indirect_iterator_pair_generator;
-{
-public:
-  typedef iterator_adaptor<...> iterator;       // the mutable indirect iterator type 
-  typedef iterator_adaptor<...> const_iterator; // the immutable indirect iterator type 
-};
-
-
- -

Example

- -
-
-  // continuing from the last example...
-
-  typedef boost::indirect_iterator_pair_generator<char**,
-    char, char*, char&, const char*, const char&> PairGen;
-
-  char mutable_characters[N];
-  char* pointers_to_mutable_chars[N];
-  for (int i = 0; i < N; ++i)
-    pointers_to_mutable_chars[i] = &mutable_characters[i];
-
-  PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars),
-    mutable_indirect_last(pointers_to_mutable_chars + N);
-  PairGen::const_iterator const_indirect_first(pointers_to_chars),
-    const_indirect_last(pointers_to_chars + N);
-
-  std::transform(const_indirect_first, const_indirect_last,
-     mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
-
-  std::copy(mutable_indirect_first, mutable_indirect_last,
-      std::ostream_iterator<char>(std::cout, ","));
-  std::cout << std::endl;
-  // to be continued...
-
-
- -

The output is: - -

-
-b,c,d,e,f,g,h,
-
-
- -

Template Parameters

- - - - - - - - - - -
Parameter - - Description - -
BaseIterator - - The iterator type being wrapped. The value_type of the - base iterator should itself be dereferenceable. - The return type of the operator* for the - value_type should match the Reference type. - -
Value - - The value_type of the resulting iterators. - If Value is const X, a conforming compiler makes the - value_type non-const X[1]. Note that if the default - is used for Value, then there must be a valid - specialization of iterator_traits for the value type - of the base iterator.
- - Default: std::iterator_traits<
-   std::iterator_traits<BaseIterator>::value_type - >::value_type
[2] - -
Reference - - The reference type of the resulting iterator, and - in particular, the result type of its operator*().
- Default: Value& - -
ConstReference - - The reference type of the resulting - const_iterator, and in particular, the result type of its - operator*().
- Default: const Value& - -
Category - The iterator_category type for the resulting iterator.
- Default: - std::iterator_traits<BaseIterator>::iterator_category - -
Pointer - - The pointer type of the resulting iterator, and - in particular, the result type of its operator->().
- Default: Value* - -
ConstPointer - - The pointer type of the resulting const_iterator, - and in particular, the result type of its operator->().
- Default: const Value* - -
- -

Concept Model

- - The indirect iterators will model whichever standard iterator - concept category is modeled by the base iterator. Thus, if the - base iterator is a model of Random - Access Iterator then so are the resulting indirect - iterators. If the base iterator models a more restrictive concept, - the resulting indirect iterators will model the same concept [3]. - - -

Members

- The resulting iterator and const_iterator types implement - the member functions and operators required of the Random Access - Iterator concept. In addition they support the following constructors: - -
-
-explicit indirect_iterator_pair_generator::iterator(const BaseIterator& it)
-explicit indirect_iterator_pair_generator::const_iterator(const BaseIterator& it)
-
-
-
-
- -
- -

- -

The Indirect Iterator Object - Generator

- The make_indirect_iterator() function provides a more convenient - way to create indirect iterator objects. The function saves the user the - trouble of explicitly writing out the iterator types. - -
-
-template <class BaseIterator>
-typename indirect_iterator_generator<BaseIterator>::type
-make_indirect_iterator(BaseIterator base)  
-
-
- -

Example

- Here we again print the chars from the array characters - by accessing them through the array of pointers pointer_to_chars, - but this time we use the make_indirect_iterator() function which - saves us some typing. - -
-
-  // continuing from the last example...
-
-  std::copy(boost::make_indirect_iterator(pointers_to_chars), 
-      boost::make_indirect_iterator(pointers_to_chars + N),
-      std::ostream_iterator<char>(std::cout, ","));
-  std::cout << std::endl;
-
-  return 0;
-}
-
-
- The output is: - -
-
-a,b,c,d,e,f,g,
-
-
-
- -

Notes

- -

- -

[2] If your compiler does not support partial - specialization and the base iterator or its value_type is a - builtin pointer type, you will not be able to use the default for - Value and will need to specify this type explicitly. - -

[3]There is a caveat to which concept the - indirect iterator can model. If the return type of the - operator* for the base iterator's value type is not a - true reference, then strickly speaking, the indirect iterator can - not be a model of Forward - Iterator or any of the concepts that refine it. In this case - the Category for the indirect iterator should be - specified as std::input_iterator_tag. However, even in - this case, if the base iterator is a random access iterator, the - resulting indirect iterator will still satisfy most of the - requirements for Random - Access Iterator. - -


- -

Revised - 18 Sep 2001 - - -

© Copyright Jeremy Siek and David Abrahams 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. - - - - - - - - diff --git a/indirect_iterator_example.cpp b/indirect_iterator_example.cpp deleted file mode 100644 index fb2b608..0000000 --- a/indirect_iterator_example.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -#include -#include -#include -#include -#include -#include - -int main(int, char*[]) -{ - char characters[] = "abcdefg"; - const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char - char* pointers_to_chars[N]; // at the end. - for (int i = 0; i < N; ++i) - pointers_to_chars[i] = &characters[i]; - - // Example of using indirect_iterator_generator - - boost::indirect_iterator_generator::type - indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N); - - std::copy(indirect_first, indirect_last, std::ostream_iterator(std::cout, ",")); - std::cout << std::endl; - - - // Example of using indirect_iterator_pair_generator - - typedef boost::indirect_iterator_pair_generator PairGen; - - 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]; - - PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars), - mutable_indirect_last(pointers_to_mutable_chars + N); - PairGen::const_iterator const_indirect_first(pointers_to_chars), - const_indirect_last(pointers_to_chars + N); - - std::transform(const_indirect_first, const_indirect_last, - mutable_indirect_first, std::bind1st(std::plus(), 1)); - - std::copy(mutable_indirect_first, mutable_indirect_last, - std::ostream_iterator(std::cout, ",")); - std::cout << std::endl; - - - // Example of using make_indirect_iterator() - -#ifndef BOOST_MSVC - std::copy(boost::make_indirect_iterator(pointers_to_chars), - boost::make_indirect_iterator(pointers_to_chars + N), - std::ostream_iterator(std::cout, ",")); - std::cout << std::endl; -#endif - - return 0; -} diff --git a/indirect_iterator_test.cpp b/indirect_iterator_test.cpp deleted file mode 100644 index f05785c..0000000 --- a/indirect_iterator_test.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// Revision History -// 08 Mar 2001 Jeremy Siek -// Moved test of indirect iterator into its own file. It to -// to be in iterator_adaptor_test.cpp. - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -struct my_iterator_tag : public std::random_access_iterator_tag { }; - -using boost::dummyT; - -typedef std::deque storage; -typedef std::deque pointer_deque; -typedef std::set iterator_set; - -void more_indirect_iterator_tests() -{ -// For some reason all heck breaks loose in the compiler under these conditions. -#if !defined(BOOST_MSVC) || !defined(__STL_DEBUG) - storage store(1000); - std::generate(store.begin(), store.end(), rand); - - pointer_deque ptr_deque; - iterator_set iter_set; - - for (storage::iterator p = store.begin(); p != store.end(); ++p) - { - ptr_deque.push_back(&*p); - iter_set.insert(p); - } - - typedef boost::indirect_iterator_pair_generator< - pointer_deque::iterator -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - , int -#endif - > IndirectDeque; - - IndirectDeque::iterator db(ptr_deque.begin()); - IndirectDeque::iterator de(ptr_deque.end()); - assert(static_cast(de - db) == store.size()); - assert(db + store.size() == de); - IndirectDeque::const_iterator dci(db); - assert(db == dci); - assert(dci == db); - assert(dci != de); - assert(dci < de); - assert(dci <= de); - assert(de >= dci); - assert(de > dci); - dci = de; - assert(dci == de); - - boost::random_access_iterator_test(db + 1, store.size() - 1, boost::next(store.begin())); - - *db = 999; - assert(store.front() == 999); - - // Borland C++ is getting very confused about the typedef's here - - typedef boost::indirect_iterator_generator< - iterator_set::iterator -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - , int -#endif - >::type indirect_set_iterator; - - typedef boost::indirect_iterator_generator< - iterator_set::iterator, - const int - >::type const_indirect_set_iterator; - - indirect_set_iterator sb(iter_set.begin()); - indirect_set_iterator se(iter_set.end()); - const_indirect_set_iterator sci(iter_set.begin()); - assert(sci == sb); - assert(sci != se); - sci = se; - assert(sci == se); - - *boost::prior(se) = 888; - assert(store.back() == 888); - assert(std::equal(sb, se, store.begin())); - - boost::bidirectional_iterator_test(boost::next(sb), store[1], store[2]); - assert(std::equal(db, de, store.begin())); - -#endif -} - -int -main() -{ - dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), - dummyT(3), dummyT(4), dummyT(5) }; - const int N = sizeof(array)/sizeof(dummyT); - - // Test indirect_iterator_generator - { - dummyT* ptr[N]; - for (int k = 0; k < N; ++k) - ptr[k] = array + k; - - typedef boost::indirect_iterator_generator::type indirect_iterator; - - typedef boost::indirect_iterator_generator::type const_indirect_iterator; - - indirect_iterator i(ptr); - boost::random_access_iterator_test(i, N, array); - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - boost::random_access_iterator_test(boost::make_indirect_iterator(ptr), N, array); -#endif - - // check operator-> - assert((*i).m_x == i->foo()); - - const_indirect_iterator j(ptr); - boost::random_access_iterator_test(j, N, array); - - dummyT*const* const_ptr = ptr; - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - boost::random_access_iterator_test(boost::make_indirect_iterator(const_ptr), N, array); -#endif - boost::const_nonconst_iterator_test(i, ++j); - - more_indirect_iterator_tests(); - } - std::cout << "test successful " << std::endl; - return 0; -} diff --git a/iter_adaptor_fail_expected1.cpp b/iter_adaptor_fail_expected1.cpp deleted file mode 100644 index 2d0288c..0000000 --- a/iter_adaptor_fail_expected1.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// Test boost/pending/iterator_adaptors.hpp - -// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 21 Jan 01 Initial version (Jeremy Siek) - -#include -#include -#include - -int main() -{ - typedef boost::iterator_adaptor::iterator, - boost::default_iterator_policies, - int,int&,int*,std::bidirectional_iterator_tag> adaptor_type; - - adaptor_type i; - i += 4; - return 0; -} diff --git a/iter_adaptor_fail_expected2.cpp b/iter_adaptor_fail_expected2.cpp deleted file mode 100644 index 592801d..0000000 --- a/iter_adaptor_fail_expected2.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Test boost/pending/iterator_adaptors.hpp - -// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 21 Jan 01 Initial version (Jeremy Siek) - -#include -#include -#include -#include - -int main() -{ - typedef boost::iterator_adaptor, - boost::default_iterator_policies, - int,int&,int*,std::input_iterator_tag> adaptor_type; - - adaptor_type iter; - --iter; - return 0; -} diff --git a/iter_traits_gen_test.cpp b/iter_traits_gen_test.cpp deleted file mode 100644 index ca214d4..0000000 --- a/iter_traits_gen_test.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// 04 Nov 2001 Jeremy Siek -// Updated with respect to new named parameter interface. -// 08 Mar 2001 Jeremy Siek -// Initial checkin. - -#include -#include -#include - -class bar { }; -void foo(bar) { } - -int -main() -{ - using boost::dummyT; - dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), - dummyT(3), dummyT(4), dummyT(5) }; - typedef boost::iterator_adaptor my_iter; - my_iter mi(array); - - { - typedef boost::iterator_adaptor, - boost::iterator_category_is > iter_type; - - BOOST_STATIC_ASSERT((boost::is_same::value)); - - BOOST_STATIC_ASSERT(( ! boost::is_convertible::value)); - - iter_type i(mi); - boost::input_iterator_test(i, dummyT(0), dummyT(1)); - } - { - typedef boost::iterator_adaptor, - boost::reference_is, - boost::pointer_is , - boost::iterator_category_is, - boost::difference_type_is > adaptor_type; - - adaptor_type i(array); - - boost::input_iterator_test(i, dummyT(0), dummyT(1)); - int zero = 0; - if (zero) // don't do this, just make sure it compiles - assert((*i).m_x == i->foo()); - } - - return 0; -} diff --git a/iterator_adaptor_examples.cpp b/iterator_adaptor_examples.cpp deleted file mode 100644 index 917fd02..0000000 --- a/iterator_adaptor_examples.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - - -#include -#include -#include -#include -#include - -int -main(int, char*[]) -{ - // This is a simple example of using the transform_iterators class to - // generate iterators that multiply the value returned by dereferencing - // the iterator. In this case we are multiplying by 2. - // Would be cooler to use lambda library in this example. - - int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; - - typedef std::binder1st< std::multiplies > Function; - typedef boost::transform_iterator_generator::type doubling_iterator; - - doubling_iterator i(x, std::bind1st(std::multiplies(), 2)), - i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies(), 2)); - - std::cout << "multiplying the array by 2:" << std::endl; - while (i != i_end) - std::cout << *i++ << " "; - std::cout << std::endl; - - // Here is an example of counting from 0 to 5 using the integer_range class. - - boost::integer_range r(0,5); - - std::cout << "counting to from 0 to 4:" << std::endl; - std::copy(r.begin(), r.end(), std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; - - return 0; -} - - diff --git a/iterator_adaptor_test.cpp b/iterator_adaptor_test.cpp deleted file mode 100644 index 74eca35..0000000 --- a/iterator_adaptor_test.cpp +++ /dev/null @@ -1,449 +0,0 @@ -// Test boost/iterator_adaptors.hpp - -// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// 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 -// on MSVC. Hack around an MSVC-with-STLport internal compiler -// error. (David Abrahams) -// 11 Feb 01 Added test of operator-> for forward and input iterators. -// (Jeremy Siek) -// 11 Feb 01 Borland fixes (David Abrahams) -// 10 Feb 01 Use new adaptors interface. (David Abrahams) -// 10 Feb 01 Use new filter_ interface. (David Abrahams) -// 09 Feb 01 Use new reverse_ and indirect_ interfaces. Replace -// BOOST_NO_STD_ITERATOR_TRAITS with -// BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION to prove we've -// normalized to core compiler capabilities (David Abrahams) -// 08 Feb 01 Use Jeremy's new make_reverse_iterator form; add more -// comprehensive testing. Force-decay array function arguments to -// pointers. -// 07 Feb 01 Added tests for the make_xxx_iterator() helper functions. -// (Jeremy Siek) -// 07 Feb 01 Replaced use of xxx_pair_generator with xxx_generator where -// possible (which was all but the projection iterator). -// (Jeremy Siek) -// 06 Feb 01 Removed now-defaulted template arguments where possible -// Updated names to correspond to new generator naming convention. -// Added a trivial test for make_transform_iterator(). -// Gave traits for const iterators a mutable value_type, per std. -// Resurrected my original tests for indirect iterators. -// (David Abrahams) -// 04 Feb 01 Fix for compilers without standard iterator_traits -// (David Abrahams) -// 13 Jun 00 Added const version of the iterator tests (Jeremy Siek) -// 12 Dec 99 Initial version with iterator operators (Jeremy Siek) - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct my_iterator_tag : public std::random_access_iterator_tag { }; - -using boost::dummyT; - - -struct mult_functor { - typedef int result_type; - typedef int argument_type; - // Functors used with transform_iterator must be - // DefaultConstructible, as the transform_iterator must be - // DefaultConstructible to satisfy the requirements for - // TrivialIterator. - mult_functor() { } - mult_functor(int aa) : a(aa) { } - int operator()(int b) const { return a * b; } - int a; -}; - -template -struct select1st_ - : public std::unary_function -{ - const typename Pair::first_type& operator()(const Pair& x) const { - return x.first; - } - typename Pair::first_type& operator()(Pair& x) const { - return x.first; - } -}; - -struct one_or_four { - bool operator()(dummyT x) const { - return x.foo() == 1 || x.foo() == 4; - } -}; - -typedef std::deque storage; -typedef std::deque pointer_deque; -typedef std::set iterator_set; - -template struct foo; - -void blah(int) { } - -struct my_gen -{ - typedef int result_type; - my_gen() : n(0) { } - int operator()() { return ++n; } - int n; -}; - -int -main() -{ - dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), - dummyT(3), dummyT(4), dummyT(5) }; - const int N = sizeof(array)/sizeof(dummyT); - - // sanity check, if this doesn't pass the test is buggy - boost::random_access_iterator_test(array, N, array); - - // Check that the policy concept checks and the default policy - // implementation match up. - boost::function_requires< - boost::RandomAccessIteratorPoliciesConcept< - boost::default_iterator_policies, - boost::iterator_adaptor, - boost::iterator - > >(); - - // Test the named parameters - { - // Test computation of defaults - typedef boost::iterator_adaptor > Iter1; - // don't use std::iterator_traits here to avoid VC++ problems - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); - } - { - // Test computation of default when the Value is const - typedef boost::iterator_adaptor::iterator, - boost::default_iterator_policies, - boost::value_type_is > Iter1; - BOOST_STATIC_ASSERT((boost::is_same::value)); -#if defined(__BORLANDC__) || defined(BOOST_MSVC) - // We currently don't know how to workaround this bug. - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); -#else - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); -#endif - } - { - // Test with no defaults - typedef boost::iterator_adaptor, - boost::pointer_is, - boost::value_type_is, - boost::iterator_category_is, - boost::difference_type_is - > Iter1; - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::value)); - } - - // Test the iterator_adaptor - { - boost::iterator_adaptor i(array); - boost::random_access_iterator_test(i, N, array); - - boost::iterator_adaptor j(array); - boost::random_access_iterator_test(j, N, array); - boost::const_nonconst_iterator_test(i, ++j); - } - - // Test projection_iterator_pair_generator - { - typedef std::pair Pair; - Pair pair_array[N]; - for (int k = 0; k < N; ++k) - pair_array[k].first = array[k]; - - typedef boost::projection_iterator_pair_generator, - Pair*, const Pair* - > Projection; - - Projection::iterator i(pair_array); - boost::random_access_iterator_test(i, N, array); - - boost::random_access_iterator_test(boost::make_projection_iterator(pair_array, select1st_()), N, array); - boost::random_access_iterator_test(boost::make_projection_iterator< select1st_ >(pair_array), N, array); - - Projection::const_iterator j(pair_array); - boost::random_access_iterator_test(j, N, array); - - boost::random_access_iterator_test(boost::make_const_projection_iterator(pair_array, select1st_()), N, array); - boost::random_access_iterator_test(boost::make_const_projection_iterator >(pair_array), N, array); - - boost::const_nonconst_iterator_test(i, ++j); - } - - // Test reverse_iterator_generator - { - dummyT reversed[N]; - std::copy(array, array + N, reversed); - std::reverse(reversed, reversed + N); - - typedef boost::reverse_iterator_generator::type reverse_iterator; - - reverse_iterator i(reversed + N); - boost::random_access_iterator_test(i, N, array); - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); -#endif - - typedef boost::reverse_iterator_generator::type const_reverse_iterator; - - const_reverse_iterator j(reversed + N); - boost::random_access_iterator_test(j, N, array); - - const dummyT* const_reversed = reversed; - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); -#endif - - boost::const_nonconst_iterator_test(i, ++j); - } - - // Test reverse_iterator_generator again, with traits fully deducible on all platforms - { - std::deque reversed_container; - std::reverse_copy(array, array + N, std::back_inserter(reversed_container)); - const std::deque::iterator reversed = reversed_container.begin(); - - - typedef boost::reverse_iterator_generator< - std::deque::iterator>::type reverse_iterator; - typedef boost::reverse_iterator_generator< - std::deque::const_iterator, const dummyT>::type const_reverse_iterator; - - // MSVC/STLport gives an INTERNAL COMPILER ERROR when any computation - // (e.g. "reversed + N") is used in the constructor below. - const std::deque::iterator finish = reversed_container.end(); - reverse_iterator i(finish); - - boost::random_access_iterator_test(i, N, array); - boost::random_access_iterator_test(boost::make_reverse_iterator(reversed + N), N, array); - - const_reverse_iterator j = reverse_iterator(finish); - boost::random_access_iterator_test(j, N, array); - - const std::deque::const_iterator const_reversed = reversed; - boost::random_access_iterator_test(boost::make_reverse_iterator(const_reversed + N), N, array); - - // Many compilers' builtin deque iterators don't interoperate well, though - // STLport fixes that problem. -#if defined(__SGI_STL_PORT) || !defined(__GNUC__) && !defined(__BORLANDC__) && !defined(BOOST_MSVC) - boost::const_nonconst_iterator_test(i, ++j); -#endif - } - - // Test integer_range's iterators - { - int int_array[] = { 0, 1, 2, 3, 4, 5 }; - boost::integer_range r(0, 5); - boost::random_access_iterator_test(r.begin(), r.size(), int_array); - } - - // Test filter iterator - { - // Using typedefs for filter_gen::type confused Borland terribly. - typedef boost::detail::non_bidirectional_category::type category; - - typedef boost::filter_iterator_generator::type filter_iter; - -#if defined(__BORLANDC__) - // 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)); -#else - filter_iter i(array, filter_iter::policies_type(one_or_four(), array + N)); - boost::forward_iterator_test(i, dummyT(1), dummyT(4)); -#endif - -#if !defined(__BORLANDC__) - // - enum { is_forward = boost::is_same< - filter_iter::iterator_category, - std::forward_iterator_tag>::value }; - BOOST_STATIC_ASSERT(is_forward); -#endif - - // On compilers not supporting partial specialization, we can do more type - // deduction with deque iterators than with pointers... unless the library - // is broken ;-( -#if !defined(BOOST_MSVC) || defined(__SGI_STL_PORT) - std::deque array2; - std::copy(array+0, array+N, std::back_inserter(array2)); - boost::forward_iterator_test( - boost::make_filter_iterator(array2.begin(), array2.end(), one_or_four()), - dummyT(1), dummyT(4)); - - boost::forward_iterator_test( - boost::make_filter_iterator(array2.begin(), array2.end()), - dummyT(1), dummyT(4)); -#endif - -#if !defined(BOOST_MSVC) // This just freaks MSVC out completely - boost::forward_iterator_test( - boost::make_filter_iterator( - boost::make_reverse_iterator(array2.end()), - boost::make_reverse_iterator(array2.begin()) - ), - dummyT(4), dummyT(1)); -#endif - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - boost::forward_iterator_test( - boost::make_filter_iterator(array+0, array+N, one_or_four()), - dummyT(1), dummyT(4)); - - boost::forward_iterator_test( - boost::make_filter_iterator(array, array + N), - dummyT(1), dummyT(4)); - -#endif - } - - // check operator-> with a forward iterator - { - boost::forward_iterator_archetype forward_iter; -#if defined(__BORLANDC__) - typedef boost::iterator_adaptor, - boost::default_iterator_policies, - dummyT, const dummyT&, const dummyT*, - std::forward_iterator_tag, std::ptrdiff_t> adaptor_type; -#else - typedef boost::iterator_adaptor, - boost::default_iterator_policies, - boost::reference_is, - boost::pointer_is , - boost::iterator_category_is, - boost::value_type_is, - boost::difference_type_is - > adaptor_type; -#endif - adaptor_type i(forward_iter); - int zero = 0; - if (zero) // don't do this, just make sure it compiles - assert((*i).m_x == i->foo()); - } - // check operator-> with an input iterator - { - boost::input_iterator_archetype input_iter; - typedef boost::iterator_adaptor, - boost::default_iterator_policies, - dummyT, const dummyT&, const dummyT*, - std::input_iterator_tag, std::ptrdiff_t> adaptor_type; - adaptor_type i(input_iter); - int zero = 0; - 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::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; -} diff --git a/iterator_adaptors.pdf b/iterator_adaptors.pdf deleted file mode 100644 index 6ae01b0aaf00b2db1ef3cda524c9b0c9c188eec0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84856 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�yd~$%wOh|N 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­Xn!{0{9yj!Y74K}kHt46`h&aJVotX4+&HjK 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 LgY1Q2QuPA>5%xMT diff --git a/iterator_traits_test.cpp b/iterator_traits_test.cpp deleted file mode 100644 index 3331d78..0000000 --- a/iterator_traits_test.cpp +++ /dev/null @@ -1,215 +0,0 @@ -// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 04 Mar 2001 Patches for Intel C++ (Dave Abrahams) -// 19 Feb 2001 Take advantage of improved iterator_traits to do more tests -// on MSVC. Reordered some #ifdefs for coherency. -// (David Abrahams) -// 13 Feb 2001 Test new VC6 workarounds (David Abrahams) -// 11 Feb 2001 Final fixes for Borland (David Abrahams) -// 11 Feb 2001 Some fixes for Borland get it closer on that compiler -// (David Abrahams) -// 07 Feb 2001 More comprehensive testing; factored out static tests for -// better reuse (David Abrahams) -// 21 Jan 2001 Quick fix to my_iterator, which wasn't returning a -// reference type from operator* (David Abrahams) -// 19 Jan 2001 Initial version with iterator operators (David Abrahams) - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// An iterator for which we can get traits. -struct my_iterator1 - : boost::forward_iterator_helper -{ - my_iterator1(const char* p) : m_p(p) {} - - bool operator==(const my_iterator1& rhs) const - { return this->m_p == rhs.m_p; } - - my_iterator1& operator++() { ++this->m_p; return *this; } - const char& operator*() { return *m_p; } - private: - const char* m_p; -}; - -// Used to prove that we don't require std::iterator<> in the hierarchy under -// MSVC6, and that we can compute all the traits for a standard-conforming UDT -// iterator. -struct my_iterator2 - : boost::equality_comparable > > -{ - typedef char value_type; - typedef long difference_type; - typedef const char* pointer; - typedef const char& reference; - typedef std::forward_iterator_tag iterator_category; - - my_iterator2(const char* p) : m_p(p) {} - - bool operator==(const my_iterator2& rhs) const - { return this->m_p == rhs.m_p; } - - my_iterator2& operator++() { ++this->m_p; return *this; } - const char& operator*() { return *m_p; } - private: - const char* m_p; -}; - -// Used to prove that we're not overly confused by the existence of -// std::iterator<> in the hierarchy under MSVC6 - we should find that -// boost::detail::iterator_traits::difference_type is int. -struct my_iterator3 : my_iterator1 -{ - typedef int difference_type; - my_iterator3(const char* p) : my_iterator1(p) {} -}; - -template -struct non_portable_tests -{ - // Unfortunately, the VC6 standard library doesn't supply these :( - typedef typename boost::detail::iterator_traits::pointer test_pt; - typedef typename boost::detail::iterator_traits::reference test_rt; - BOOST_STATIC_ASSERT(( - ::boost::is_same< - test_pt, - pointer - >::value)); - - BOOST_STATIC_ASSERT(( - ::boost::is_same< - test_rt, - reference - >::value)); -}; - -template -struct portable_tests -{ - typedef typename boost::detail::iterator_traits::difference_type test_dt; - typedef typename boost::detail::iterator_traits::iterator_category test_cat; - BOOST_STATIC_ASSERT(( - ::boost::is_same< - test_dt, - difference_type - >::value)); - - BOOST_STATIC_ASSERT(( - ::boost::is_same< - test_cat, - category - >::value)); -}; - -// Test iterator_traits -template -struct input_iterator_test - : portable_tests -{ - typedef typename boost::detail::iterator_traits::value_type test_vt; - BOOST_STATIC_ASSERT(( - ::boost::is_same< - test_vt, - value_type - >::value)); -}; - -template -struct non_pointer_test - : input_iterator_test - , non_portable_tests -{ -}; - -template -struct maybe_pointer_test - : portable_tests -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - , non_portable_tests -#endif -{ -}; - -input_iterator_test, int, std::ptrdiff_t, int*, int&, std::input_iterator_tag> - istream_iterator_test; - -// -#if defined(__BORLANDC__) && !defined(__SGI_STL_PORT) -typedef ::std::char_traits::off_type distance; -non_pointer_test,int, - distance,int*,int&,std::output_iterator_tag> ostream_iterator_test; -#elif defined(BOOST_MSVC_STD_ITERATOR) -non_pointer_test, - int, void, void, void, std::output_iterator_tag> - ostream_iterator_test; -#else -non_pointer_test, - void, void, void, void, std::output_iterator_tag> - ostream_iterator_test; -#endif - - -#ifdef __KCC - typedef long std_list_diff_type; -#else - typedef std::ptrdiff_t std_list_diff_type; -#endif -non_pointer_test::iterator, int, std_list_diff_type, int*, int&, std::bidirectional_iterator_tag> - list_iterator_test; - -maybe_pointer_test::iterator, int, std::ptrdiff_t, int*, int&, std::random_access_iterator_tag> - vector_iterator_test; - -maybe_pointer_test - int_pointer_test; - -non_pointer_test - my_iterator1_test; - -non_pointer_test - my_iterator2_test; - -non_pointer_test - my_iterator3_test; - -int main() -{ - char chars[100]; - int ints[100]; - - for (std::ptrdiff_t length = 3; length < 100; length += length / 3) - { - std::list l(length); - assert(boost::detail::distance(l.begin(), l.end()) == length); - - std::vector v(length); - assert(boost::detail::distance(v.begin(), v.end()) == length); - - assert(boost::detail::distance(&ints[0], ints + length) == length); - assert(boost::detail::distance(my_iterator1(chars), my_iterator1(chars + length)) == length); - assert(boost::detail::distance(my_iterator2(chars), my_iterator2(chars + length)) == length); - assert(boost::detail::distance(my_iterator3(chars), my_iterator3(chars + length)) == length); - } - return 0; -} diff --git a/iterators_test.cpp b/iterators_test.cpp deleted file mode 100644 index b316e79..0000000 --- a/iterators_test.cpp +++ /dev/null @@ -1,342 +0,0 @@ -// Demonstrate and test boost/operators.hpp on std::iterators --------------// - -// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 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 // for main - -#include // for BOOST_STATIC_CONSTANT -#include // for boost::exit_success -#include // for boost::random_access_iterator_helper - -#include // for std::ptrdiff_t, std::size_t -#include // for std::strcmp -#include // for std::cout (std::endl, ends, and flush indirectly) -#include // for std::string -#include // for std::ostrstream - -# ifdef BOOST_NO_STDC_NAMESPACE - namespace std { using ::strcmp; } -# endif - - -// Iterator test class -template -struct test_iter - : public boost::random_access_iterator_helper< - test_iter, T, std::ptrdiff_t, P, R> -{ - typedef test_iter self; - typedef R Reference; - typedef std::ptrdiff_t Distance; - -public: - explicit test_iter(T* i =0) : _i(i) { } - test_iter(const self& x) : _i(x._i) { } - self& operator=(const self& x) { _i = x._i; return *this; } - Reference operator*() const { return *_i; } - self& operator++() { ++_i; return *this; } - self& operator--() { --_i; return *this; } - self& operator+=(Distance n) { _i += n; return *this; } - self& operator-=(Distance n) { _i -= n; return *this; } - bool operator==(const self& x) const { return _i == x._i; } - bool operator<(const self& x) const { return _i < x._i; } - friend Distance operator-(const self& x, const self& y) { - return x._i - y._i; - } -protected: - P _i; -}; - -// Iterator operator testing classes -class test_opr_base -{ -protected: - // Test data and types - BOOST_STATIC_CONSTANT( std::size_t, fruit_length = 6u ); - BOOST_STATIC_CONSTANT( std::size_t, scratch_length = 40u ); - - typedef std::string fruit_array_type[ fruit_length ]; - typedef char scratch_array_type[ scratch_length ]; - - static fruit_array_type fruit; - static scratch_array_type scratch; - -}; // test_opr_base - -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -// A definition is required even for integral static constants -const std::size_t test_opr_base::fruit_length; -const std::size_t test_opr_base::scratch_length; -#endif - -template -class test_opr - : public test_opr_base -{ - typedef test_opr self_type; - -public: - // Types - typedef T value_type; - typedef R reference; - typedef P pointer; - - typedef test_iter 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 test_opr::iter_type const - test_opr::fruit_begin = test_iter( fruit ); - -template -typename test_opr::iter_type const - test_opr::fruit_end = test_iter( fruit + fruit_length ); - - -// Main testing function -int -test_main( int , char * [] ) -{ - using std::string; - - typedef test_opr test1_type; - typedef test_opr test2_type; - - test1_type::master_test( "non-const string" ); - test2_type::master_test( "const string" ); - - return boost::exit_success; -} - -// Tests for all of the operators added by random_access_iterator_helper -template -void -test_opr::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 -void -test_opr::post_increment_test -( -) -{ - std::cout << "\tDoing post-increment test." << std::endl; - - std::ostrstream oss( scratch, scratch_length ); - for ( iter_type i = fruit_begin ; i != fruit_end ; ) - { - oss << *i++ << ' '; - } - - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ") - == 0 ); -} - -// Test post-decrement -template -void -test_opr::post_decrement_test -( -) -{ - std::cout << "\tDoing post-decrement test." << std::endl; - - std::ostrstream oss( scratch, scratch_length ); - for ( iter_type i = fruit_end ; i != fruit_begin ; ) - { - i--; - oss << *i << ' '; - } - - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "plum grape peach pear orange apple ") - == 0 ); -} - -// Test indirect structure referral -template -void -test_opr::indirect_referral_test -( -) -{ - std::cout << "\tDoing indirect reference test." << std::endl; - - std::ostrstream oss( scratch, scratch_length ); - for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) - { - oss << i->size() << ' '; - } - - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "5 6 4 5 5 4 ") == 0 ); -} - -// Test offset addition -template -void -test_opr::offset_addition_test -( -) -{ - std::cout << "\tDoing offset addition test." << std::endl; - - std::ptrdiff_t const two = 2; - std::ostrstream oss( scratch, scratch_length ); - for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two ) - { - oss << *i << ' '; - } - - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 ); -} - -// Test offset addition, in reverse order -template -void -test_opr::reverse_offset_addition_test -( -) -{ - std::cout << "\tDoing reverse offset addition test." << std::endl; - - std::ptrdiff_t const two = 2; - std::ostrstream oss( scratch, scratch_length ); - for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i ) - { - oss << *i << ' '; - } - - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "apple pear grape ") == 0 ); -} - -// Test offset subtraction -template -void -test_opr::offset_subtraction_test -( -) -{ - std::cout << "\tDoing offset subtraction test." << std::endl; - - std::ptrdiff_t const two = 2; - std::ostrstream oss( scratch, scratch_length ); - for ( iter_type i = fruit_end ; fruit_begin < i ; ) - { - i = i - two; - if ( (fruit_begin < i) || (fruit_begin == i) ) - { - oss << *i << ' '; - } - } - - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "grape pear apple ") == 0 ); -} - -// Test comparisons -template -void -test_opr::comparison_test -( -) -{ - using std::cout; - using std::ptrdiff_t; - - cout << "\tDoing comparison tests.\n\t\tPass:"; - - for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) - { - ptrdiff_t const i_offset = i - fruit_begin; - - cout << ' ' << *i << std::flush; - for ( iter_type j = fruit_begin ; j != fruit_end ; ++j ) - { - ptrdiff_t const j_offset = j - fruit_begin; - - BOOST_TEST( (i != j) == (i_offset != j_offset) ); - BOOST_TEST( (i > j) == (i_offset > j_offset) ); - BOOST_TEST( (i <= j) == (i_offset <= j_offset) ); - BOOST_TEST( (i >= j) == (i_offset >= j_offset) ); - } - } - cout << std::endl; -} - -// Test indexing -template -void -test_opr::indexing_test -( -) -{ - std::cout << "\tDoing indexing test." << std::endl; - - std::ostrstream oss( scratch, scratch_length ); - for ( std::size_t k = 0u ; k < fruit_length ; ++k ) - { - oss << fruit_begin[ k ] << ' '; - } - - oss << std::ends; - BOOST_TEST( std::strcmp(oss.str(), "apple orange pear peach grape plum ") - == 0 ); -} diff --git a/noncopyable_test.cpp b/noncopyable_test.cpp deleted file mode 100644 index 9986401..0000000 --- a/noncopyable_test.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// boost class noncopyable test program ------------------------------------// - -// (C) Copyright boost.org 1999. Permission to copy, use, modify, sell -// and distribute this software is granted provided this copyright -// notice appears in all copies. This software is provided "as is" without -// express or implied warranty, and with no claim as to its suitability for -// any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 9 Jun 99 Add unnamed namespace -// 2 Jun 99 Initial Version - -#include -#include - -// This program demonstrates compiler errors resulting from trying to copy -// construct or copy assign a class object derived from class noncopyable. - -namespace -{ - class DontTreadOnMe : private boost::noncopyable - { - public: - DontTreadOnMe() { std::cout << "defanged!" << std::endl; } - }; // DontTreadOnMe - -} // unnamed namespace - -int main() -{ - DontTreadOnMe object1; - DontTreadOnMe object2(object1); - object1 = object2; - return 0; -} // main - diff --git a/numeric_traits_test.cpp b/numeric_traits_test.cpp deleted file mode 100644 index df20f77..0000000 --- a/numeric_traits_test.cpp +++ /dev/null @@ -1,387 +0,0 @@ -// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 1 Apr 2001 Fixes for ICL; use BOOST_STATIC_CONSTANT -// 11 Feb 2001 Fixes for Borland (David Abrahams) -// 23 Jan 2001 Added test for wchar_t (David Abrahams) -// 23 Jan 2001 Now statically selecting a test for signed numbers to avoid -// warnings with fancy compilers. Added commentary and -// additional dumping of traits data for tested types (David -// Abrahams). -// 21 Jan 2001 Initial version (David Abrahams) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef BOOST_NO_LIMITS -# include -#endif - -// ================================================================================= -// template class complement_traits -- -// -// statically computes the max and min for 1s and 2s-complement binary -// numbers. This helps on platforms without support. It also shows -// an example of a recursive template that works with MSVC! -// - -template struct complement; // forward - -// The template complement, below, does all the real work, using "poor man's -// partial specialization". We need complement_traits_aux<> so that MSVC doesn't -// complain about undefined min/max as we're trying to recursively define them. -template -struct complement_traits_aux -{ - BOOST_STATIC_CONSTANT(Number, max = complement::template traits::max); - BOOST_STATIC_CONSTANT(Number, min = complement::template traits::min); -}; - -template -struct complement -{ - template - struct traits - { - private: - // indirection through complement_traits_aux neccessary to keep MSVC happy - typedef complement_traits_aux prev; - public: - BOOST_STATIC_CONSTANT(Number, max = - Number(Number(prev::max) << CHAR_BIT) - + Number(UCHAR_MAX)); - - BOOST_STATIC_CONSTANT(Number, min = Number(Number(prev::min) << CHAR_BIT)); - }; -}; - -// Template class complement_base<> -- defines values for min and max for -// complement<1>, at the deepest level of recursion. Uses "poor man's partial -// specialization" again. -template struct complement_base; - -template <> struct complement_base -{ - template - struct values - { - BOOST_STATIC_CONSTANT(Number, min = 0); - BOOST_STATIC_CONSTANT(Number, max = UCHAR_MAX); - }; -}; - -template <> struct complement_base -{ - template - struct values - { - BOOST_STATIC_CONSTANT(Number, min = SCHAR_MIN); - BOOST_STATIC_CONSTANT(Number, max = SCHAR_MAX); - }; -}; - -// Base specialization of complement, puts an end to the recursion. -template <> -struct complement<1> -{ - template - struct traits - { - BOOST_STATIC_CONSTANT(bool, is_signed = boost::detail::is_signed::value); - BOOST_STATIC_CONSTANT(Number, min = - complement_base::template values::min); - BOOST_STATIC_CONSTANT(Number, max = - complement_base::template values::max); - }; -}; - -// Now here's the "pretty" template you're intended to actually use. -// complement_traits::min, complement_traits::max are the -// minimum and maximum values of Number if Number is a built-in integer type. -template -struct complement_traits -{ - BOOST_STATIC_CONSTANT(Number, max = (complement_traits_aux::max)); - BOOST_STATIC_CONSTANT(Number, min = (complement_traits_aux::min)); -}; - -// ================================================================================= - -// Support for streaming various numeric types in exactly the format I want. I -// needed this in addition to all the assertions so that I could see exactly -// what was going on. -// -// Numbers go through a 2-stage conversion process (by default, though, no real -// conversion). -// -template struct stream_as { - typedef T t1; - typedef T t2; -}; - -// char types first get converted to unsigned char, then to unsigned. -template <> struct stream_as { - typedef unsigned char t1; - typedef unsigned t2; -}; -template <> struct stream_as { - typedef unsigned char t1; typedef unsigned t2; -}; -template <> struct stream_as { - typedef unsigned char t1; typedef unsigned t2; -}; - -#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in - -// With this library implementation, __int64 and __uint64 get streamed as strings -template <> struct stream_as { - typedef std::string t1; - typedef std::string t2; -}; - -template <> struct stream_as { - typedef std::string t1; - typedef std::string t2; -}; -#endif - -// Standard promotion process for streaming -template struct promote -{ - static typename stream_as::t1 from(T x) { - typedef typename stream_as::t1 t1; - return t1(x); - } -}; - -#if defined(BOOST_MSVC_STD_ITERATOR) // No intmax streaming built-in - -// On this platform, stream them as long/unsigned long if they fit. -// Otherwise, write a string. -template <> struct promote { - std::string static from(const boost::uintmax_t x) { - if (x > ULONG_MAX) - return std::string("large unsigned value"); - else - return boost::lexical_cast((unsigned long)x); - } -}; -template <> struct promote { - std::string static from(const boost::intmax_t x) { - if (x > boost::intmax_t(ULONG_MAX)) - return std::string("large positive signed value"); - else if (x >= 0) - return boost::lexical_cast((unsigned long)x); - - if (x < boost::intmax_t(LONG_MIN)) - return std::string("large negative signed value"); - else - return boost::lexical_cast((long)x); - } -}; -#endif - -// This is the function which converts types to the form I want to stream them in. -template -typename stream_as::t2 stream_number(T x) -{ - return promote::from(x); -} -// ================================================================================= - -// -// Tests for built-in signed and unsigned types -// - -// Tag types for selecting tests -struct unsigned_tag {}; -struct signed_tag {}; - -// Tests for unsigned numbers. The extra default Number parameter works around -// an MSVC bug. -template -void test_aux(unsigned_tag, Number* = 0) -{ - typedef typename boost::detail::numeric_traits::difference_type difference_type; - BOOST_STATIC_ASSERT(!boost::detail::is_signed::value); - BOOST_STATIC_ASSERT( - (sizeof(Number) < sizeof(boost::intmax_t)) - | (boost::is_same::value)); - - // Force casting to Number here to work around the fact that it's an enum on MSVC - BOOST_STATIC_ASSERT(Number(complement_traits::max) > Number(0)); - BOOST_STATIC_ASSERT(Number(complement_traits::min) == Number(0)); - - const Number max = complement_traits::max; - const Number min = complement_traits::min; - - const Number test_max = (sizeof(Number) < sizeof(boost::intmax_t)) - ? max - : max / 2 - 1; - - std::cout << std::hex << "(unsigned) min = " << stream_number(min) << ", max = " - << stream_number(max) << "..." << std::flush; - std::cout << "difference_type = " << typeid(difference_type).name() << "..." - << std::flush; - - difference_type d1 = boost::detail::numeric_distance(Number(0), test_max); - difference_type d2 = boost::detail::numeric_distance(test_max, Number(0)); - - std::cout << "0->" << stream_number(test_max) << "==" << std::dec << stream_number(d1) << "; " - << std::hex << stream_number(test_max) << "->0==" << std::dec << stream_number(d2) << "..." << std::flush; - - assert(d1 == difference_type(test_max)); - assert(d2 == -difference_type(test_max)); -} - -// Tests for signed numbers. The extra default Number parameter works around an -// MSVC bug. -struct out_of_range_tag {}; -struct in_range_tag {}; - -// This test morsel gets executed for numbers whose difference will always be -// representable in intmax_t -template -void signed_test(in_range_tag, Number* = 0) -{ - BOOST_STATIC_ASSERT(boost::detail::is_signed::value); - typedef typename boost::detail::numeric_traits::difference_type difference_type; - const Number max = complement_traits::max; - const Number min = complement_traits::min; - - difference_type d1 = boost::detail::numeric_distance(min, max); - difference_type d2 = boost::detail::numeric_distance(max, min); - - std::cout << stream_number(min) << "->" << stream_number(max) << "=="; - std::cout << std::dec << stream_number(d1) << "; "; - std::cout << std::hex << stream_number(max) << "->" << stream_number(min) - << "==" << std::dec << stream_number(d2) << "..." << std::flush; - assert(d1 == difference_type(max) - difference_type(min)); - assert(d2 == difference_type(min) - difference_type(max)); -} - -// This test morsel gets executed for numbers whose difference may exceed the -// capacity of intmax_t. -template -void signed_test(out_of_range_tag, Number* = 0) -{ - BOOST_STATIC_ASSERT(boost::detail::is_signed::value); - typedef typename boost::detail::numeric_traits::difference_type difference_type; - const Number max = complement_traits::max; - const Number min = complement_traits::min; - - difference_type min_distance = complement_traits::min; - difference_type max_distance = complement_traits::max; - - const Number n1 = Number(min + max_distance); - const Number n2 = Number(max + min_distance); - difference_type d1 = boost::detail::numeric_distance(min, n1); - difference_type d2 = boost::detail::numeric_distance(max, n2); - - std::cout << stream_number(min) << "->" << stream_number(n1) << "=="; - std::cout << std::dec << stream_number(d1) << "; "; - std::cout << std::hex << stream_number(max) << "->" << stream_number(n2) - << "==" << std::dec << stream_number(d2) << "..." << std::flush; - assert(d1 == max_distance); - assert(d2 == min_distance); -} - -template -void test_aux(signed_tag, Number* = 0) -{ - typedef typename boost::detail::numeric_traits::difference_type difference_type; - BOOST_STATIC_ASSERT(boost::detail::is_signed::value); - BOOST_STATIC_ASSERT( - (sizeof(Number) < sizeof(boost::intmax_t)) - | (boost::is_same::value)); - - // Force casting to Number here to work around the fact that it's an enum on MSVC - BOOST_STATIC_ASSERT(Number(complement_traits::max) > Number(0)); - BOOST_STATIC_ASSERT(Number(complement_traits::min) < Number(0)); - - const Number max = complement_traits::max; - const Number min = complement_traits::min; - - std::cout << std::hex << "min = " << stream_number(min) << ", max = " - << stream_number(max) << "..." << std::flush; - std::cout << "difference_type = " << typeid(difference_type).name() << "..." - << std::flush; - - typedef typename boost::detail::if_true< - (sizeof(Number) < sizeof(boost::intmax_t))> - ::template then< - in_range_tag, - out_of_range_tag - >::type - range_tag; - signed_test(range_tag()); -} - - -// Test for all numbers. The extra default Number parameter works around an MSVC -// bug. -template -void test(Number* = 0) -{ - std::cout << "testing " << typeid(Number).name() << ":\n" -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - << "is_signed: " << (std::numeric_limits::is_signed ? "true\n" : "false\n") - << "is_bounded: " << (std::numeric_limits::is_bounded ? "true\n" : "false\n") - << "digits: " << std::numeric_limits::digits << "\n" -#endif - << "..." << std::flush; - - // factoring out difference_type for the assert below confused Borland :( - typedef boost::detail::is_signed< -#ifndef BOOST_MSVC - typename -#endif - boost::detail::numeric_traits::difference_type - > is_signed; - BOOST_STATIC_ASSERT(is_signed::value); - - typedef typename boost::detail::if_true< - boost::detail::is_signed::value - >::template then::type signedness; - - test_aux(signedness()); - std::cout << "passed" << std::endl; -} - -int main() -{ - test(); - test(); - test(); - test(); - test(); - test(); - test(); - test(); - test(); - test(); -#if defined(BOOST_HAS_LONG_LONG) && !defined(BOOST_NO_INTEGRAL_INT64_T) - test(); - test(); -#elif defined(BOOST_MSVC) - // The problem of not having compile-time static class constants other than - // enums prevents this from working, since values get truncated. - // test(); - // test(); -#endif - return 0; -} diff --git a/operators.htm b/operators.htm deleted file mode 100644 index 11699d9..0000000 --- a/operators.htm +++ /dev/null @@ -1,1387 +0,0 @@ - - - - - -Header <boost/operators.hpp> Documentation - - - - -

c++boost.gif (8819 bytes)Header <boost/operators.hpp>

- -

The header <boost/operators.hpp> -supplies several sets of class templates (in namespace -boost). These templates define operators at namespace -scope in terms of a minimal number of fundamental operators -provided by the class.

- -

Contents

- - - -

Rationale

- -

Overloaded operators for class types typically occur in groups. If -you can write x + y, you probably also want to be able to -write x += y. If you can write x < y, you -also want x > y, x >= y, and x <= y. -Moreover, unless your class has really surprising behavior, some of -these related operators can be defined in terms of others (e.g. x ->= y <=> !(x < y)). Replicating this boilerplate for -multiple classes is both tedious and error-prone. The boost/operators.hpp -templates help by generating operators for you at namespace scope based -on other operators you've defined in your class.

- -

If, for example, you declare a class like this:

- -
-
class MyInt
-    : boost::operators<MyInt>
-{
-    bool operator<(const MyInt& x) const; 
-    bool operator==(const MyInt& x) const;
-    MyInt& operator+=(const MyInt& x);    
-    MyInt& operator-=(const MyInt& x);    
-    MyInt& operator*=(const MyInt& x);    
-    MyInt& operator/=(const MyInt& x);    
-    MyInt& operator%=(const MyInt& x);    
-    MyInt& operator|=(const MyInt& x);    
-    MyInt& operator&=(const MyInt& x);    
-    MyInt& operator^=(const MyInt& x);    
-    MyInt& operator++();    
-    MyInt& operator--();    
-};
-
- -

then the operators<> -template adds more than a dozen additional operators, such as -operator>, <=, >=, and -(binary) +. Two-argument forms of -the templates are also provided to allow interaction with other types.

- -

Summary of Template Semantics

- -
    -
  1. Each operator template completes the concept(s) it describes by - defining overloaded operators for its target class.
  2. - -
  3. The name of an operator class template indicates the concept that its target class will - model.
  4. - -
  5. Usually, the target class uses an instantation of the operator class - template as a base class. Some operator templates support an - alternate method.
  6. - -
  7. The concept can be compound, i.e. it may represent a - common combination of other, simpler concepts.
  8. - -
  9. Most operator templates require their target class to support - operations related to the operators supplied by the template. In - accordance with widely accepted coding style - recommendations, the target class is often required to - supply the assignment counterpart operator of the concept's - "main operator." For example, the addable - template requires operator+=(T const&) and - in turn supplies operator+(T const&, T - const&).
  10. -
- -

Use of concepts

- -

The discussed concepts are not necessarily the standard library's -concepts (CopyConstructible, etc.), although some of them could -be; they are what we call concepts with a small 'c'. In -particular, they are different from the former ones in that they do -not describe precise semantics of the operators they require to -be defined, except the requirements that (a) the semantics of the -operators grouped in one concept should be consistent (e.g. -effects of evaluating of a += b and a = a + b -expressions should be the same), and (b) that the return types of the -operators should follow semantics of return types of corresponding -operators for built-in types (e.g. operator< -should return a type convertible to bool, and -T::operator-= should return type convertible to -T). Such "loose" requirements make operators -library applicable to broader set of target classes from different -domains, i.e. eventually more useful.

- -

Usage

- -

Two-Argument Template Forms

- -

General Considerations

- -

The arguments to a binary operator commonly have identical types, but -it is not unusual to want to define operators which combine different -types. For example, one might want to multiply a -mathematical vector by a scalar. The two-argument template forms of the -arithmetic operator templates are supplied for this purpose. When -applying the two-argument form of a template, the desired return type of -the operators typically determines which of the two types in question -should be derived from the operator template. For example, if the -result of T + U is of type T, then -T (not U) should be derived from addable<T, U>. The comparison -templates (less_than_comparable<T, -U>, equality_comparable<T, -U>, equivalent<T, U>, -and partially_ordered<T, U>) -are exceptions to this guideline, since the return type of the operators -they define is bool.

- -

On compilers which do not support partial specialization, the -two-argument forms must be specified by using the names shown below with -the trailing '2'. The single-argument forms with the -trailing '1' are provided for symmetry and to enable -certain applications of the base class chaining -technique.

- -

Mixed Arithmetics

- -

Another application of the two-argument template forms is for -mixed arithmetics between a type T and a type U -that is convertible to T. In this case there are two ways -where the two-argument template forms are helpful: one is to provide -the respective signatures for operator overloading, the second is -performance.

- -

With respect to the operator overloading assume e.g. that -U is int, that T is an user-defined -unlimited integer type, and that double operator-(double, const -T&) exists. If one wants to compute int - T and -does not provide T operator-(int, const T&), the -compiler will consider double operator-(double, const T&) -to be a better match than T operator-(const T&, const -T&), which will probably be different from the user's intention. -To define a complete set of operator signatures, additional 'left' forms -of the two-argument template forms are provided (subtractable2_left<T, U>, -dividable2_left<T, U>, -modable2_left<T, U>) that -define the signatures for non-commutative operators where U -appears on the left hand side (operator-(const U&, const -T&), operator/(const U&, const T&), -operator%(const U&, const T&)).

- -

With respect to the performance observe that when one uses the -single type binary operator for mixed type arithmetics, the type -U argument has to be converted to type T. In -practice, however, there are often more efficient implementations of, -say T::operator-=(const U&) that avoid unnecessary -conversions from U to T. The two-argument -template forms of the arithmetic operator create additional operator -interfaces that use these more efficient implementations. There is, however, -no performance gain in the 'left' forms: they still need a conversion -from U to T and have an implementation -equivalent to the code that would be automatically created by the compiler -if it considered the single type binary operator to be the best match.

- -

Base Class Chaining and Object Size

- -

Every operator class template, except the arithmetic -examples and the iterator helpers, has an -additional, but optional, template type parameter B. This -parameter will be a publicly-derived base class of the instantiated template. -This means it must be a class type. It can be used to avoid the bloating of -object sizes that is commonly associated with multiple-inheritance from -several empty base classes (see the note for users of -older versions for more details). To provide support for a group of -operators, use the B parameter to chain operator templates -into a single-base class hierarchy, demostrated in the usage -example. The technique is also used by the composite operator templates -to group operator definitions. If a chain becomes too long for the compiler to -support, try replacing some of the operator templates with a single grouped -operator template that chains the old templates together; the length limit only -applies to the number of templates directly in the chain, not those hidden in -group templates.

- -

Caveat: to chain to a base class which is -not a Boost operator template when using the single-argument form of a Boost operator template, -you must specify the operator template with the trailing -'1' in its name. Otherwise the library will assume you -mean to define a binary operation combining the class you intend to use -as a base class and the class you're deriving.

- -

Separate, Explicit Instantiation

- -

On some compilers (e.g. Borland, GCC) even single-inheritance seems -to cause an increase in object size in some cases. If you are not defining -a class template, you may get better object-size performance by avoiding -derivation altogether, and instead explicitly instantiating the operator -template as follows:

- -
-    class myclass // lose the inheritance...
-    {
-        //...
-    };
-
-    // explicitly instantiate the operators I need.
-    template struct less_than_comparable<myclass>;
-    template struct equality_comparable<myclass>;
-    template struct incrementable<myclass>;
-    template struct decrementable<myclass>;
-    template struct addable<myclass,long>;
-    template struct subtractable<myclass,long>;
-
- -

Note that some operator templates cannot use this workaround and must -be a base class of their primary operand type. Those templates define -operators which must be member functions, and the workaround needs the -operators to be independent friend functions. The relevant templates are:

- - - -

Requirement Portability

- -

Many compilers (e.g. MSVC 6.3, GCC 2.95.2) will not enforce -the requirements in the operator template tables unless the operations -which depend on them are actually used. This is not standard-conforming -behavior. In particular, although it would be convenient to derive all -your classes which need binary operators from the -operators<> -and operators2<> -templates, regardless of whether they implement all the requirements -of those templates, this shortcut is not portable. Even if this currently -works with your compiler, it may not work later.

- -

Example

- -

This example shows how some of the arithmetic -operator templates can be used with a geometric point class (template).

- -
-template <class T>
-class point    // note: private inheritance is OK here!
-    : boost::addable< point<T>          // point + point
-    , boost::subtractable< point<T>     // point - point
-    , boost::dividable2< point<T>, T    // point / T
-    , boost::multipliable2< point<T>, T // point * T, T * point
-      > > > >
-{
-public:
-    point(T, T);
-    T x() const;
-    T y() const;
-
-    point operator+=(const point&);
-    // point operator+(point, const point&) automatically
-    // generated by addable.
-
-    point operator-=(const point&);
-    // point operator-(point, const point&) automatically
-    // generated by subtractable.
-
-    point operator*=(T);
-    // point operator*(point, const T&) and
-    // point operator*(const T&, point) auto-generated
-    // by multipliable.
-
-    point operator/=(T);
-    // point operator/(point, const T&) auto-generated
-    // by dividable.
-private:
-    T x_;
-    T y_;
-};
-
-// now use the point<> class:
-
-template <class T>
-T length(const point<T> p)
-{
-    return sqrt(p.x()*p.x() + p.y()*p.y());
-}
-
-const point<float> right(0, 1);
-const point<float> up(1, 0);
-const point<float> pi_over_4 = up + right;
-const point<float> pi_over_4_normalized = pi_over_4 / length(pi_over_4);
-
- -

Arithmetic Operators

- -

The arithmetic operator templates ease the task of creating a custom -numeric type. Given a core set of operators, the templates add related -operators to the numeric class. These operations are like the ones the -standard arithmetic types have, and may include comparisons, adding, -incrementing, logical and bitwise manipulations, etc. Further, since -most numeric types need more than one of these operators, some -templates are provided to combine several of the basic operator -templates in one declaration.

- -

The requirements for the types used to instantiate the simple operator -templates are specified in terms of expressions which must be valid and -the expression's return type. The composite operator templates only list -what other templates they use. The supplied operations and requirements -of the composite operator templates can be inferred from the operations and -requirements of the listed components.

- -

Simple Arithmetic Operators

- -

These templates are "simple" since they provide operators -based on a single operation the base type has to provide. They have an -additional optional template parameter B, which is not shown, -for the base class chaining technique. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Simple Arithmetic Operator Template Classes
- - - - - - - - - -
Key
T: primary operand typeU: alternate operand type
t, t1: values of type - Tu: value of type U
TemplateSupplied OperationsRequirements
less_than_comparable<T>
- less_than_comparable1<T>
bool operator>(const T&, const T&)
- bool operator<=(const T&, const T&)
- bool operator>=(const T&, const T&)
t < t1.
- Return convertible to bool. See the Ordering Note.
less_than_comparable<T, U>
- less_than_comparable2<T, U>
bool operator<=(const T&, const U&)
- bool operator>=(const T&, const U&)
- bool operator>(const U&, const T&)
- bool operator<(const U&, const T&)
- bool operator<=(const U&, const T&)
- bool operator>=(const U&, const T&)
t < u. t > u.
- Returns convertible to bool. See the Ordering Note.
equality_comparable<T>
- equality_comparable1<T>
bool operator!=(const T&, const T&)t == t1.
- Return convertible to bool.
equality_comparable<T, U>
- equality_comparable2<T, U>
friend bool operator==(const U&, const T&)
- friend bool operator!=(const U&, const T&)
- friend bool operator!=( const T&, const U&)
t == u.
- Return convertible to bool.
addable<T>
- addable1<T>
T operator+(T, const T&)t += t1.
- Return convertible to T.
addable<T, U>
- addable2<T, U>
T operator+(T, const U&)
- T operator+(const U&, T )
t += u.
- Return convertible to T.
subtractable<T>
- subtractable1<T>
T operator-(T, const T&)t -= t1.
- Return convertible to T.
subtractable<T, U>
- subtractable2<T, U>
T operator-(T, const U&)t -= u.
- Return convertible to T.
subtractable2_left<T, U>T operator-(const U&, const T&)T temp(u); temp -= t.
- Return convertible to T.
multipliable<T>
- multipliable1<T>
T operator*(T, const T&)t *= t1.
- Return convertible to T.
multipliable<T, U>
- multipliable2<T, U>
T operator*(T, const U&)
- T operator*(const U&, T )
t *= u.
- Return convertible to T.
dividable<T>
- dividable1<T>
T operator/(T, const T&)t /= t1.
- Return convertible to T.
dividable<T, U>
- dividable2<T, U>
T operator/(T, const U&)t /= u.
- Return convertible to T.
dividable2_left<T, U>T operator/(const U&, const T&)T temp(u); temp /= t.
- Return convertible to T.
modable<T>
- modable1<T>
T operator%(T, const T&)t %= t1.
- Return convertible to T.
modable<T, U>
- modable2<T, U>
T operator%(T, const U&)t %= u.
- Return convertible to T.
modable2_left<T, U>T operator%(const U&, const T&)T temp(u); temp %= t.
- Return convertible to T.
orable<T>
- orable1<T>
T operator|(T, const T&)t |= t1.
- Return convertible to T.
orable<T, U>
- orable2<T, U>
T operator|(T, const U&)
- T operator|(const U&, T )
t |= u.
- Return convertible to T.
andable<T>
- andable1<T>
T operator&(T, const T&)t &= t1.
- Return convertible to T.
andable<T, U>
- andable2<T, U>
T operator&(T, const U&)
- T operator&(const U&, T)
t &= u.
- Return convertible to T.
xorable<T>
- xorable1<T>
T operator^(T, const T&)t ^= t1.
- Return convertible to T.
xorable<T, U>
- xorable2<T, U>
T operator^(T, const U&)
- T operator^(const U&, T )
t ^= u.
- Return convertible to T.
incrementable<T>T operator++(T& x, int)T temp(x); ++x; return temp;
- Return convertible to T.
decrementable<T>T operator--(T& x, int)T temp(x); --x; return temp;
- Return convertible to T.
left_shiftable<T>
- left_shiftable1<T>
T operator<<(T, const T&)t <<= t1.
- Return convertible to T.
left_shiftable<T, U>
- left_shiftable2<T, U>
T operator<<(T, const U&)t <<= u.
- Return convertible to T.
right_shiftable<T>
- right_shiftable1<T>
T operator>>(T, const T&)t >>= t1.
- Return convertible to T.
right_shiftable<T, U>
- right_shiftable2<T, U>
T operator>>(T, const U&)t >>= u.
- Return convertible to T.
equivalent<T>
- equivalent1<T>
bool operator==(const T&, const T&)t < t1.
- Return convertible to bool. See the Ordering Note.
equivalent<T, U>
- equivalent2<T, U>
bool operator==(const T&, const U&)t < u. t > u.
- Returns convertible to bool. See the Ordering Note.
partially_ordered<T>
- partially_ordered1<T>
bool operator>(const T&, const T&)
- bool operator<=(const T&, const T&)
- bool operator>=(const T&, const T&)
t < t1. t == t1.
- Returns convertible to bool. See the Ordering Note.
partially_ordered<T, U>
- partially_ordered2<T, U>
bool operator<=(const T&, const U&)
- bool operator>=(const T&, const U&)
- bool operator>(const U&, const T&)
- bool operator<(const U&, const T&)
- bool operator<=(const U&, const T&)
- bool operator>=(const U&, const T&)
t < u. t > u. t == u.
- Returns convertible to bool. See the Ordering Note.
- -

Ordering Note

- -

The less_than_comparable<T> -and partially_ordered<T> -templates provide the same set of operations. However, the workings of -less_than_comparable<T> -assume that all values of type T can be placed in a total order. If -that is not true (e.g. Not-a-Number values in IEEE floating point -arithmetic), then -partially_ordered<T> -should be used. The -partially_ordered<T> -template can be used for a totally-ordered type, but it is not as efficient as -less_than_comparable<T>. -This rule also applies for -less_than_comparable<T, -U> and partially_ordered<T, -U> with respect to the ordering of all T and -U values, and for both versions of -equivalent<>. The solution for -equivalent<> is to write a -custom operator== for the target class.

- -

Grouped Arithmetic Operators

- -

The following templates provide common groups of related operations. -For example, since a type which is addable is usually also subractable, the -additive template provides the combined -operators of both. The grouped operator templates have an additional -optional template parameter B, which is not shown, for the -base class chaining technique.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Grouped Arithmetic Operator Template Classes
- - - - - -
Key
T: primary operand typeU: alternate operand type
TemplateComponent Operator Templates
totally_ordered<T>
- totally_ordered1<T>
totally_ordered<T, U>
- totally_ordered2<T, U>
additive<T>
- additive1<T>
additive<T, U>
- additive2<T, U>
multiplicative<T>
- multiplicative1<T>
multiplicative<T, U>
- multiplicative2<T, U>
integer_multiplicative<T>
- integer_multiplicative1<T>
integer_multiplicative<T, U>
- integer_multiplicative2<T, U>
arithmetic<T>
- arithmetic1<T>
arithmetic<T, U>
- arithmetic2<T, U>
integer_arithmetic<T>
- integer_arithmetic1<T>
integer_arithmetic<T, U>
- integer_arithmetic2<T, U>
bitwise<T>
- bitwise1<T>
bitwise<T, U>
- bitwise2<T, U>
unit_steppable<T>
shiftable<T>
- shiftable1<T>
shiftable<T, U>
- shiftable2<T, U>
ring_operators<T>
- ring_operators1<T>
ring_operators<T, U>
- ring_operators2<T, U>
ordered_ring_operators<T>
- ordered_ring_operators1<T>
ordered_ring_operators<T, U>
- ordered_ring_operators2<T, U>
field_operators<T>
- field_operators1<T>
field_operators<T, U>
- field_operators2<T, U>
ordered_field_operators<T>
- ordered_field_operators1<T>
ordered_field_operators<T, U>
- ordered_field_operators2<T, U>
euclidian_ring_operators<T>
- euclidian_ring_operators1<T>
euclidian_ring_operators<T, U>
- euclidian_ring_operators2<T, U>
ordered_euclidian_ring_operators<T>
- ordered_euclidian_ring_operators1<T>
ordered_euclidian_ring_operators<T, U>
- ordered_euclidian_ring_operators2<T, U>
- -

Example Templates

- -

The arithmetic operator class templates operators<> and operators2<> are examples of -non-extensible operator grouping classes. These legacy class templates, -from previous versions of the header, cannot be used for -base class chaining.

- - - - - - - - - - - - - - - - - - -
Final Arithmetic Operator Template Classes
- - - - - -
Key
T: primary operand typeU: alternate operand type
TemplateComponent Operator Templates
operators<T>
operators<T, U>
- operators2<T, U>
- -

Arithmetic Operators Demonstration and Test Program

- -

The operators_test.cpp -program demonstrates the use of the arithmetic operator templates, and -can also be used to verify correct operation. Check the compiler status report for the test results -with selected platforms.

- -

Dereference Operators and Iterator Helpers

- -

The iterator helper templates ease the task -of creating a custom iterator. Similar to arithmetic types, a complete -iterator has many operators that are "redundant" and can be -implemented in terms of the core set of operators.

- -

The dereference operators were motivated -by the iterator helpers, but are often useful in -non-iterator contexts as well. Many of the redundant iterator operators -are also arithmetic operators, so the iterator helper classes borrow -many of the operators defined above. In fact, only two new operators -need to be defined (the pointer-to-member operator-> and -the subscript operator[])!

- -

The requirements for the types used to instantiate the dereference -operators are specified in terms of expressions which must be valid and -their return type. The composite operator templates list their component -templates, which the instantiating type must support, and possibly other -requirements.

- -

Dereference Operators

- -

All the dereference operator templates in this table accept an -optional template parameter (not shown) to be used for base class chaining.

- - - - - - - - - - - - - - - - - - - - - -
Dereference Operator Template Classes
- - - - - - - - - - - - - -
Key
T: operand typeP: pointer type
D: difference_typeR: reference type
i: object of type T (an iterator)n: object of type D (an index)
TemplateSupplied OperationsRequirements
dereferenceable<T, P>P operator->() const(&*i). Return convertible to P.
indexable<T, D, R>R operator[](D n) const*(i + n). Return of type R.
- -

Grouped Iterator Operators

- -

There are five iterator operator class templates, each for a different -category of iterator. The following table shows the operator groups -for any category that a custom iterator could define. These class -templates have an additional optional template parameter B, -which is not shown, to support base class chaining.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Iterator Operator Class Templates
- - - - - - - - - - - - - -
Key
T: operand typeP: pointer type
D: difference_typeR: reference type
V: value_type
TemplateComponent Operator Templates
input_iteratable<T, P>
output_iteratable<T>
forward_iteratable<T, P>
bidirectional_iteratable<T, P>
random_access_iteratable<T, P, D, R>
- -

Iterator Helpers

- -

There are also five iterator helper class templates, each corresponding -to a different iterator category. These classes cannot be used for base class chaining. The following summaries -show that these class templates supply both the iterator operators from -the iterator operator class templates and -the iterator typedef's required by the C++ standard (iterator_category, -value_type, etc.).

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Iterator Helper Class Templates
- - - - - - - - - - - - - -
Key
T: operand typeP: pointer type
D: difference_typeR: reference type
V: value_typex1, x2: objects of type T
TemplateOperations & Requirements
input_iterator_helper<T, V, D, P, R>Supports the operations and has the requirements of -
output_iterator_helper<T>Supports the operations and has the requirements of - - See also [1], [2]. -
forward_iterator_helper<T, V, D, P, R>Supports the operations and has the requirements of -
bidirectional_iterator_helper<T, V, D, P, R>Supports the operations and has the requirements of -
random_access_iterator_helper<T, V, D, P, R>Supports the operations and has the requirements of - - To satisfy RandomAccessIterator, - x1 - x2 with return convertible to D - is also required.
- -

Iterator Helper Notes

- -

[1] Unlike other iterator helpers templates, -output_iterator_helper takes only one template parameter - the type of -its target class. Although to some it might seem like an unnecessary -restriction, the standard requires difference_type and -value_type of any output iterator to be -void (24.3.1 [lib.iterator.traits]), and -output_iterator_helper template respects this -requirement. Also, output iterators in the standard have void pointer and -reference types, so the output_iterator_helper does the -same. - -

[2] As self-proxying is the easiest and most common way to -implement output iterators (see, for example, insert [24.4.2] and stream -iterators [24.5] in the standard library), output_iterator_helper -supports the idiom by defining operator* -and operator++ member functions which just return a -non-const reference to the iterator itself. Support for -self-proxying allows us, in many cases, to reduce the task of writing an output -iterator to writing just two member functions - an appropriate -constructor and a copy-assignment operator. For example, here is a possible -implementation of boost::function_output_iterator -adaptor:

- -
-template<class UnaryFunction>
-struct function_output_iterator
-    : boost::output_iterator_helper< function_output_iterator<UnaryFunction> >
-{
-    explicit function_output_iterator(UnaryFunction const& f = UnaryFunction())
-        : func(f) {}
-
-    template<typename T>
-    function_output_iterator& operator=(T const& value)
-    {
-        this->func(value); 
-        return *this; 
-    }
-
- private:
-    UnaryFunction func;
-};
-
- -

Note that support for self-proxying does not prevent you from using output_iterator_helper to ease any other, different kind of output iterator's implementation. If output_iterator_helper's target type provides its own definition of operator* or/and operator++, then these operators will get used and the ones supplied by output_iterator_helper will never be instantiated.

- -

Iterator Demonstration and Test Program

- -

The iterators_test.cpp -program demonstrates the use of the iterator templates, and can also be -used to verify correct operation. The following is the custom iterator -defined in the test program. It demonstrates a correct (though trivial) -implementation of the core operations that must be defined in order for -the iterator helpers to "fill in" the rest of the iterator -operations.

- -
-
template <class T, class R, class P>
-struct test_iter
-  : public boost::random_access_iterator_helper<
-     test_iter<T,R,P>, T, std::ptrdiff_t, P, R>
-{
-  typedef test_iter self;
-  typedef R Reference;
-  typedef std::ptrdiff_t Distance;
-
-public:
-  explicit test_iter(T* i =0);
-  test_iter(const self& x);
-  self& operator=(const self& x);
-  Reference operator*() const;
-  self& operator++();
-  self& operator--();
-  self& operator+=(Distance n);
-  self& operator-=(Distance n);
-  bool operator==(const self& x) const;
-  bool operator<(const self& x) const;
-  friend Distance operator-(const self& x, const self& y);
-};
-
- -

Check the compiler status report for -the test results with selected platforms.

- -
- -

Contributors

- -
-
Dave Abrahams -
Started the library and contributed the arithmetic operators in - boost/operators.hpp. - -
Jeremy Siek -
Contributed the dereference operators and - iterator helpers in boost/operators.hpp. - Also contributed iterators_test.cpp. - -
Aleksey Gurtovoy -
Contributed the code to support base class - chaining while remaining backward-compatible with old - versions of the library. - -
Beman Dawes -
Contributed operators_test.cpp. - -
Daryle Walker -
Contributed classes for the shift operators, equivalence, - partial ordering, and arithmetic conversions. Added the - grouped operator classes. Added helper classes for - input and output iterators. - -
Helmut Zeisel -
Contributed the 'left' operators and added some - grouped operator classes. -
- -

Note for Users of Older Versions

- -

The changes in the library interface and -recommended usage were motivated by some practical issues described -below. The new version of the library is still backward-compatible with -the former one (so you're not forced change any existing code), -but the old usage is deprecated. Though it was arguably simpler and -more intuitive than using base class chaining, -it has been discovered that the old practice of deriving from multiple -operator templates can cause the resulting classes to be much larger -than they should be. Most modern C++ compilers significantly bloat the -size of classes derived from multiple empty base classes, even though -the base classes themselves have no state. For instance, the size of -point<int> from the example -above was 12-24 bytes on various compilers for the Win32 platform, -instead of the expected 8 bytes.

- -

Strictly speaking, it was not the library's fault--the language -rules allow the compiler to apply the empty base class optimization in -that situation. In principle an arbitrary number of empty base classes -can be allocated at the same offset, provided that none of them have a -common ancestor (see section 10.5 [class.derived] paragraph 5 of the -standard). But the language definition also doesn't require -implementations to do the optimization, and few if any of today's -compilers implement it when multiple inheritance is involved. What's -worse, it is very unlikely that implementors will adopt it as a future -enhancement to existing compilers, because it would break binary -compatibility between code generated by two different versions of the -same compiler. As Matt Austern said, "One of the few times when you -have the freedom to do this sort of thing is when you're targeting a new -architecture...". On the other hand, many common compilers will use -the empty base optimization for single inheritance hierarchies.

- -

Given the importance of the issue for the users of the library (which -aims to be useful for writing light-weight classes like -MyInt or point<>), and the forces -described above, we decided to change the library interface so that the -object size bloat could be eliminated even on compilers that support -only the simplest form of the empty base class optimization. The -current library interface is the result of those changes. Though the -new usage is a bit more complicated than the old one, we think it's -worth it to make the library more useful in real world. Alexy Gurtovoy -contributed the code which supports the new usage idiom while allowing -the library remain backward-compatible.

- -
- -

Revised: 30 Oct 2001

- -

Copyright © David Abrahams and Beman Dawes 1999-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.

- - - diff --git a/operators_test.cpp b/operators_test.cpp deleted file mode 100644 index f2893e0..0000000 --- a/operators_test.cpp +++ /dev/null @@ -1,890 +0,0 @@ -// Demonstrate and test boost/operators.hpp -------------------------------// - -// (C) Copyright Beman Dawes 1999. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 01 Oct 01 Added tests for "left" operators -// and new grouped operators. (Helmut Zeisel) -// 20 May 01 Output progress messages. Added tests for new operator -// templates. Updated random number generator. Changed tests to -// use Boost Test Tools library. (Daryle Walker) -// 04 Jun 00 Added regression test for a bug I found (David Abrahams) -// 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy) -// ?? ??? 00 Major update to randomly test all one- and two- argument forms by -// wrapping integral types and comparing the results of operations -// to the results for the raw types (David Abrahams) -// 12 Dec 99 Minor update, output confirmation message. -// 15 Nov 99 Initial version - -#define BOOST_INCLUDE_MAIN - -#include // for BOOST_MSVC -#include // for boost::exit_success -#include // for the tested items -#include // for boost::minstd_rand -#include // for main - -#include // for std::cout (std::endl indirectly) - - -namespace -{ - // avoiding a template version of true_value so as to not confuse VC++ - int true_value(int x) { return x; } - long true_value(long x) { return x; } - signed char true_value(signed char x) { return x; } - short true_value(short x) { return x; } - unsigned int true_value(unsigned int x) { return x; } - unsigned long true_value(unsigned long x) { return x; } - unsigned char true_value(unsigned char x) { return x; } - unsigned short true_value(unsigned short x) { return x; } - - // The use of operators<> here tended to obscure - // interactions with certain compiler bugs - template - class Wrapped1 - : boost::operators > - , boost::shiftable > - { - public: - explicit Wrapped1( T v = T() ) : _value(v) {} - T value() const { return _value; } - - bool operator<(const Wrapped1& x) const { return _value < x._value; } - bool operator==(const Wrapped1& x) const { return _value == x._value; } - - Wrapped1& operator+=(const Wrapped1& x) - { _value += x._value; return *this; } - Wrapped1& operator-=(const Wrapped1& x) - { _value -= x._value; return *this; } - Wrapped1& operator*=(const Wrapped1& x) - { _value *= x._value; return *this; } - Wrapped1& operator/=(const Wrapped1& x) - { _value /= x._value; return *this; } - Wrapped1& operator%=(const Wrapped1& x) - { _value %= x._value; return *this; } - Wrapped1& operator|=(const Wrapped1& x) - { _value |= x._value; return *this; } - Wrapped1& operator&=(const Wrapped1& x) - { _value &= x._value; return *this; } - Wrapped1& operator^=(const Wrapped1& x) - { _value ^= x._value; return *this; } - Wrapped1& operator<<=(const Wrapped1& x) - { _value <<= x._value; return *this; } - Wrapped1& operator>>=(const Wrapped1& x) - { _value >>= x._value; return *this; } - Wrapped1& operator++() { ++_value; return *this; } - Wrapped1& operator--() { --_value; return *this; } - - private: - T _value; - }; - template - T true_value(Wrapped1 x) { return x.value(); } - - template - class Wrapped2 - : boost::operators > - , boost::operators2, U> - , boost::shiftable1 - , boost::shiftable2, U > > - { - public: - explicit Wrapped2( T v = T() ) : _value(v) {} - T value() const { return _value; } - - bool operator<(const Wrapped2& x) const { return _value < x._value; } - bool operator==(const Wrapped2& x) const { return _value == x._value; } - - Wrapped2& operator+=(const Wrapped2& x) - { _value += x._value; return *this; } - Wrapped2& operator-=(const Wrapped2& x) - { _value -= x._value; return *this; } - Wrapped2& operator*=(const Wrapped2& x) - { _value *= x._value; return *this; } - Wrapped2& operator/=(const Wrapped2& x) - { _value /= x._value; return *this; } - Wrapped2& operator%=(const Wrapped2& x) - { _value %= x._value; return *this; } - Wrapped2& operator|=(const Wrapped2& x) - { _value |= x._value; return *this; } - Wrapped2& operator&=(const Wrapped2& x) - { _value &= x._value; return *this; } - Wrapped2& operator^=(const Wrapped2& x) - { _value ^= x._value; return *this; } - Wrapped2& operator<<=(const Wrapped2& x) - { _value <<= x._value; return *this; } - Wrapped2& operator>>=(const Wrapped2& x) - { _value >>= x._value; return *this; } - Wrapped2& operator++() { ++_value; return *this; } - Wrapped2& operator--() { --_value; return *this; } - - bool operator<(U u) const { return _value < u; } - bool operator>(U u) const { return _value > u; } - bool operator==(U u) const { return _value == u; } - Wrapped2& operator+=(U u) { _value += u; return *this; } - Wrapped2& operator-=(U u) { _value -= u; return *this; } - Wrapped2& operator*=(U u) { _value *= u; return *this; } - Wrapped2& operator/=(U u) { _value /= u; return *this; } - Wrapped2& operator%=(U u) { _value %= u; return *this; } - Wrapped2& operator|=(U u) { _value |= u; return *this; } - Wrapped2& operator&=(U u) { _value &= u; return *this; } - Wrapped2& operator^=(U u) { _value ^= u; return *this; } - Wrapped2& operator<<=(U u) { _value <<= u; return *this; } - Wrapped2& operator>>=(U u) { _value >>= u; return *this; } - - private: - T _value; - }; - template - T true_value(Wrapped2 x) { return x.value(); } - - template - class Wrapped3 - : boost::equivalent > - , boost::partially_ordered > - , boost::equality_comparable > - { - 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 - T true_value(Wrapped3 x) { return x.value(); } - - template - class Wrapped4 - : boost::equality_comparable1 - , boost::equivalent1 - , boost::partially_ordered1 > > > - , boost::partially_ordered2, U - , boost::equivalent2, U - , boost::equality_comparable2, 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 - T true_value(Wrapped4 x) { return x.value(); } - - // U must be convertible to T - template - class Wrapped5 - : boost::ordered_field_operators2, U> - , boost::ordered_field_operators1 > - { - public: - explicit Wrapped5( T v = T() ) : _value(v) {} - - // Conversion from U to Wrapped5 - 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 - T true_value(Wrapped5 x) { return x.value(); } - - // U must be convertible to T - template - class Wrapped6 - : boost::ordered_euclidian_ring_operators2, U> - , boost::ordered_euclidian_ring_operators1 > - { - public: - explicit Wrapped6( T v = T() ) : _value(v) {} - - // Conversion from U to Wrapped6 - 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 - T true_value(Wrapped6 x) { return x.value(); } - - // MyInt uses only the single template-argument form of all_operators<> - typedef Wrapped1 MyInt; - - typedef Wrapped2 MyLong; - - typedef Wrapped3 MyChar; - - typedef Wrapped4 MyShort; - - typedef Wrapped5 MyDoubleInt; - - typedef Wrapped6 MyLongInt; - - template - void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - BOOST_TEST( true_value(y1) == true_value(y2) ); - BOOST_TEST( true_value(x1) == true_value(x2) ); - } - - template - void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - BOOST_TEST( (x1 < y1) == (x2 < y2) ); - BOOST_TEST( (x1 <= y1) == (x2 <= y2) ); - BOOST_TEST( (x1 >= y1) == (x2 >= y2) ); - BOOST_TEST( (x1 > y1) == (x2 > y2) ); - } - - template - void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - test_less_than_comparable_aux( x1, y1, x2, y2 ); - test_less_than_comparable_aux( y1, x1, y2, x2 ); - } - - template - void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - BOOST_TEST( (x1 == y1) == (x2 == y2) ); - BOOST_TEST( (x1 != y1) == (x2 != y2) ); - } - - template - void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - test_equality_comparable_aux( x1, y1, x2, y2 ); - test_equality_comparable_aux( y1, x1, y2, x2 ); - } - - template - void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - BOOST_TEST( (x1 * y1).value() == (x2 * y2) ); - } - - template - void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - test_multipliable_aux( x1, y1, x2, y2 ); - test_multipliable_aux( y1, x1, y2, x2 ); - } - - template - void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - BOOST_TEST( (x1 + y1).value() == (x2 + y2) ); - } - - template - void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - test_addable_aux( x1, y1, x2, y2 ); - test_addable_aux( y1, x1, y2, x2 ); - } - - template - 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 - 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) ); - } - - template - 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) ); - } - - template - 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 - 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) ); - } - - template - 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 - void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - BOOST_TEST( (x1 ^ y1).value() == (x2 ^ y2) ); - } - - template - void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - test_xorable_aux( x1, y1, x2, y2 ); - test_xorable_aux( y1, x1, y2, x2 ); - } - - template - void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - BOOST_TEST( (x1 & y1).value() == (x2 & y2) ); - } - - template - void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - test_andable_aux( x1, y1, x2, y2 ); - test_andable_aux( y1, x1, y2, x2 ); - } - - template - void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - BOOST_TEST( (x1 | y1).value() == (x2 | y2) ); - } - - template - 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 - 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 - 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) ); - } - - template - void test_incrementable(X1 x1, X2 x2) - { - sanity_check( x1, x1, x2, x2 ); - BOOST_TEST( (x1++).value() == x2++ ); - BOOST_TEST( x1.value() == x2 ); - } - - template - void test_decrementable(X1 x1, X2 x2) - { - sanity_check( x1, x1, x2, x2 ); - BOOST_TEST( (x1--).value() == x2-- ); - BOOST_TEST( x1.value() == x2 ); - } - - template - void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - test_less_than_comparable( x1, y1, x2, y2 ); - test_equality_comparable( x1, y1, x2, y2 ); - test_multipliable( x1, y1, x2, y2 ); - test_addable( x1, y1, x2, y2 ); - test_subtractable( x1, y1, x2, y2 ); - test_dividable( x1, y1, x2, y2 ); - test_modable( x1, y1, x2, y2 ); - test_xorable( x1, y1, x2, y2 ); - test_andable( x1, y1, x2, y2 ); - test_orable( x1, y1, x2, y2 ); - test_left_shiftable( x1, y1, x2, y2 ); - test_right_shiftable( x1, y1, x2, y2 ); - test_incrementable( x1, x2 ); - test_decrementable( x1, x2 ); - } - - template - 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 - struct tester - { - void operator()(boost::minstd_rand& randomizer) const - { - Big b1 = Big( randomizer() ); - Big b2 = Big( randomizer() ); - Small s = Small( randomizer() ); - - test_all( Wrapped1(b1), Wrapped1(b2), b1, b2 ); - test_all( Wrapped2(b1), s, b1, s ); - } - }; - - template - struct tester_left - { - void operator()(boost::minstd_rand& randomizer) const - { - Big b1 = Big( randomizer() ); - Small s = Small( randomizer() ); - - test_left( Wrapped6(b1), s, b1, s ); - } - }; - - // added as a regression test. We had a bug which this uncovered. - struct Point - : boost::addable > - { - Point( int h, int v ) : h(h), v(v) {} - Point() :h(0), v(0) {} - const Point& operator+=( const Point& rhs ) - { h += rhs.h; v += rhs.v; return *this; } - const Point& operator-=( const Point& rhs ) - { h -= rhs.h; v -= rhs.v; return *this; } - - int h; - int v; - }; - -} // unnamed namespace - - -// workaround for MSVC bug; for some reasons the compiler doesn't instantiate -// inherited operator templates at the moment it must, so the following -// explicit instantiations force it to do that. - -#if defined(BOOST_MSVC) && (_MSC_VER <= 1200) -template Wrapped1; -template Wrapped1; -template Wrapped1; -template Wrapped1; - -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; - -template Wrapped6; -template Wrapped6; -template Wrapped6; -template Wrapped6; -template Wrapped6; -template Wrapped6; -#endif - -#define PRIVATE_EXPR_TEST(e, t) BOOST_TEST( ((e), (t)) ) - - -int -test_main( int , char * [] ) -{ - using std::cout; - using std::endl; - - // Regression test. - Point x; - x = x + Point(3, 4); - x = x - Point(3, 4); - - cout << "Created point, and operated on it." << endl; - - for (int n = 0; n < 10000; ++n) - { - boost::minstd_rand r; - tester()(r); - tester()(r); - tester()(r); - tester()(r); - tester()(r); - - tester()(r); - tester()(r); - tester()(r); - tester()(r); - tester()(r); - - tester_left()(r); - tester_left()(r); - tester_left()(r); - - tester_left()(r); - tester_left()(r); - tester_left()(r); - } - - cout << "Did random tester loop." << endl; - - MyInt i1(1); - MyInt i2(2); - MyInt i; - - BOOST_TEST( i1.value() == 1 ); - BOOST_TEST( i2.value() == 2 ); - BOOST_TEST( i.value() == 0 ); - - cout << "Created MyInt objects.\n"; - - PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) ); - - BOOST_TEST( i2 == i ); - BOOST_TEST( i1 != i2 ); - BOOST_TEST( i1 < i2 ); - BOOST_TEST( i1 <= i2 ); - BOOST_TEST( i <= i2 ); - BOOST_TEST( i2 > i1 ); - BOOST_TEST( i2 >= i1 ); - BOOST_TEST( i2 >= i ); - - PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) ); - PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) ); - PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) ); - PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) ); - PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) ); - PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) ); - PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) ); - PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) ); - PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) ); - PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) ); - PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) ); - PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) ); - - PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) ); - PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) ); - - cout << "Performed tests on MyInt objects.\n"; - - MyLong j1(1); - MyLong j2(2); - MyLong j; - - BOOST_TEST( j1.value() == 1 ); - BOOST_TEST( j2.value() == 2 ); - BOOST_TEST( j.value() == 0 ); - - cout << "Created MyLong objects.\n"; - - PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) ); - - BOOST_TEST( j2 == j ); - BOOST_TEST( 2 == j ); - BOOST_TEST( j2 == 2 ); - BOOST_TEST( j == j2 ); - BOOST_TEST( j1 != j2 ); - BOOST_TEST( j1 != 2 ); - BOOST_TEST( 1 != j2 ); - BOOST_TEST( j1 < j2 ); - BOOST_TEST( 1 < j2 ); - BOOST_TEST( j1 < 2 ); - BOOST_TEST( j1 <= j2 ); - BOOST_TEST( 1 <= j2 ); - BOOST_TEST( j1 <= j ); - BOOST_TEST( j <= j2 ); - BOOST_TEST( 2 <= j2 ); - BOOST_TEST( j <= 2 ); - BOOST_TEST( j2 > j1 ); - BOOST_TEST( 2 > j1 ); - BOOST_TEST( j2 > 1 ); - BOOST_TEST( j2 >= j1 ); - BOOST_TEST( 2 >= j1 ); - BOOST_TEST( j2 >= 1 ); - BOOST_TEST( j2 >= j ); - BOOST_TEST( 2 >= j ); - BOOST_TEST( j2 >= 2 ); - - BOOST_TEST( (j1 + 2) == 3 ); - BOOST_TEST( (1 + j2) == 3 ); - PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) ); - - BOOST_TEST( (j + 2) == 5 ); - BOOST_TEST( (3 + j2) == 5 ); - PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) ); - - BOOST_TEST( (j - 1) == 4 ); - PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) ); - - BOOST_TEST( (j * 2) == 8 ); - BOOST_TEST( (4 * j2) == 8 ); - PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) ); - - BOOST_TEST( (j / 2) == 4 ); - PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) ); - - BOOST_TEST( (j % 3) == 1 ); - PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) ); - - PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) ); - - BOOST_TEST( (1 | j2 | j) == 7 ); - BOOST_TEST( (j1 | 2 | j) == 7 ); - BOOST_TEST( (j1 | j2 | 4) == 7 ); - PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) ); - - BOOST_TEST( (7 & j2) == 2 ); - BOOST_TEST( (j & 2) == 2 ); - PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) ); - - PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) ); - - BOOST_TEST( (3 ^ j1) == 2 ); - BOOST_TEST( (j ^ 1) == 2 ); - PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) ); - - PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) ); - - BOOST_TEST( (j1 << 2) == 4 ); - BOOST_TEST( (j2 << 1) == 4 ); - PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) ); - - BOOST_TEST( (j >> 2) == 1 ); - BOOST_TEST( (j2 >> 1) == 1 ); - PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) ); - - cout << "Performed tests on MyLong objects.\n"; - - MyChar k1(1); - MyChar k2(2); - MyChar k; - - BOOST_TEST( k1.value() == 1 ); - BOOST_TEST( k2.value() == 2 ); - BOOST_TEST( k.value() == 0 ); - - cout << "Created MyChar objects.\n"; - - PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) ); - - BOOST_TEST( k2 == k ); - BOOST_TEST( k1 != k2 ); - BOOST_TEST( k1 < k2 ); - BOOST_TEST( k1 <= k2 ); - BOOST_TEST( k <= k2 ); - BOOST_TEST( k2 > k1 ); - BOOST_TEST( k2 >= k1 ); - BOOST_TEST( k2 >= k ); - - cout << "Performed tests on MyChar objects.\n"; - - MyShort l1(1); - MyShort l2(2); - MyShort l; - - BOOST_TEST( l1.value() == 1 ); - BOOST_TEST( l2.value() == 2 ); - BOOST_TEST( l.value() == 0 ); - - cout << "Created MyShort objects.\n"; - - PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) ); - - BOOST_TEST( l2 == l ); - BOOST_TEST( 2 == l ); - BOOST_TEST( l2 == 2 ); - BOOST_TEST( l == l2 ); - BOOST_TEST( l1 != l2 ); - BOOST_TEST( l1 != 2 ); - BOOST_TEST( 1 != l2 ); - BOOST_TEST( l1 < l2 ); - BOOST_TEST( 1 < l2 ); - BOOST_TEST( l1 < 2 ); - BOOST_TEST( l1 <= l2 ); - BOOST_TEST( 1 <= l2 ); - BOOST_TEST( l1 <= l ); - BOOST_TEST( l <= l2 ); - BOOST_TEST( 2 <= l2 ); - BOOST_TEST( l <= 2 ); - BOOST_TEST( l2 > l1 ); - BOOST_TEST( 2 > l1 ); - BOOST_TEST( l2 > 1 ); - BOOST_TEST( l2 >= l1 ); - BOOST_TEST( 2 >= l1 ); - BOOST_TEST( l2 >= 1 ); - BOOST_TEST( l2 >= l ); - BOOST_TEST( 2 >= l ); - BOOST_TEST( l2 >= 2 ); - - cout << "Performed tests on MyShort objects.\n"; - - MyDoubleInt di1(1); - MyDoubleInt di2(2.); - MyDoubleInt half(0.5); - MyDoubleInt di; - MyDoubleInt tmp; - - BOOST_TEST( di1.value() == 1 ); - BOOST_TEST( di2.value() == 2 ); - BOOST_TEST( di2.value() == 2 ); - BOOST_TEST( di.value() == 0 ); - - cout << "Created MyDoubleInt objects.\n"; - - PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) ); - - BOOST_TEST( di2 == di ); - BOOST_TEST( 2 == di ); - BOOST_TEST( di == 2 ); - BOOST_TEST( di1 < di2 ); - BOOST_TEST( 1 < di2 ); - BOOST_TEST( di1 <= di2 ); - BOOST_TEST( 1 <= di2 ); - BOOST_TEST( di2 > di1 ); - BOOST_TEST( di2 > 1 ); - BOOST_TEST( di2 >= di1 ); - BOOST_TEST( di2 >= 1 ); - BOOST_TEST( di1 / di2 == half ); - BOOST_TEST( di1 / 2 == half ); - BOOST_TEST( 1 / di2 == half ); - PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=2) == half) ); - PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=di2) == half) ); - BOOST_TEST( di1 * di2 == di2 ); - BOOST_TEST( di1 * 2 == di2 ); - BOOST_TEST( 1 * di2 == di2 ); - PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=2) == di2) ); - PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=di2) == di2) ); - BOOST_TEST( di2 - di1 == di1 ); - BOOST_TEST( di2 - 1 == di1 ); - BOOST_TEST( 2 - di1 == di1 ); - PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=1) == di1) ); - PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=di1) == di1) ); - BOOST_TEST( di1 + di1 == di2 ); - BOOST_TEST( di1 + 1 == di2 ); - BOOST_TEST( 1 + di1 == di2 ); - PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=1) == di2) ); - PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=di1) == di2) ); - - cout << "Performed tests on MyDoubleInt objects.\n"; - - MyLongInt li1(1); - MyLongInt li2(2); - MyLongInt li; - MyLongInt tmp2; - - BOOST_TEST( li1.value() == 1 ); - BOOST_TEST( li2.value() == 2 ); - BOOST_TEST( li.value() == 0 ); - - cout << "Created MyLongInt objects.\n"; - - PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) ); - - BOOST_TEST( li2 == li ); - BOOST_TEST( 2 == li ); - BOOST_TEST( li == 2 ); - BOOST_TEST( li1 < li2 ); - BOOST_TEST( 1 < li2 ); - BOOST_TEST( li1 <= li2 ); - BOOST_TEST( 1 <= li2 ); - BOOST_TEST( li2 > li1 ); - BOOST_TEST( li2 > 1 ); - BOOST_TEST( li2 >= li1 ); - BOOST_TEST( li2 >= 1 ); - BOOST_TEST( li1 % li2 == li1 ); - BOOST_TEST( li1 % 2 == li1 ); - BOOST_TEST( 1 % li2 == li1 ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=2) == li1) ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=li2) == li1) ); - BOOST_TEST( li1 / li2 == 0 ); - BOOST_TEST( li1 / 2 == 0 ); - BOOST_TEST( 1 / li2 == 0 ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=2) == 0) ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=li2) == 0) ); - BOOST_TEST( li1 * li2 == li2 ); - BOOST_TEST( li1 * 2 == li2 ); - BOOST_TEST( 1 * li2 == li2 ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=2) == li2) ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=li2) == li2) ); - BOOST_TEST( li2 - li1 == li1 ); - BOOST_TEST( li2 - 1 == li1 ); - BOOST_TEST( 2 - li1 == li1 ); - PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=1) == li1) ); - PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=li1) == li1) ); - BOOST_TEST( li1 + li1 == li2 ); - BOOST_TEST( li1 + 1 == li2 ); - BOOST_TEST( 1 + li1 == li2 ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=1) == li2) ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=li1) == li2) ); - - cout << "Performed tests on MyLongInt objects.\n"; - - return boost::exit_success; -} diff --git a/permutation_iterator.htm b/permutation_iterator.htm deleted file mode 100644 index ea68387..0000000 --- a/permutation_iterator.htm +++ /dev/null @@ -1,177 +0,0 @@ - - - - -Permutation Iterator Adaptor Documentation - - - - -

Permutation Iterator Adaptor

-

Defined in header boost/permutation_iterator.hpp

-

The permutation iterator adaptor provides an iterator to a permutation of a given range. -(see definition of permutation). -The adaptor takes two arguments -

    -
  • an iterator to the range V on which the permutation will be applied
  • -
  • the reindexing scheme that defines how the elements of V will be permuted.
  • -
- -

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

- -

Synopsis

- -
-
-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);
-}
-
-
- - -

The Permutation Iterator Generator Class Template

- -

The permutation_iterator_generator is a helper class whose purpose -is to construct a permutation iterator type. 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. - -

-
-template <class ElementIterator, class IndexIterator>
-class permutation_iterator_generator
-{
-public:
-  typedef iterator_adaptor<...> type; // the resulting permutation iterator type 
-}
-
-
- - -

Template Parameters

- - - - - - - - - - - - - - - -
ParameterDescription
ElementIteratorThe iterator over the elements to be permuted. This type must be a model -of RandomAccessIterator
IndexIteratorThe iterator over the new indexing scheme. This type must at least be a model -of ForwardIterator. -The IndexIterator::value_type must be convertible to the -ElementIterator::difference_type.
- -

Concept Model

-The permutation iterator is always a model of the same concept as the IndexIterator. - -

Members

-The permutation iterator implements the member functions -and operators required for the -Random Access Iterator -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 operator+=(distance), this operation will take linear time -in case the IndexIterator is a model of ForwardIterator instead of amortized constant time. - -
- -

The Permutation Iterator Object Generator

- -The make_permutation_iterator() function provides a -convenient way to create permutation iterator objects. The function -saves the user the trouble of explicitly writing out the iterator -types. - -
-
-template <class ElementIterator, class IndexIterator >
-typename permutation_iterator_generator<ElementIterator, IndexIterator>::type
-make_permutation_iterator(ElementIterator& base, IndexIterator& indices);
-
-
- -

Example

-
-
-  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";
-
-
- -



-Thanks: The permutation iterator is only a small addition to the superb iterator adaptors -library of David Abrahams and Jeremy Siek. -

- -Copyright 2001 Toon Knapen. - - - diff --git a/projection_iterator.htm b/projection_iterator.htm deleted file mode 100644 index e6b0df3..0000000 --- a/projection_iterator.htm +++ /dev/null @@ -1,391 +0,0 @@ - - - - - - -Projection Iterator Adaptor Documentation - - - - -c++boost.gif (8819 bytes) - -

Projection Iterator Adaptor

- -Defined in header -boost/iterator_adaptors.hpp - -

-The projection iterator adaptor is similar to the transform iterator adaptor in that -its operator*() applies some function to the result of -dereferencing the base iterator and then returns the result. The -difference is that the function must return a reference to some -existing object (for example, a data member within the -value_type of the base iterator). The following -pseudo-code gives the basic idea. The data member p is -the function object. - -

-  reference projection_iterator::operator*() const {
-    return this->p(*this->base_iterator);
-  }
-
- -

Synopsis

- -
-namespace boost {
-  template <class AdaptableUnaryFunction, class BaseIterator>
-  struct projection_iterator_generator;
-  
-  template <class AdaptableUnaryFunction, 
-            class BaseIterator, class ConstBaseIterator>
-  struct projection_iterator_pair_generator;
-
-  template <class AdaptableUnaryFunction, class BaseIterator>
-  typename projection_iterator_generator<AdaptableUnaryFunction, BaseIterator>::type
-  make_projection_iterator(BaseIterator base,
-			   const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
-
-  template <class AdaptableUnaryFunction, class ConstBaseIterator>
-  typename projection_iterator_generator<AdaptableUnaryFunction, ConstBaseIterator>::type
-  make_const_projection_iterator(ConstBaseIterator base,
-                                 const AdaptableUnaryFunction& p = AdaptableUnaryFunction())  
-}
-
- -
- -

The Projection Iterator Type -Generator

- -The class projection_iterator_generator is a helper class -whose purpose is to construct an projection iterator type. The main -template parameter for this class is the AdaptableUnaryFunction -function object type and the BaseIterator type that is being -wrapped. - -
-template <class AdaptableUnaryFunction, class BaseIterator>
-class projection_iterator_generator
-{
-public:
-  typedef iterator_adaptor<...> type; // the resulting projection iterator type 
-};
-
- -

Example

- -In the following example we have a list of personnel records. Each -record has an employee's name and ID number. We want to be able to -traverse through the list accessing either the name or the ID numbers -of the employees using the projection iterator so we create the -function object classes select_name and -select_ID. We then use the -projection_iterator_generator class to create a projection -iterator and use it to print out the names of the employees. - -
-#include <boost/config.hpp>
-#include <list>
-#include <iostream>
-#include <iterator>
-#include <algorithm>
-#include <string>
-#include <boost/iterator_adaptors.hpp>
-
-struct personnel_record {
-  personnel_record(std::string n, int id) : m_name(n), m_ID(id) { }
-  std::string m_name;
-  int m_ID;
-};
-
-struct select_name {
-  typedef personnel_record argument_type;
-  typedef std::string result_type;
-  const std::string& operator()(const personnel_record& r) const {
-    return r.m_name;
-  }
-  std::string& operator()(personnel_record& r) const {
-    return r.m_name;
-  }
-};
-
-struct select_ID {
-  typedef personnel_record argument_type;
-  typedef int result_type;
-  const int& operator()(const personnel_record& r) const {
-    return r.m_ID;
-  }
-  int& operator()(personnel_record& r) const {
-    return r.m_ID;
-  }
-};
-
-int main(int, char*[])
-{
-  std::list<personnel_record> personnel_list;
-
-  personnel_list.push_back(personnel_record("Barney", 13423));
-  personnel_list.push_back(personnel_record("Fred", 12343));
-  personnel_list.push_back(personnel_record("Wilma", 62454));
-  personnel_list.push_back(personnel_record("Betty", 20490));
-
-  // Example of using projection_iterator_generator
-  // to print out the names in the personnel list.
-
-  boost::projection_iterator_generator<select_name,
-    std::list<personnel_record>::iterator>::type
-    personnel_first(personnel_list.begin()),
-    personnel_last(personnel_list.end());
-
-  std::copy(personnel_first, personnel_last,
-            std::ostream_iterator<std::string>(std::cout, "\n"));
-  std::cout << std::endl;
-
-  // to be continued...
-
-The output for this part is: -
-Barney
-Fred
-Wilma
-Betty
-
- -

Template Parameters

- - - - - - - - - - - - - - - - - -
ParameterDescription
AdaptableUnaryFunctionThe type of the function object. The argument_type of the -function must match the value type of the base iterator. The function -should return a reference to the function's result_type. -The result_type will be the resulting iterator's value_type. -
BaseIteratorThe iterator type being wrapped.
- -

Model of

- -If the base iterator is a model of Random -Access Iterator then so is the resulting projection iterator. If -the base iterator supports less functionality than this the resulting -projection iterator will also support less functionality. - -

Members

- -The projection iterator type implements the member functions and -operators required of the Random -Access Iterator concept. -In addition it has the following constructor: - -
-projection_iterator_generator::type(const BaseIterator& it,
-                                    const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
-
- -

-


-

- -

The Projection Iterator Pair -Generator

- -Sometimes a mutable/const pair of iterator types is needed, such as -when implementing a container type. The -projection_iterator_pair_generator class makes it more -convenient to create this pair of iterator types. - -
-template <class AdaptableUnaryFunction, class BaseIterator, class ConstBaseIterator>
-class projection_iterator_pair_generator
-{
-public:
-  typedef iterator_adaptor<...> iterator;       // the mutable projection iterator type 
-  typedef iterator_adaptor<...> const_iterator; // the immutable projection iterator type 
-};
-
- -

Example

- -In this part of the example we use the -projection_iterator_pair_generator to create a mutable/const -pair of projection iterators that access the ID numbers of the -personnel. We use the mutable iterator to re-index the ID numbers from -zero. We then use the constant iterator to print the ID numbers out. - -
-  // continuing from the last example...
-
-  typedef boost::projection_iterator_pair_generator<select_ID,
-    std::list<personnel_record>::iterator,
-    std::list<personnel_record>::const_iterator> PairGen;
-
-  PairGen::iterator ID_first(personnel_list.begin()),
-    ID_last(personnel_list.end());
-
-  int new_id = 0;
-  while (ID_first != ID_last) {
-    *ID_first = new_id++;
-    ++ID_first;
-  }
-
-  PairGen::const_iterator const_ID_first(personnel_list.begin()),
-    const_ID_last(personnel_list.end());
-
-  std::copy(const_ID_first, const_ID_last,
-            std::ostream_iterator<int>(std::cout, " "));
-  std::cout << std::endl;
-  std::cout << std::endl;
-  
-  // to be continued...
-
-0 1 2 3 
-
- -

Template Parameters

- - - - - - - - - - - - - - - - - - - - - - - -
ParameterDescription
AdaptableUnaryFunctionThe type of the function object. The argument_type of the -function must match the value type of the base iterator. The function -should return a true reference to the function's result_type. -The result_type will be the resulting iterator's value_type. -
BaseIteratorThe mutable iterator type being wrapped.
ConstBaseIteratorThe constant iterator type being wrapped.
- -

Model of

- -If the base iterator types model the Random -Access Iterator then so do the resulting projection iterator -types. If the base iterators support less functionality the -resulting projection iterator types will also support less -functionality. The resulting iterator type is mutable, and -the resulting const_iterator type is constant. - -

Members

- -The resulting iterator and const_iterator types -implements the member functions and operators required of the Random -Access Iterator concept. In addition they support the following -constructors: - -
-projection_iterator_pair_generator::iterator(const BaseIterator& it,
-                                             const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
- -
-projection_iterator_pair_generator::const_iterator(const BaseIterator& it,
-                                                   const AdaptableUnaryFunction& p = AdaptableUnaryFunction())
-
- -

-


-

- -

The Projection Iterator Object Generators

- -The make_projection_iterator() and -make_const_projection_iterator() functions provide a more -convenient way to create projection iterator objects. The functions -save the user the trouble of explicitly writing out the iterator -types. - -
-template <class AdaptableUnaryFunction, class BaseIterator>
-typename projection_iterator_generator<AdaptableUnaryFunction, BaseIterator>::type
-make_projection_iterator(BaseIterator base,
-			 const AdaptableUnaryFunction& p = AdaptableUnaryFunction())  
-
-template <class AdaptableUnaryFunction, class ConstBaseIterator>
-typename projection_iterator_generator<AdaptableUnaryFunction, ConstBaseIterator>::type
-make_const_projection_iterator(ConstBaseIterator base,
-			       const AdaptableUnaryFunction& p = AdaptableUnaryFunction())  
-
- - -

Example

- -In this part of the example, we again print out the names of the -personnel, but this time we use the -make_const_projection_iterator() function to save some typing. - -
-  // continuing from the last example...
-
-  std::copy
-    (boost::make_const_projection_iterator<select_name>(personnel_list.begin()),
-     boost::make_const_projection_iterator<select_name>(personnel_list.end()),
-     std::ostream_iterator(std::cout, "\n"));
-
-  return 0;
-}
-
-The output is: -
-Barney
-Fred
-Wilma
-Betty
-
- -
-

Revised 19 Aug 2001

-

© Copyright Jeremy Siek 2000. Permission to copy, use, -modify, sell and distribute this document is granted provided this copyright -notice appears in all copies. This document is provided "as is" -without express or implied warranty, and with no claim as to its suitability for -any purpose.

- - - - - - - - diff --git a/projection_iterator_example.cpp b/projection_iterator_example.cpp deleted file mode 100644 index 5405ced..0000000 --- a/projection_iterator_example.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -#include -#include -#include -#include -#include -#include -#include - -struct personnel_record { - personnel_record(std::string n, int id) : m_name(n), m_ID(id) { } - std::string m_name; - int m_ID; -}; - -struct select_name { - typedef personnel_record argument_type; - typedef std::string result_type; - const std::string& operator()(const personnel_record& r) const { - return r.m_name; - } - std::string& operator()(personnel_record& r) const { - return r.m_name; - } -}; - -struct select_ID { - typedef personnel_record argument_type; - typedef int result_type; - const int& operator()(const personnel_record& r) const { - return r.m_ID; - } - int& operator()(personnel_record& r) const { - return r.m_ID; - } -}; - -int main(int, char*[]) -{ - std::list personnel_list; - - personnel_list.push_back(personnel_record("Barney", 13423)); - personnel_list.push_back(personnel_record("Fred", 12343)); - personnel_list.push_back(personnel_record("Wilma", 62454)); - personnel_list.push_back(personnel_record("Betty", 20490)); - - // Example of using projection_iterator_generator - // to print out the names in the personnel list. - - boost::projection_iterator_generator::iterator>::type - personnel_first(personnel_list.begin()), - personnel_last(personnel_list.end()); - - std::copy(personnel_first, personnel_last, - std::ostream_iterator(std::cout, "\n")); - std::cout << std::endl; - - // Example of using projection_iterator_pair_generator - // to assign new ID numbers to the personnel. - - typedef boost::projection_iterator_pair_generator::iterator, - std::list::const_iterator> PairGen; - - PairGen::iterator ID_first(personnel_list.begin()), - ID_last(personnel_list.end()); - - int new_id = 0; - while (ID_first != ID_last) { - *ID_first = new_id++; - ++ID_first; - } - - PairGen::const_iterator const_ID_first(personnel_list.begin()), - const_ID_last(personnel_list.end()); - - std::copy(const_ID_first, const_ID_last, - std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; - std::cout << std::endl; - - // Example of using make_const_projection_iterator() - // to print out the names in the personnel list again. - - std::copy - (boost::make_const_projection_iterator(personnel_list.begin()), - boost::make_const_projection_iterator(personnel_list.end()), - std::ostream_iterator(std::cout, "\n")); - - return 0; -} diff --git a/ref_ct_test.cpp b/ref_ct_test.cpp deleted file mode 100644 index d9af429..0000000 --- a/ref_ct_test.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// compile-time test for "boost/ref.hpp" header content -// see 'ref_test.cpp' for run-time part - -#include -#include -#include - -namespace { - -template< typename T, typename U > -void ref_test(boost::reference_wrapper) -{ - typedef typename boost::reference_wrapper::type type; - BOOST_STATIC_ASSERT((boost::is_same::value)); - BOOST_STATIC_ASSERT((boost::is_same::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::value == R); -} - -template< typename R, typename Ref > -void cxx_reference_test(Ref) -{ - BOOST_STATIC_ASSERT((boost::is_same::value)); -} - -template< typename R, typename Ref > -void unwrap_reference_test(Ref) -{ - typedef typename boost::unwrap_reference::type type; - BOOST_STATIC_ASSERT((boost::is_same::value)); -} - -} // namespace - -int main() -{ - int i = 0; - int& ri = i; - - int const ci = 0; - int const& rci = ci; - - // 'ref/cref' functions test - ref_test(boost::ref(i)); - ref_test(boost::ref(ri)); - ref_test(boost::ref(ci)); - ref_test(boost::ref(rci)); - - ref_test(boost::cref(i)); - ref_test(boost::cref(ri)); - ref_test(boost::cref(ci)); - ref_test(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(boost::ref(i)); - is_reference_wrapper_test(boost::ref(ri)); - is_reference_wrapper_test(boost::cref(i)); - is_reference_wrapper_test(boost::cref(ci)); - is_reference_wrapper_test(boost::cref(rci)); - - is_reference_wrapper_test(i); - is_reference_wrapper_test(ri); - is_reference_wrapper_test(ci); - is_reference_wrapper_test(rci); - - // ordinary references/function template arguments deduction test - cxx_reference_test(i); - cxx_reference_test(ri); - cxx_reference_test(ci); - cxx_reference_test(rci); - - cxx_reference_test(i); - cxx_reference_test(ri); - cxx_reference_test(i); - cxx_reference_test(ri); - cxx_reference_test(ci); - cxx_reference_test(rci); - - // 'unwrap_reference' test - unwrap_reference_test(boost::ref(i)); - unwrap_reference_test(boost::ref(ri)); - unwrap_reference_test(boost::cref(i)); - unwrap_reference_test(boost::cref(ci)); - unwrap_reference_test(boost::cref(rci)); - - unwrap_reference_test(i); - unwrap_reference_test(ri); - unwrap_reference_test(ci); - unwrap_reference_test(rci); - unwrap_reference_test(i); - unwrap_reference_test(ri); - unwrap_reference_test(i); - unwrap_reference_test(ri); - unwrap_reference_test(ci); - unwrap_reference_test(rci); - - return 0; -} diff --git a/ref_test.cpp b/ref_test.cpp deleted file mode 100644 index 1cfb5dd..0000000 --- a/ref_test.cpp +++ /dev/null @@ -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 - -#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) -# pragma warning(push, 3) -#endif - -#include - -#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) -# pragma warning(pop) -#endif - - -#define BOOST_INCLUDE_MAIN -#include - -namespace { -using namespace boost; - -template -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 - static T* passthru(Arg x) - { - return get_pointer(x); - } - - template - 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::test(1); - ref_wrapper::test(1); - return 0; -} diff --git a/reverse_iterator.htm b/reverse_iterator.htm deleted file mode 100644 index d20735f..0000000 --- a/reverse_iterator.htm +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - - - - - Reverse Iterator Adaptor Documentation - - - - c++boost.gif (8819 bytes) - -

Reverse Iterator Adaptor

- Defined in header boost/iterator_adaptors.hpp - -

The reverse iterator adaptor flips the direction of a base iterator's - motion. Invoking operator++() moves the base iterator backward and - invoking operator--() moves the base iterator forward. The Boost - reverse iterator adaptor is better to use than the - std::reverse_iterator class in situations where pairs of - mutable/constant iterators are needed (e.g., in containers) because - comparisons and conversions between the mutable and const versions are - implemented correctly. - -

Synopsis

-
-namespace boost {
-  template <class BidirectionalIterator,
-            class Value, class Reference, class Pointer, class Category, class Distance>
-  struct reverse_iterator_generator;
-  
-  template <class BidirectionalIterator>
-  typename reverse_iterator_generator<BidirectionalIterator>::type
-  make_reverse_iterator(BidirectionalIterator base)  
-}
-
-
- -

The Reverse Iterator Type - Generator

- The reverse_iterator_generator template is a generator of - reverse iterator types. The main template parameter for this class is the - base BidirectionalIterator type that is being adapted. In most - cases the associated types of the base iterator can be deduced using - std::iterator_traits, but in some situations the user may want to - override these types, so there are also template parameters for the base - iterator's associated types. - -
-
-template <class BidirectionalIterator,
-          class Value, class Reference, class Pointer, class Category, class Distance>
-class reverse_iterator_generator
-{
-public:
-  typedef iterator_adaptor<...> type; // the resulting reverse iterator type 
-};
-
-
- -

Example

- In this example we sort a sequence of letters and then output the sequence - in descending order using reverse iterators. - -
-
-#include <boost/config.hpp>
-#include <iostream>
-#include <algorithm>
-#include <boost/iterator_adaptors.hpp>
-
-int main(int, char*[])
-{
-  char letters[] = "hello world!";
-  const int N = sizeof(letters)/sizeof(char) - 1;
-  std::cout << "original sequence of letters:\t"
-      << letters << std::endl;
-
-  std::sort(letters, letters + N);
-
-  // Use reverse_iterator_generator to print a sequence
-  // of letters in reverse order.
-  
-  boost::reverse_iterator_generator<char*>::type
-    reverse_letters_first(letters + N),
-    reverse_letters_last(letters);
-
-  std::cout << "letters in descending order:\t";
-  std::copy(reverse_letters_first, reverse_letters_last,
-      std::ostream_iterator<char>(std::cout));
-  std::cout << std::endl;
-
-  // to be continued...
-
-
- The output is: - -
-
-original sequence of letters: hello world!
-letters in descending order:  wroolllhed! 
-
-
- -

Template Parameters

- - - - - - - - - -
Parameter - - Description - -
BidirectionalIterator - - - The iterator type being wrapped. - -
Value - - The value-type of the base iterator and the resulting reverse - iterator.
- Default:std::iterator_traits<BidirectionalIterator>::value_type - - -
Reference - - The reference type of the resulting iterator, and in - particular, the result type of operator*().
- Default: If Value is supplied, Value& is - used. Otherwise - std::iterator_traits<BidirectionalIterator>::reference - is used. - -
Pointer - - The pointer type of the resulting iterator, and in - particular, the result type of operator->().
- Default: If Value was supplied, then Value*, - otherwise - std::iterator_traits<BidirectionalIterator>::pointer. - -
Category - - The iterator_category type for the resulting iterator.
- Default: - std::iterator_traits<BidirectionalIterator>::iterator_category - - -
Distance - - The difference_type for the resulting iterator.
- Default: - std::iterator_traits<BidirectionalIterator&gt::difference_type - -
- -

Concept Model

- The indirect iterator will model whichever standard iterator concept - category is modeled by the base iterator. Thus, if the base iterator is - a model of Random Access - Iterator then so is the resulting indirect iterator. If the base - iterator models a more restrictive concept, the resulting indirect iterator - will model the same concept. The base iterator must be at least a Bidirectional - Iterator - -

Members

- The reverse iterator type implements the member functions and operators - required of the Random Access - Iterator concept. In addition it has the following constructor: - -
-
-reverse_iterator_generator::type(const BidirectionalIterator& it)
-
-
- - -
-
- -
- -

- -

The Reverse Iterator Object - Generator

- The make_reverse_iterator() function provides a more convenient - way to create reverse iterator objects. The function saves the user the - trouble of explicitly writing out the iterator types. - -
-
-template <class BidirectionalIterator>
-typename reverse_iterator_generator<BidirectionalIterator>::type
-make_reverse_iterator(BidirectionalIterator base);
-
-
- -

Example

- In this part of the example we use make_reverse_iterator() to - print the sequence of letters in reverse-reverse order, which is the - original order. - -
-
-  // continuing from the previous example...
-
-  std::cout << "letters in ascending order:\t";
-  std::copy(boost::make_reverse_iterator(reverse_letters_last),
-      boost::make_reverse_iterator(reverse_letters_first),
-      std::ostream_iterator<char>(std::cout));
-  std::cout << std::endl;
-
-  return 0;
-}
-
-
- The output is: - -
-
-letters in ascending order:  !dehllloorw
-
-
-
- -

Constant/Mutable Iterator Interactions

- -

One failing of the standard reverse_iterator - adaptor is that it doesn't properly support interactions between adapted - const and non-const iterators. For example: -

-
-#include <vector>
-
-template <class T> void convert(T x) {}
-
-// Test interactions of a matched pair of random access iterators
-template <class Iterator, class ConstIterator>
-void test_interactions(Iterator i, ConstIterator ci)
-{
-  bool eq = i == ci;               // comparisons
-  bool ne = i != ci;            
-  bool lt = i < ci;
-  bool le = i <= ci;
-  bool gt = i > ci;
-  bool ge = i >= ci;
-  std::size_t distance = i - ci;   // difference
-  ci = i;                          // assignment
-  ConstIterator ci2(i);            // construction
-  convert<ConstIterator>(i);       // implicit conversion
-}
-
-void f()
-{
-  typedef std::vector<int> vec;
-  vec v;
-  const vec& cv;
-
-  test_interactions(v.begin(), cv.begin());   // OK
-  test_interactions(v.rbegin(), cv.rbegin()); // ERRORS ON EVERY TEST!!
-
-
-Reverse iterators created with boost::reverse_iterator_generator don't have this problem, though: -
-
-  typedef boost::reverse_iterator_generator<vec::iterator>::type ri;
-  typedef boost::reverse_iterator_generator<vec::const_iterator>::type cri;
-  test_interactions(ri(v.begin()), cri(cv.begin()));   // OK!!
-
-
-Or, more simply, -
-
-  test_interactions(
-    boost::make_reverse_iterator(v.begin()), 
-    boost::make_reverse_iterator(cv.begin()));   // OK!!
-}
-
-
- -

If you are wondering why there is no -reverse_iterator_pair_generator in the manner of projection_iterator_pair_generator, -the answer is simple: we tried it, but found that in practice it took -more typing to use reverse_iterator_pair_generator than to -simply use reverse_iterator_generator twice!

- -


- - -

Revised - 19 Aug 2001 - - -

© Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell - and distribute this document is granted provided this copyright notice - appears in all copies. This document is provided "as is" without express or - implied warranty, and with no claim as to its suitability for any purpose. - - - - - - - diff --git a/reverse_iterator_example.cpp b/reverse_iterator_example.cpp deleted file mode 100644 index f80bd1b..0000000 --- a/reverse_iterator_example.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -#include -#include -#include -#include - -int main(int, char*[]) -{ - char letters_[] = "hello world!"; - const int N = sizeof(letters_)/sizeof(char) - 1; -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - // 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 base_iterator; -#else - typedef char* base_iterator; -#endif - base_iterator letters(letters_); - - std::cout << "original sequence of letters:\t" - << letters_ << std::endl; - - std::sort(letters, letters + N); - - // Use reverse_iterator_generator to print a sequence - // of letters in reverse order. - - boost::reverse_iterator_generator::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(std::cout)); - std::cout << std::endl; - - // Use make_reverse_iterator() to print the sequence - // of letters in reverse-reverse order. - - std::cout << "letters in ascending order:\t"; - std::copy(boost::make_reverse_iterator(reverse_letters_last), - boost::make_reverse_iterator(reverse_letters_first), - std::ostream_iterator(std::cout)); - std::cout << std::endl; - - return 0; -} diff --git a/tie.html b/tie.html deleted file mode 100644 index 14219b4..0000000 --- a/tie.html +++ /dev/null @@ -1,143 +0,0 @@ - - - -Boost Tie - -C++ Boost - -
- -

-tie -

- -

-[This version of tie has been removed from the utility.hpp -header.  There is a new, more general version of tie 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.]

-
-template <class A, class B>
-tied<A,B> tie(A& a, B& b);
-
- -

-This is a utility function that makes it more convenient to work with -a function which returns a std::pair<>. The effect of the tie() -function is to allow the assignment of the two values of the pair to -two separate variables. The idea for this comes from Jaakko -Järvi's Binders [1]. - -

- -

Where Defined

- -

-boost/utility.hpp - -

- -

Example

- -

-An example of using the tie() function with the -vertices() function, which returns a pair of -type std::pair<vertex_iterator,vertex_iterator>. The -pair of iterators is assigned to the iterator variables i and -end. - -

-

-  graph_traits< adjacency_list<> >::vertex_iterator i, end;
-  for(tie(i,end) = vertices(G); i != end; ++i)
-    // ...
-
- -

-Here is another example that uses tie() for handling operations with std::set. - -

-

-#include <set>
-#include <algorithm>
-#include <iostream>
-#include <boost/utility.hpp>
-
-int
-main(int, char*[])
-{
-  {
-    typedef std::set<int> SetT;
-    SetT::iterator i, end;
-    bool inserted;
-    
-    int vals[5] = { 5, 2, 4, 9, 1 };
-    SetT s(vals, vals + 5);
-    
-    // Using tie() with a return value of pair<iterator,bool>
-
-    int new_vals[2] = { 3, 9 };
-
-    for (int k = 0; k < 2; ++k) {
-      boost::tie(i,inserted) = s.insert(new_vals[k]);
-      if (!inserted)
-        std::cout << *i << " was already in the set." << std::endl;
-      else
-        std::cout << *i << " successfully inserted." << std::endl;    
-    }
-  }    
-  {
-    int* i, *end;
-    int vals[6] = { 5, 2, 4, 4, 9, 1 };
-    std::sort(vals, vals + 6);
-
-    // Using tie() with a return value of pair<iterator,iterator>
-
-    boost::tie(i,end) = std::equal_range(vals, vals + 6, 4);
-    std::cout << "There were " << std::distance(i,end)
-              << " occurrences of " << *i << "." << std::endl;
-    // Footnote: of course one would normally just use std::count()
-    // to get this information, but that would spoil the example :)
-  }
-  return 0;
-}
-
-The output is: -
-  3 successfully inserted.
-  9 was already in the set.
-  There were 2 occurrences of 4.
-
- -
-
- - -
Copyright © 2000 -Jeremy Siek, -Univ.of Notre Dame (jsiek@lsc.nd.edu)
-Lie-Quan Lee, Univ.of Notre Dame (llee1@lsc.nd.edu)
-Andrew Lumsdaine, -Univ.of Notre Dame (lums@lsc.nd.edu) -
- - - diff --git a/tie_example.cpp b/tie_example.cpp deleted file mode 100644 index a2462df..0000000 --- a/tie_example.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -// -// This is an example demonstrating how to use the tie() function. -// The purpose of tie() is to make it easiery to deal with std::pair -// return values. -// -// Contributed by Jeremy Siek -// -// Sample output -// -// 3 successfully inserted. -// 9 was already in the set. -// There were 2 occurrences of 4. - -#include -#include -#include -#include // std::distance -// Note: tie() use to live in boost/utility.hpp, but -// not it is part of the more general Boost Tuple Library. -#include - -int -main(int, char*[]) -{ - { - typedef std::set SetT; - SetT::iterator i; - bool inserted; - - int vals[5] = { 5, 2, 4, 9, 1 }; - SetT s(vals, vals + 5); - - // Using tie() with a return value of pair - - int new_vals[2] = { 3, 9 }; - - for (int k = 0; k < 2; ++k) { - boost::tie(i,inserted) = s.insert(new_vals[k]); - if (!inserted) - std::cout << *i << " was already in the set." << std::endl; - else - std::cout << *i << " successfully inserted." << std::endl; - } - } - { - int* i, *end; - int vals[6] = { 5, 2, 4, 4, 9, 1 }; - std::sort(vals, vals + 6); - - // Using tie() with a return value of pair - - boost::tie(i,end) = std::equal_range(vals, vals + 6, 4); - std::cout << "There were " << std::distance(i,end) - << " occurrences of " << *i << "." << std::endl; - // Footnote: of course one would normally just use std::count() - // to get this information, but that would spoil the example :) - } - return 0; -} diff --git a/transform_iterator.htm b/transform_iterator.htm deleted file mode 100644 index 1e5aa8d..0000000 --- a/transform_iterator.htm +++ /dev/null @@ -1,223 +0,0 @@ - - - - - - -Transform Iterator Adaptor Documentation - - - - -c++boost.gif (8819 bytes) - -

Transform Iterator Adaptor

- -Defined in header -boost/iterator_adaptors.hpp - -

-The transform iterator adaptor augments an iterator by applying some -function object to the result of dereferencing the iterator. Another -words, the operator* of the transform iterator first -dereferences the base iterator, passes the result of this to the -function object, and then returns the result. The following -pseudo-code shows the basic idea: - -

-  value_type transform_iterator::operator*() const {
-    return this->f(*this->base_iterator);
-  }
-
- -All of the other operators of the transform iterator behave in the -same fashion as those of the base iterator. - - -

Synopsis

- -
-namespace boost {
-  template <class AdaptableUnaryFunction, class BaseIterator>
-  class transform_iterator_generator;
-
-  template <class AdaptableUnaryFunction, class BaseIterator>
-  typename transform_iterator_generator<AdaptableUnaryFunction,Iterator>::type
-  make_transform_iterator(BaseIterator base, const AdaptableUnaryFunction& f = AdaptableUnaryFunction());
-}
-
- -
- -

The Transform Iterator Type -Generator

- -The class transform_iterator_generator is a helper class whose -purpose is to construct a transform iterator type. The template -parameters for this class are the AdaptableUnaryFunction function object -type and the BaseIterator type that is being wrapped. - -
-template <class AdaptableUnaryFunction, class Iterator>
-class transform_iterator_generator
-{
-public:
-    typedef iterator_adaptor<...> type;
-};
-
- -

Example

- -

-The following is an example of how to use the -transform_iterator_generator class to iterate through a range -of numbers, multiplying each of them by 2 when they are dereferenced. -The boost::binder1st class is used instead of the standard -one because tranform iterator requires the function object to be -Default Constructible. - -

-

-#include <functional>
-#include <iostream>
-#include <boost/iterator_adaptors.hpp>
-
-// definition of class boost::binder1st and function boost::bind1st() ...
-
-int
-main(int, char*[])
-{
-  int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
-
-  typedef boost::binder1st< std::multiplies<int> > Function;
-  typedef boost::transform_iterator_generator<Function, int*>::type doubling_iterator;
-
-  doubling_iterator i(x, boost::bind1st(std::multiplies<int>(), 2)),
-    i_end(x + sizeof(x)/sizeof(int), boost::bind1st(std::multiplies<int>(), 2));
-
-  std::cout << "multiplying the array by 2:" << std::endl;
-  while (i != i_end)
-    std::cout << *i++ << " ";
-  std::cout << std::endl;
-
-  // to be continued...
-
-The output from this part is: -
-2 4 6 8 10 12 14 16
-
- -

Template Parameters

- - - - - - - - - - - - - - - - -
ParameterDescription
AdaptableUnaryFunctionThe function object that transforms each element in the iterator -range. The argument_type of the function object must match -the value type of the base iterator. The result_type of the -function object will be the resulting iterator's -value_type. If you want the resulting iterator to behave as -an iterator, the result of the function should be solely a function of -its argument. Also, the function object must be Default -Constructible (which many of the standard function objects are not).
BaseIteratorThe iterator type being wrapped. This type must at least be a model - of the InputIterator concept.
- -

Model of

- -The transform iterator adaptor (the type -transform_iterator_generator<...>::type) is a model of Input Iterator[1]. - - -

Members

- -The transform iterator type implements the member functions and -operators required of the Random Access Iterator -concept, except that the reference type is the same as the value_type -so operator*() returns by-value. In addition it has the following constructor: - -
-transform_iterator_generator::type(const BaseIterator& it,
-                                   const AdaptableUnaryFunction& f = AdaptableUnaryFunction())
-
- -

-


-

- - -

The Transform Iterator Object Generator

- -
-template <class AdaptableUnaryFunction, class BaseIterator>
-typename transform_iterator_generator<AdaptableUnaryFunction,BaseIterator>::type
-make_transform_iterator(BaseIterator base,
-                        const AdaptableUnaryFunction& f = AdaptableUnaryFunction());
-
- -This function provides a convenient way to create transform iterators. - -

Example

- -Continuing from the previous example, we use the make_transform_iterator() -function to add four to each element of the array. - -
-  std::cout << "adding 4 to each element in the array:" << std::endl;
-
-  std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus(), 4)),
-	    boost::make_transform_iterator(x + N, boost::bind1st(std::plus(), 4)),
-	    std::ostream_iterator(std::cout, " "));
-  std::cout << std::endl;
-
-  return 0;
-}
-
-The output from this part is: -
-5 6 7 8 9 10 11 12
-
- -

Notes

- - -[1] If the base iterator is a model of Random Access Iterator -then the transform iterator will also suppport most of the -functionality required by the Random Access Iterator concept. However, a -transform iterator can never completely satisfy the requirements for -Forward Iterator -(or of any concepts that refine Forward Iterator, which includes -Random Access Iterator and Bidirectional Iterator) since the operator* of the transform -iterator always returns by-value. - - - -
-

Revised 19 Aug 2001

-

© Copyright Jeremy Siek 2000. Permission to copy, use, -modify, sell and distribute this document is granted provided this copyright -notice appears in all copies. This document is provided "as is" -without express or implied warranty, and with no claim as to its suitability for -any purpose.

- - - - diff --git a/transform_iterator_example.cpp b/transform_iterator_example.cpp deleted file mode 100644 index f65a493..0000000 --- a/transform_iterator_example.cpp +++ /dev/null @@ -1,76 +0,0 @@ -// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - - -#include -#include -#include -#include - -// What a bummer. We can't use std::binder1st with transform iterator -// because it does not have a default constructor. Here's a version -// that does. - -namespace boost { - - template - class binder1st - : public std::unary_function { - protected: - Operation op; - typename Operation::first_argument_type value; - public: - binder1st() { } // this had to be added! - binder1st(const Operation& x, - const typename Operation::first_argument_type& y) - : op(x), value(y) {} - typename Operation::result_type - operator()(const typename Operation::second_argument_type& x) const { - return op(value, x); - } - }; - - template - inline binder1st bind1st(const Operation& op, const T& x) { - typedef typename Operation::first_argument_type arg1_type; - return binder1st(op, arg1_type(x)); - } - -} // namespace boost - -int -main(int, char*[]) -{ - // This is a simple example of using the transform_iterators class to - // generate iterators that multiply the value returned by dereferencing - // the iterator. In this case we are multiplying by 2. - // Would be cooler to use lambda library in this example. - - int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; - const int N = sizeof(x)/sizeof(int); - - typedef boost::binder1st< std::multiplies > Function; - typedef boost::transform_iterator_generator::type doubling_iterator; - - doubling_iterator i(x, boost::bind1st(std::multiplies(), 2)), - i_end(x + N, boost::bind1st(std::multiplies(), 2)); - - std::cout << "multiplying the array by 2:" << std::endl; - while (i != i_end) - std::cout << *i++ << " "; - std::cout << std::endl; - - std::cout << "adding 4 to each element in the array:" << std::endl; - - std::copy(boost::make_transform_iterator(x, boost::bind1st(std::plus(), 4)), - boost::make_transform_iterator(x + N, boost::bind1st(std::plus(), 4)), - std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; - - return 0; -} - - diff --git a/transform_iterator_test.cpp b/transform_iterator_test.cpp deleted file mode 100644 index a1f173e..0000000 --- a/transform_iterator_test.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// Revision History -// 08 Mar 2001 Jeremy Siek -// Moved test of transform iterator into its own file. It to -// to be in iterator_adaptor_test.cpp. - -#include -#include -#include -#include -#include - -struct mult_functor { - typedef int result_type; - typedef int argument_type; - // Functors used with transform_iterator must be - // DefaultConstructible, as the transform_iterator must be - // DefaultConstructible to satisfy the requirements for - // TrivialIterator. - mult_functor() { } - mult_functor(int aa) : a(aa) { } - int operator()(int b) const { return a * b; } - int a; -}; - -int -main() -{ - const int N = 10; - - // Borland is getting confused about typedef's and constructors here - - // Test transform_iterator - { - int x[N], y[N]; - for (int k = 0; k < N; ++k) - x[k] = k; - std::copy(x, x + N, y); - - for (int k2 = 0; k2 < N; ++k2) - x[k2] = x[k2] * 2; - - boost::transform_iterator_generator::type i(y, mult_functor(2)); - boost::input_iterator_test(i, x[0], x[1]); - boost::input_iterator_test(boost::make_transform_iterator(&y[0], mult_functor(2)), x[0], x[1]); - } - std::cout << "test successful " << std::endl; - return 0; -} diff --git a/utility.htm b/utility.htm deleted file mode 100644 index 9a24679..0000000 --- a/utility.htm +++ /dev/null @@ -1,193 +0,0 @@ - - - - -Header boost/utility.hpp Documentation - - - - -

c++boost.gif (8819 bytes)Header -boost/utility.hpp

- -

The entire contents of the header <boost/utility.hpp> - are in namespace boost.

- -

Contents

- - -

Function templates checked_delete() and -checked_array_delete()

- -

Deletion of a pointer to an incomplete type is an unsafe programming practice -because there is no way for the compiler to verify that the destructor is indeed -trivial.  The checked_delete() and checked_array_delete() function -templates simply delete or delete[] their argument, but also -require that their argument be a complete type.  They issue an appropriate -compiler error diagnostic if that requirement is not met.  A typical -implementation is shown; other implementations may vary:

- -
    template< typename T >
-    inline void checked_delete(T const volatile * x)
-    {
-        BOOST_STATIC_ASSERT( sizeof(T) ); // assert type complete at point
-                                          // of instantiation
-        delete x;
-    }
-
-    template< typename T >
-    inline void checked_array_delete(T const volatile * x)
-    {
-        BOOST_STATIC_ASSERT( sizeof(T) ); // assert type complete at point
-                                          // of instantiation
-        delete [] x;
-    }
- -

Contributed by Beman Dawes, based on a suggestion from Dave Abrahams, -generalizing an idea from Vladimir Prus, with comments from Rainer Deyke, John -Maddock, and others.

- -

Background

- -

The C++ Standard specifies that delete on a pointer to an incomplete types is -undefined behavior if the type has a non-trivial destructor in  [expr.delete] -5.3.5 paragraph.  No diagnostic is required.  Some but not all -compilers issue warnings if the type is incomplete at point of deletion.

- -

Function templates next() and prior()

- -

Certain data types, such as the C++ Standard Library's forward and -bidirectional iterators, do not provide addition and subtraction via operator+() -or operator-().  This means that non-modifying computation of the next or -prior value requires a temporary, even though operator++() or operator--() is -provided.  It also means that writing code like itr+1 inside a -template restricts the iterator category to random access iterators.

- -

The next() and prior() functions provide a simple way around these problems:

- -
- -
template <class T>
-T next(T x) { return ++x; }
-
-template <class X>
-T prior(T x) { return --x; }
- -
- -

Usage is simple:

- -
- -
const std::list<T>::iterator p = get_some_iterator();
-const std::list<T>::iterator prev = boost::prior(p);
- -
- -

Contributed by Dave Abrahams.

- -

Class noncopyable

- -

Class noncopyable is a base class.  Derive your own class from noncopyable -when you want to prohibit copy construction and copy assignment.

- -

Some objects, particularly those which hold complex resources like files or -network connections, have no sensible copy semantics.  Sometimes there are -possible copy semantics, but these would be of very limited usefulness and be -very difficult to implement correctly.  Sometimes you're implementing a class that doesn't need to be copied -just yet and you don't want to take the time to write the appropriate functions.  -Deriving from noncopyable will prevent the otherwise implicitly-generated -functions (which don't have the proper semantics) from becoming a trap for other programmers.

- -

The traditional way to deal with these is to declare a private copy constructor and copy assignment, and then -document why this is done.  But deriving from noncopyable is simpler -and clearer, and doesn't require additional documentation.

- -

The program noncopyable_test.cpp can be -used to verify class noncopyable works as expected. It has have been run successfully under -GCC 2.95, Metrowerks -CodeWarrior 5.0, and Microsoft Visual C++ 6.0 sp 3.

- -

Contributed by Dave Abrahams.

- -

Example

-
-
// inside one of your own headers ...
-#include <boost/utility.hpp>
-
-class ResourceLadenFileSystem : boost::noncopyable {
-...
-
- -

Rationale

-

Class noncopyable has protected constructor and destructor members to -emphasize that it is to be used only as a base class.  Dave Abrahams notes -concern about the effect on compiler optimization of adding (even trivial inline) -destructor declarations. He says "Probably this concern is misplaced, because -noncopyable will be used mostly for classes which own resources and thus have non-trivial destruction semantics."

-

Function template addressof()

-

Function addressof() returns the address of an object.

- -
-
-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);
-
-
- - -

C++ allows programmers to replace the unary -operator&() 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 -operator&(). Function addressof() -provides a wrapper around the necessary code to make it easy to get an -object's real address. -

- -

The program addressof_test.cpp can be -used to verify that addressof() works as expected.

- -

Contributed by Brad King based on ideas from discussion with Doug Gregor.

-

Example

-
-
#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 */
-}
-
- -

Class templates for the Base-from-Member Idiom

-

See separate documentation.

-

Function template tie()

-

See separate documentation.

-
-

Revised  10 September, 2001 -

-

© Copyright boost.org 1999. Permission to copy, use, modify, sell and -distribute this document is granted provided this copyright notice appears in -all copies. This document is provided "as is" without express or -implied warranty, and with no claim as to its suitability for any purpose.

- -