diff --git a/Assignable.html b/Assignable.html deleted file mode 100644 index 557f4e7..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/Collection.html b/Collection.html deleted file mode 100644 index 9069e28..0000000 --- a/Collection.html +++ /dev/null @@ -1,648 +0,0 @@ - - - -Collection - - - -

- boost logo -
Collection -

- -

Description

- -A Collection is a concept similar to the STL Container -concept. A Collection provides iterators for accessing a range of -elements and provides information about the number of elements in the -Collection. However, a Collection has fewer requirements than a -Container. The motivation for the Collection concept is that there are -many useful Container-like types that do not meet the full -requirements of Container, and many algorithms that can be written -with this reduced set of requirements. To summarize the reduction -in requirements: - - - - -Because of the reduced requirements, some care must be taken when -writing code that is meant to be generic for all Collection types. -In particular, a Collection object should be passed by-reference -since assumptions can not be made about the behaviour of the -copy constructor. - -

- -

Associated types

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Value type - -X::value_type - -The type of the object stored in a Collection. -If the Collection is mutable then -the value type must be Assignable. -Otherwise the value type must be CopyConstructible. -
-Iterator type - -X::iterator - -The type of iterator used to iterate through a Collection's - elements. The iterator's value type is expected to be the - Collection's value type. A conversion - from the iterator type to the const iterator type must exist. - The iterator type must be an InputIterator. -
-Const iterator type - -X::const_iterator - -A type of iterator that may be used to examine, but not to modify, - a Collection's elements. -
-Reference type - -X::reference - -A type that behaves like a reference to the Collection's value type. -[1] -
-Const reference type - -X::const_reference - -A type that behaves like a const reference to the Collection's value type. -
-Pointer type - -X::pointer - -A type that behaves as a pointer to the Collection's value type. -
-Distance type - -X::difference_type - -A signed integral type used to represent the distance between two - of the Collection's iterators. This type must be the same as - the iterator's distance type. -
-Size type - -X::size_type - -An unsigned integral type that can represent any nonnegative value - of the Collection's distance type. -
-

Notation

- - - - - - - - - - - - - -
-X - -A type that is a model of Collection. -
-a, b - -Object of type X. -
-T - -The value type of X. -
- -

Valid expressions

- -The following expressions must be valid. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Name - -Expression - -Return type -
-Beginning of range - -a.begin() - -iterator if a is mutable, const_iterator otherwise -
-End of range - -a.end() - -iterator if a is mutable, const_iterator otherwise -
-Size - -a.size() - -size_type -
-Empty Collection - -a.empty() - -Convertible to bool -
-Swap - -a.swap(b) - -void -
-

Expression semantics

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Name - -Expression - -Semantics - -Postcondition -
-
-Beginning of range - -a.begin() - -Returns an iterator pointing to the first element in the Collection. - -a.begin() is either dereferenceable or past-the-end. It is - past-the-end if and only if a.size() == 0. -
-End of range - -a.end() - -Returns an iterator pointing one past the last element in the - Collection. - -a.end() is past-the-end. -
-Size - -a.size() - -Returns the size of the Collection, that is, its number of elements. - -a.size() >= 0 -
-Empty Collection - -a.empty() - -Equivalent to a.size() == 0. (But possibly faster.) - -  -
-Swap - -a.swap(b) - -Equivalent to swap(a,b) - -  -
-

Complexity guarantees

- -begin() and end() are amortized constant time. -

-size() is at most linear in the Collection's -size. empty() is amortized constant time. -

-swap() is at most linear in the size of the two collections. -

Invariants

- - - - - - - - - - - - - -
-Valid range - -For any Collection a, [a.begin(), a.end()) is a valid - range. -
-Range size - -a.size() is equal to the distance from a.begin() to a.end(). -
-Completeness - -An algorithm that iterates through the range [a.begin(), a.end()) - will pass through every element of a. -
- - -

Models

- - - -

Collection Refinements

- -There are quite a few concepts that refine the Collection concept, -similar to the concepts that refine the Container concept. Here -is a brief overview of the refining concepts. - -

ForwardCollection

-The elements are arranged in some order that -does not change spontaneously from one iteration to the next. As -a result, a ForwardCollection is -EqualityComparable -and -LessThanComparable. -In addition, the iterator type of a ForwardCollection is a -MultiPassInputIterator which is just an InputIterator with the added -requirements that the iterator can be used to make multiple passes -through a range, and that if it1 == it2 and it1 is -dereferenceable then ++it1 == ++it2. The ForwardCollection -also has a front() method. - -

- - - - - - - - - - - - - - - -
-Name - -Expression - -Return type - -Semantics -
-Front - -a.front() - -reference if a is mutable,
const_reference -otherwise. -
-Equivalent to *(a.begin()). -
- - -

ReversibleCollection

- -The container provides access to iterators that traverse in both -directions (forward and reverse). The iterator type must meet all of -the requirements of -BidirectionalIterator -except that the reference type does not have to be a real C++ -reference. The ReversibleCollection adds the following requirements -to those of ForwardCollection. -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Name - -Expression - -Return type - -Semantics -
-Beginning of range - -a.rbegin() - -reverse_iterator if a is mutable, -const_reverse_iterator otherwise. - -Equivalent to X::reverse_iterator(a.end()). -
-End of range - -a.rend() - -reverse_iterator if a is mutable, -const_reverse_iterator otherwise. - -Equivalent to X::reverse_iterator(a.begin()). -
-Back - -a.back() - -reference if a is mutable,
const_reference -otherwise. -
-Equivalent to *(--a.end()). -
- -

SequentialCollection

- -The elements are arranged in a strict linear order. No extra methods -are required. - -

RandomAccessCollection

- -The iterators of a RandomAccessCollection satisfy all of the -requirements of RandomAccessIterator -except that the reference type does not have to be a real C++ -reference. In addition, a RandomAccessCollection provides -an element access operator. - -

- - - - - - - - - - - - - - - -
-Name - -Expression - -Return type - -Semantics -
-Element Access - -a[n] - -reference if a is mutable, -const_reference otherwise. - -Returns the nth element of the Collection. -n must be convertible to size_type. -Precondition: 0 <= n < a.size(). -
- -

Notes

- -

[1] - -The reference type does not have to be a real C++ reference. The -requirements of the reference type depend on the context within which -the Collection is being used. Specifically it depends on the -requirements the context places on the value type of the Collection. -The reference type of the Collection must meet the same requirements -as the value type. In addition, the reference objects must be -equivalent to the value type objects in the collection (which is -trivially true if they are the same object). Also, in a mutable -Collection, an assignment to the reference object must result in an -assignment to the object in the Collection (again, which is trivially -true if they are the same object, but non-trivial if the reference -type is a proxy class). - -

See also

-Container - - -
-
- - -
Copyright © 2000 -Jeremy Siek, Univ.of Notre Dame and C++ Library & Compiler Group/SGI (jsiek@engr.sgi.com) -
- - - diff --git a/CopyConstructible.html b/CopyConstructible.html deleted file mode 100644 index f2d6308..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 8913b38..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 dec6e31..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/OptionalPointee.html b/OptionalPointee.html deleted file mode 100644 index a6d6d97..0000000 --- a/OptionalPointee.html +++ /dev/null @@ -1,158 +0,0 @@ - - -OptionalPointee Concept - - -C++ Boost - -
-

Concept: OptionalPointee

- -

Description

-A type is a model of OptionalPointee if it points to (or refers to) a value -that may not exist. That is, if it has a pointee which might be valid -(existent) or invalid (inexistent); and it is possible to test whether the -pointee is valid or not. -This model does not imply pointer semantics: i.e., it does not imply shallow copy nor -aliasing. -

Notation

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

Definitions

-

Valid expressions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Name Expression Return type Semantics
Value Access *t T&If the pointee is valid returns a reference to - the pointee.
- If the pointee is invalid the result is undefined.
Value Access t->xyz T*If the pointee is valid returns a builtin pointer to the pointee.
- If the pointee is invalid the result is undefined (It might not even return NULL).
-
Validity Test t
-  t != 0
-  !!t -
 bool If the pointee is valid returns true.
- If the pointee is invalid returns false.
Invalidity Test t == 0
-  !t -
 bool If the pointee is valid returns false.
- If the pointee is invalid returns true.
- - -

Models

- - - -
-

OptionalPointee and relational operations

-

This concept does not define any particular semantic for relational operations, therefore, -a type which models this concept might have either shallow or deep relational semantics.
-For instance, pointers, which are models of OptionalPointee, have shallow relational operators: -comparisons of pointers do not involve comparisons of pointees. -This makes sense for pointers because they have shallow copy semantics.
-But boost::optional<T>, on the other hand, which is also a model of OptionalPointee, has -deep-copy and deep-relational semantics.
-If generic code is written for this concept, it is important not to use relational -operators directly because the semantics might be different depending on the actual type.
-Still, the concept itsef can be used to define deep relational tests that can -be used in generic code with any type which models OptionalPointee:

- -

Equivalence relation:

-
template<class OptionalPointee>
-inline
-bool equal_pointees ( OptionalPointee const& x, OptionalPointee const& y )
-{
-  return (!x) != (!y) ? false : ( !x ? true : (*x) == (*y) ) ;
-}
-template<class OptionalPointee>
-struct equal_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
-{
-  bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
-    { return equal_pointees(x,y) ; }
-} ;
-
-

The preceding generic function and function object have the following semantics:
-If both x and y have valid pointees, it compares values via (*x == *y).
-If only one has a valid pointee, returns false.
-If both have invalid pointees, returns true.

- -

Less-than relation:

-
template<class OptionalPointee>
-inline
-bool less_pointees ( OptionalPointee const& x, OptionalPointee const& y )
-{
-  return !y ? false : ( !x ? true : (*x) < (*y) ) ;
-}
-template<class OptionalPointee>
-struct less_pointees_t : std::binary_function<OptionalPointee,OptionalPointee,bool>
-{
-  bool operator() ( OptionalPointee const& x, OptionalPointee const& y ) const
-    { return less_pointees(x,y) ; }
-} ;
-
-

The preceding generic function and function object have the following semantics:
-If y has an invalid pointee, returns false.
-Else, if x has an invalid pointee, returns true.
-Else, ( x and y have valid pointees), compares values via (*x < -*y).

-


-All these functions and function -objects are is implemented in compare_pointees.hpp

-

Notice that OptionalPointee does not imply aliasing (and optional<> for instance does not alias); -so direct usage of relational operators with the implied aliasing of shallow semantics --as with pointers- should not be used with generic code written for this concept.

- -
-
- - -
Copyright © 2003 -Fernando Cacciola, -based on the original concept developed by Augustus Saunders. -
- - - \ No newline at end of file diff --git a/addressof_test.cpp b/addressof_test.cpp deleted file mode 100644 index 9619cc3..0000000 --- a/addressof_test.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (C) 2002 Brad King (brad.king@kitware.com) -// Douglas Gregor (gregod@cs.rpi.edu) -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// For more information, see http://www.boost.org - - -#include - -#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) -#pragma warning(push, 3) -#endif - -#include - -#if defined(BOOST_MSVC) && (BOOST_MSVC < 1300) -#pragma warning(pop) -#endif - -#include - -template void scalar_test( T * = 0 ) -{ - T* px = new T(); - - T& x = *px; - BOOST_TEST( boost::addressof(x) == px ); - - const T& cx = *px; - const T* pcx = boost::addressof(cx); - BOOST_TEST( pcx == px ); - - volatile T& vx = *px; - volatile T* pvx = boost::addressof(vx); - BOOST_TEST( pvx == px ); - - const volatile T& cvx = *px; - const volatile T* pcvx = boost::addressof(cvx); - BOOST_TEST( pcvx == px ); - - delete px; -} - -template void array_test( T * = 0 ) -{ - T nrg[3] = {1,2,3}; - T (*pnrg)[3] = &nrg; - BOOST_TEST( boost::addressof(nrg) == pnrg ); - - T const cnrg[3] = {1,2,3}; - T const (*pcnrg)[3] = &cnrg; - BOOST_TEST( boost::addressof(cnrg) == pcnrg ); -} - -struct addressable -{ - addressable( int = 0 ) - { - } -}; - -struct useless_type {}; - -class nonaddressable { -public: - - nonaddressable( int = 0 ) - { - } - - void dummy(); // Silence GCC warning: all member of class are private - -private: - - useless_type operator&() const; -}; - -int main() -{ - scalar_test(); - scalar_test(); - scalar_test(); - scalar_test(); - - array_test(); - array_test(); - array_test(); - array_test(); - - return boost::report_errors(); -} diff --git a/assert.html b/assert.html deleted file mode 100644 index 617f212..0000000 --- a/assert.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - Boost: assert.hpp documentation - - - - - - - - - - - -
- boost.png (6897 bytes) - -

assert.hpp

-
 
-

- The header <boost/assert.hpp> defines the macro BOOST_ASSERT, - which is similar to the standard assert macro defined in <cassert>. - The macro is intended to be used in Boost libraries. -

-

By default, BOOST_ASSERT(expr) is equivalent to assert(expr).

-

When the macro BOOST_DISABLE_ASSERTS is defined when <boost/assert.hpp> - is included, BOOST_ASSERT(expr) is defined as ((void)0). This - allows users to selectively disable BOOST_ASSERT without - affecting the definition of the standard assert.

-

When the macro BOOST_ENABLE_ASSERT_HANDLER is defined when <boost/assert.hpp> - is included, BOOST_ASSERT(expr) evaluates expr and, if the - result is false, evaluates the expression

-

::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, - __FILE__, __LINE__)

-

assertion_failed is declared in <boost/assert.hpp> - as

-
-namespace boost
-{
-
-void assertion_failed(char const * expr, char const * function, char const * file, long line);
-
-}
-
-

but it is never defined. The user is expected to supply an appropriate - definition.

-

As is the case with <cassert>, <boost/assert.hpp> - can be included multiple times in a single translation unit. BOOST_ASSERT - will be redefined each time as specified above.

-


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

- - diff --git a/assert_test.cpp b/assert_test.cpp deleted file mode 100644 index 693adc4..0000000 --- a/assert_test.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// -// assert_test.cpp - a test for boost/assert.hpp -// -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -#include - -#include - -void test_default() -{ - int x = 1; - - BOOST_ASSERT(1); - BOOST_ASSERT(x); - BOOST_ASSERT(x == 1); - BOOST_ASSERT(&x); -} - -#define BOOST_DISABLE_ASSERTS -#include - -void test_disabled() -{ - int x = 1; - - BOOST_ASSERT(1); - BOOST_ASSERT(x); - BOOST_ASSERT(x == 1); - BOOST_ASSERT(&x); - - BOOST_ASSERT(0); - BOOST_ASSERT(!x); - BOOST_ASSERT(x == 0); - - void * p = 0; - - BOOST_ASSERT(p); - - // supress warnings - p = &x; - p = &p; -} - -#undef BOOST_DISABLE_ASSERTS - -#define BOOST_ENABLE_ASSERT_HANDLER -#include -#include -#include - -int handler_invoked = 0; - -void boost::assertion_failed(char const * expr, char const * function, char const * file, long line) -{ -#if !defined(BOOST_NO_STDC_NAMESPACE) - using std::printf; -#endif - - printf("Expression: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n", expr, function, file, line); - ++handler_invoked; -} - -struct X -{ - static void f() - { - BOOST_ASSERT(0); - } -}; - -void test_handler() -{ - int x = 1; - - BOOST_ASSERT(1); - BOOST_ASSERT(x); - BOOST_ASSERT(x == 1); - BOOST_ASSERT(&x); - - BOOST_ASSERT(0); - BOOST_ASSERT(!x); - BOOST_ASSERT(x == 0); - - void * p = 0; - - BOOST_ASSERT(p); - - X::f(); - - BOOST_ASSERT(handler_invoked == 5); - BOOST_TEST(handler_invoked == 5); -} - -#undef BOOST_ENABLE_ASSERT_HANDLER - -int main() -{ - test_default(); - test_disabled(); - test_handler(); - - return boost::report_errors(); -} diff --git a/base_from_member.html b/base_from_member.html deleted file mode 100644 index d5cba0b..0000000 --- a/base_from_member.html +++ /dev/null @@ -1,371 +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.

- -

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. R. Samuel 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

- -
-#ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY
-#define BOOST_BASE_FROM_MEMBER_MAX_ARITY  10
-#endif
-
-template < typename MemberType, int UniqueID = 0 >
-class boost::base_from_member
-{
-protected:
-    MemberType  member;
-
-    base_from_member();
-
-    template< typename T1 >
-    explicit  base_from_member( T1 x1 );
-
-    template< typename T1, typename T2 >
-    base_from_member( T1 x1, T2 x2 );
-
-    //...
-
-    template< typename T1, typename T2, typename T3, typename T4,
-     typename T5, typename T6, typename T7, typename T8, typename T9,
-     typename T10 >
-    base_from_member( T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, T6 x6, T7 x7,
-     T8 x8, T9 x9, T10 x10 );
-};
-
- -

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 ten) as possible and pass them to a constructor of -the data member. Since C++ does not allow any way to explicitly state -the template parameters of a templated constructor, make sure that -the arguments are already close as possible to the actual type used in -the data member's desired constructor.

- -

The BOOST_BASE_FROM_MEMBER_MAX_ARITY macro constant specifies -the maximum argument length for the constructor templates. The constant -may be overridden if more (or less) argument configurations are needed. The -constant may be read for code that is expandable like the class template and -needs to maintain the same maximum size. (Example code would be a class that -uses this class template as a base class for a member with a flexible set of -constructors.)

- -

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. - -
R. Samuel Klatchko (rsk@moocat.org, rsk@brightmail.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. - -
Jonathan Turkanis -
Supplied an implementation of generating the constructor templates that - can be controlled and automated with macros. The implementation uses - the Preprocessor library. - -
Daryle Walker -
Started the library. Contributed the test file base_from_member_test.cpp. -
- -
- -

Revised: 28 August 2004

- -

Copyright 2001, 2003, 2004 Daryle Walker. Use, modification, and distribution -are subject to the Boost Software License, Version 1.0. (See accompanying -file LICENSE_1_0.txt or a copy at <http://www.boost.org/LICENSE_1_0.txt>.)

- - - diff --git a/base_from_member_test.cpp b/base_from_member_test.cpp deleted file mode 100644 index 89328e4..0000000 --- a/base_from_member_test.cpp +++ /dev/null @@ -1,595 +0,0 @@ -// Boost test program for base-from-member class templates -----------------// - -// Copyright 2001, 2003 Daryle Walker. Use, modification, and distribution are -// subject to the Boost Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or a copy at .) - -// See for the library's home page. - -// Revision History -// 14 Jun 2003 Adjusted code for Boost.Test changes (Daryle Walker) -// 29 Aug 2001 Initial Version (Daryle Walker) - -#include // for BOOST_CHECK, 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_CHECK( obj_reg.db_.empty() ); - BOOST_CHECK( obj_reg.defrauders_in_.empty() ); - BOOST_CHECK( obj_reg.defrauders_out_.empty() ); - BOOST_CHECK( obj_reg.overeager_.empty() ); - BOOST_CHECK( obj_reg.overkilled_.empty() ); - - // Make a separate block to examine pre- and post-effects - { - using std::cout; - using std::endl; - - bad_class bc; - BOOST_CHECK( obj_reg.db_.size() == 3 ); - BOOST_CHECK( obj_reg.defrauders_in_.size() == 1 ); - - good_class_1 gc1; - BOOST_CHECK( obj_reg.db_.size() == 6 ); - BOOST_CHECK( obj_reg.defrauders_in_.size() == 1 ); - - good_class_2 gc2; - BOOST_CHECK( obj_reg.db_.size() == 11 ); - BOOST_CHECK( obj_reg.defrauders_in_.size() == 1 ); - - BOOST_CHECK( obj_reg.defrauders_out_.empty() ); - BOOST_CHECK( obj_reg.overeager_.empty() ); - BOOST_CHECK( obj_reg.overkilled_.empty() ); - - // Getting the addresses of the objects ensure - // that they're used, and not optimized away. - cout << "Object 'bc' is at " << &bc << '.' << endl; - cout << "Object 'gc1' is at " << &gc1 << '.' << endl; - cout << "Object 'gc2' is at " << &gc2 << '.' << endl; - } - - BOOST_CHECK( obj_reg.db_.empty() ); - BOOST_CHECK( obj_reg.defrauders_in_.size() == 1 ); - BOOST_CHECK( obj_reg.defrauders_out_.size() == 1 ); - BOOST_CHECK( obj_reg.overeager_.empty() ); - BOOST_CHECK( obj_reg.overkilled_.empty() ); - - return boost::exit_success; -} - - -// Print an object's ID -std::ostream & -operator << -( - std::ostream & os, - object_id const & oi -) -{ - // I had an std::ostringstream to help, but I did not need it since - // the program never screws around with formatting. Worse, using - // std::ostringstream is an issue with some compilers. - - return os << '[' << ( oi.second ? oi.second->name() : "NOTHING" ) - << " at " << oi.first << ']'; -} - -// Get an object ID given an object -template < typename T > -inline -object_id -identify -( - T & obj -) -{ - return std::make_pair( static_cast(&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 c17a859..0000000 --- a/binary_search_test.cpp +++ /dev/null @@ -1,258 +0,0 @@ -// (C) Copyright David Abrahams 2000. -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include -#include -#include -#include -#include -#include -#include // for rand(). Would use cstdlib but VC6.4 doesn't put it in std:: -#include -#include -#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 { - -// In order to get ADL to find the comparison operators defined below, they have -struct mystring : std::string -{ - typedef std::string base; - - mystring(std::string const& x) - : base(x) {} -}; - -typedef std::vector 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 mystring& x, const unsigned y) -{ - return to_int(x) < y; -} - -inline bool operator<(const unsigned y, const mystring& x) -{ - return y < to_int(x); -} - -template -void sort_by_value(T& x); - -template -void sort_by_value_(T& v, long) -{ - 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); -} - -template -void sort_by_value_(std::list& l, int) -{ -# if BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) && !defined(__SGI_STL_PORT) -// VC6's standard lib doesn't have a template member function for list::sort() - std::vector seq; - seq.reserve(sequence_length); - std::copy(l.begin(), l.end(), std::back_inserter(seq)); - sort_by_value(seq); - std::copy(seq.begin(), seq.end(), l.begin()); -# else - l.sort(cmp()); -# endif -} - -template -void sort_by_value(T& x) -{ - (sort_by_value_)(x, 1); -} - -// A way to select the comparisons with/without a Compare parameter for testing. -template 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() -{ - string_vector x; - std::cout << "=== testing random-access iterators with <: ===\n"; - test_loop(x, no_compare(), 25); - std::cout << "=== testing random-access iterators with compare: ===\n"; - test_loop(x, cmp(), 25); - - std::list 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 53f093e..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 f5ac3a2..0000000 --- a/call_traits_test.cpp +++ /dev/null @@ -1,466 +0,0 @@ -// boost::compressed_pair test program - -// (C) Copyright John Maddock 2000. -// Use, modification and distribution are subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt). - - -// standalone test program for -// 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 -#include - -// -// define tests here -unsigned failures = 0; -unsigned test_count = 0; -// -// This must get defined within the test file. -// All compilers have bugs, set this to the number of -// regressions *expected* from a given compiler, -// if there are no workarounds for the bugs, *and* -// the regressions have been investigated. -// -extern unsigned int expected_failures; -// -// proc check_result() -// Checks that there were no regressions: -// -int check_result(int argc, char** argv) -{ - std::cout << test_count << " tests completed, " - << failures << " failures found, " - << expected_failures << " failures expected from this compiler." << std::endl; - if((argc == 2) - && (argv[1][0] == '-') - && (argv[1][1] == 'a') - && (argv[1][2] == 0)) - { - std::cout << "Press any key to continue..."; - std::cin.get(); - } - return (failures == expected_failures) - ? 0 - : (failures != 0) ? static_cast(failures) : -1; -} - -// 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; - - BOOST_CHECK_TYPE(comparible_UDT, boost::call_traits::value_type); - BOOST_CHECK_TYPE(comparible_UDT&, boost::call_traits::reference); - BOOST_CHECK_TYPE(const comparible_UDT&, boost::call_traits::const_reference); - BOOST_CHECK_TYPE(const comparible_UDT&, boost::call_traits::param_type); - BOOST_CHECK_TYPE(int, boost::call_traits::value_type); - BOOST_CHECK_TYPE(int&, boost::call_traits::reference); - BOOST_CHECK_TYPE(const int&, boost::call_traits::const_reference); - BOOST_CHECK_TYPE(const int, boost::call_traits::param_type); - BOOST_CHECK_TYPE(int*, boost::call_traits::value_type); - BOOST_CHECK_TYPE(int*&, boost::call_traits::reference); - BOOST_CHECK_TYPE(int*const&, boost::call_traits::const_reference); - BOOST_CHECK_TYPE(int*const, boost::call_traits::param_type); -#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) - BOOST_CHECK_TYPE(int&, boost::call_traits::value_type); - BOOST_CHECK_TYPE(int&, boost::call_traits::reference); - BOOST_CHECK_TYPE(const int&, boost::call_traits::const_reference); - BOOST_CHECK_TYPE(int&, boost::call_traits::param_type); -#if !(defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1))) - BOOST_CHECK_TYPE(int&, boost::call_traits::value_type); - BOOST_CHECK_TYPE(int&, boost::call_traits::reference); - BOOST_CHECK_TYPE(const int&, boost::call_traits::const_reference); - BOOST_CHECK_TYPE(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 - BOOST_CHECK_TYPE(const int&, boost::call_traits::value_type); - BOOST_CHECK_TYPE(const int&, boost::call_traits::reference); - BOOST_CHECK_TYPE(const int&, boost::call_traits::const_reference); - BOOST_CHECK_TYPE(const int&, boost::call_traits::param_type); -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - BOOST_CHECK_TYPE(const int*, boost::call_traits::value_type); - BOOST_CHECK_TYPE(int(&)[3], boost::call_traits::reference); - BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits::const_reference); - BOOST_CHECK_TYPE(const int*const, boost::call_traits::param_type); - BOOST_CHECK_TYPE(const int*, boost::call_traits::value_type); - BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits::reference); - BOOST_CHECK_TYPE(const int(&)[3], boost::call_traits::const_reference); - BOOST_CHECK_TYPE(const int*const, boost::call_traits::param_type); - // test with abstract base class: - BOOST_CHECK_TYPE(test_abc1, boost::call_traits::value_type); - BOOST_CHECK_TYPE(test_abc1&, boost::call_traits::reference); - BOOST_CHECK_TYPE(const test_abc1&, boost::call_traits::const_reference); - BOOST_CHECK_TYPE(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: - BOOST_CHECK_TYPE(incomplete_type, boost::call_traits::value_type); - BOOST_CHECK_TYPE(incomplete_type&, boost::call_traits::reference); - BOOST_CHECK_TYPE(const incomplete_type&, boost::call_traits::const_reference); - BOOST_CHECK_TYPE(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 - -#if defined(BOOST_MSVC) && _MSC_VER <= 1300 -unsigned int expected_failures = 12; -#elif defined(__SUNPRO_CC) -#if(__SUNPRO_CC <= 0x520) -unsigned int expected_failures = 18; -#elif(__SUNPRO_CC < 0x530) -unsigned int expected_failures = 17; -#else -unsigned int expected_failures = 6; -#endif -#elif defined(__BORLANDC__) -unsigned int expected_failures = 2; -#elif (defined(__GNUC__) && ((__GNUC__ < 3) || (__GNUC__ == 3) && (__GNUC_MINOR__ < 1))) -unsigned int expected_failures = 4; -#elif defined(__HP_aCC) -unsigned int expected_failures = 24; -#else -unsigned int expected_failures = 0; -#endif - diff --git a/checked_delete.html b/checked_delete.html deleted file mode 100644 index 20ffef0..0000000 --- a/checked_delete.html +++ /dev/null @@ -1,124 +0,0 @@ - - - - Boost: checked_delete.hpp documentation - - - - - - - - - - - -
- boost.png (6897 bytes) - -

checked_delete.hpp

-
 
-

- The header <boost/checked_delete.hpp> defines two - function templates, checked_delete and checked_array_delete, - and two class templates, checked_deleter and checked_array_deleter. -

-

The C++ Standard allows, in 5.3.5/5, pointers to incomplete class types to be - deleted with a delete-expression. When the class has a non-trivial - destructor, or a class-specific operator delete, the behavior is undefined. - Some compilers issue a warning when an incomplete type is deleted, but - unfortunately, not all do, and programmers sometimes ignore or disable - warnings.

-

A particularly troublesome case is when a smart pointer's destructor, such as - boost::scoped_ptr<T>::~scoped_ptr, is instantiated with an - incomplete type. This can often lead to silent, hard to track failures.

-

The supplied function and class templates can be used to prevent these problems, - as they require a complete type, and cause a compilation error otherwise.

-

Synopsis

-
-namespace boost
-{
-
-template<class T> void checked_delete(T * p);
-template<class T> void checked_array_delete(T * p);
-template<class T> struct checked_deleter;
-template<class T> struct checked_array_deleter;
-
-}
-
-

checked_delete

-

template<class T> void checked_delete(T * p);

-
-

- Requires: T must be a complete type. The expression delete p - must be well-formed. -

-

- Effects: delete p; -

-
-

checked_array_delete

-

template<class T> void checked_array_delete(T - * p);

-
-

- Requires: T must be a complete type. The expression delete [] p - must be well-formed. -

-

- Effects: delete [] p; -

-
-

checked_deleter

-
-template<class T> struct checked_deleter
-{
-    typedef void result_type;
-    typedef T * argument_type;
-    void operator()(T * p) const;
-};
-
-

void checked_deleter<T>::operator()(T * p) const;

-
-

- Requires: T must be a complete type. The expression delete p - must be well-formed. -

-

- Effects: delete p; -

-
-

checked_array_deleter

-
-template<class T> struct checked_array_deleter
-{
-    typedef void result_type;
-    typedef T * argument_type;
-    void operator()(T * p) const;
-};
-
-

void checked_array_deleter<T>::operator()(T * p) const;

-
-

- Requires: T must be a complete type. The expression delete [] p - must be well-formed. -

-

- Effects: delete [] p; -

-
-

Acknowledgements

-

- The function templates checked_delete and checked_array_delete - were originally part of <boost/utility.hpp>, and the - documentation acknowledged Beman Dawes, Dave Abrahams, Vladimir Prus, Rainer - Deyke, John Maddock, and others as contributors. -

-

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

- - diff --git a/checked_delete_test.cpp b/checked_delete_test.cpp deleted file mode 100644 index 41fdc9a..0000000 --- a/checked_delete_test.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Boost checked_delete test program ---------------------------------------// - -// Copyright Beman Dawes 2001. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/libs/utility for documentation. - -// Revision History -// 21 May 01 Initial version (Beman Dawes) - -#include // for checked_delete - -// This program demonstrates compiler errors when trying to delete an -// incomplete type. - -namespace -{ - class Incomplete; -} - -int main() -{ - Incomplete * p = 0; - boost::checked_delete(p); // should cause compile time error - boost::checked_array_delete(p); // should cause compile time error - return 0; -} // main diff --git a/compressed_pair.htm b/compressed_pair.htm deleted file mode 100644 index 4662fc5..0000000 --- a/compressed_pair.htm +++ /dev/null @@ -1,75 +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 if either member is a POD type, then that member is not - zero-initialized by the compressed_pair default constructor: it's up to you to - supply an initial value for these types if you want them to have a default - value.

-

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 7687f0a..0000000 --- a/compressed_pair_test.cpp +++ /dev/null @@ -1,395 +0,0 @@ -// boost::compressed_pair test program - -// (C) Copyright John Maddock 2000. -// Use, modification and distribution are subject to the Boost Software License, -// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt). - -// standalone test program for -// Revised 03 Oct 2000: -// Enabled tests for VC6. - -#include -#include -#include - -#include -#include - -using namespace boost; - -struct empty_UDT -{ - ~empty_UDT(){}; - empty_UDT& operator=(const empty_UDT&){ return *this; } - bool operator==(const empty_UDT&)const - { return true; } -}; -struct empty_POD_UDT -{ - empty_POD_UDT& operator=(const empty_POD_UDT&){ return *this; } - bool operator==(const empty_POD_UDT&)const - { return true; } -}; - -struct non_empty1 -{ - int i; - non_empty1() : i(1){} - non_empty1(int v) : i(v){} - friend bool operator==(const non_empty1& a, const non_empty1& b) - { return a.i == b.i; } -}; - -struct non_empty2 -{ - int i; - non_empty2() : i(3){} - non_empty2(int v) : i(v){} - friend bool operator==(const non_empty2& a, const non_empty2& b) - { return a.i == b.i; } -}; - -#ifdef __GNUC__ -using std::swap; -#endif - -template -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_CHECK(cp2.first() == p1); - BOOST_CHECK(cp2.second() == p2); - // second param construct: - boost::compressed_pair cp3(p2); - cp3.first() = p1; - BOOST_CHECK(cp3.second() == p2); - BOOST_CHECK(cp3.first() == p1); - // both param construct: - boost::compressed_pair cp4(p1, p2); - BOOST_CHECK(cp4.first() == p1); - BOOST_CHECK(cp4.second() == p2); - boost::compressed_pair cp5(p3, p4); - BOOST_CHECK(cp5.first() == p3); - BOOST_CHECK(cp5.second() == p4); - // check const members: - const boost::compressed_pair& cpr1 = cp4; - BOOST_CHECK(cpr1.first() == p1); - BOOST_CHECK(cpr1.second() == p2); - - // copy construct: - boost::compressed_pair cp6(cp4); - BOOST_CHECK(cp6.first() == p1); - BOOST_CHECK(cp6.second() == p2); - // assignment: - cp1 = cp4; - BOOST_CHECK(cp1.first() == p1); - BOOST_CHECK(cp1.second() == p2); - cp1 = cp5; - BOOST_CHECK(cp1.first() == p3); - BOOST_CHECK(cp1.second() == p4); - // swap: - cp4.swap(cp5); - BOOST_CHECK(cp4.first() == p3); - BOOST_CHECK(cp4.second() == p4); - BOOST_CHECK(cp5.first() == p1); - BOOST_CHECK(cp5.second() == p2); - swap(cp4,cp5); - BOOST_CHECK(cp4.first() == p1); - BOOST_CHECK(cp4.second() == p2); - BOOST_CHECK(cp5.first() == p3); - BOOST_CHECK(cp5.second() == p4); -} - -// -// tests for case where one or both -// parameters are reference types: -// -template -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_CHECK(cp4.first() == p1); - BOOST_CHECK(cp4.second() == p2); - boost::compressed_pair cp5(p3, p4); - BOOST_CHECK(cp5.first() == p3); - BOOST_CHECK(cp5.second() == p4); - // check const members: - const boost::compressed_pair& cpr1 = cp4; - BOOST_CHECK(cpr1.first() == p1); - BOOST_CHECK(cpr1.second() == p2); - - // copy construct: - boost::compressed_pair cp6(cp4); - BOOST_CHECK(cp6.first() == p1); - BOOST_CHECK(cp6.second() == p2); - // assignment: - // VC6 bug: - // When second() is an empty class, VC6 performs the - // assignment by doing a memcpy - even though the empty - // class is really a zero sized base class, the result - // is that the memory of first() gets trampled over. - // Similar arguments apply to the case that first() is - // an empty base class. - // Strangely the problem is dependent upon the compiler - // settings - some generate the problem others do not. - cp4.first() = p3; - cp4.second() = p4; - BOOST_CHECK(cp4.first() == p3); - BOOST_CHECK(cp4.second() == p4); -} -// -// supplimentary tests for case where first arg only is a reference type: -// -template -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_CHECK(cp2.first() == p1); - BOOST_CHECK(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_CHECK(cp3.second() == p2); - BOOST_CHECK(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_CHECK(cp3.second() == p2); - BOOST_CHECK(cp3.first()[0] == p1[0]); - // check const members: - const boost::compressed_pair& cpr1 = cp3; - BOOST_CHECK(cpr1.first()[0] == p1[0]); - BOOST_CHECK(cpr1.second() == p2); - - BOOST_CHECK(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_CHECK(cp2.first() == p1); - BOOST_CHECK(cp2.second()[0] == p2[0]); - // check const members: - const boost::compressed_pair& cpr1 = cp2; - BOOST_CHECK(cpr1.first() == p1); - BOOST_CHECK(cpr1.second()[0] == p2[0]); - - BOOST_CHECK(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_CHECK(cp1.first()[0] == p1[0]); - BOOST_CHECK(cp1.second()[0] == p2[0]); - // check const members: - const boost::compressed_pair& cpr1 = cp1; - BOOST_CHECK(cpr1.first()[0] == p1[0]); - BOOST_CHECK(cpr1.second()[0] == p2[0]); - - BOOST_CHECK(sizeof(T1) == sizeof(cp1.first())); - BOOST_CHECK(sizeof(T2) == sizeof(cp1.second())); -} - -int test_main(int, char *[]) -{ - // declare some variables to pass to the tester: - non_empty1 ne1(2); - non_empty1 ne2(3); - non_empty2 ne3(4); - non_empty2 ne4(5); - empty_POD_UDT e1; - empty_UDT e2; - - // T1 != T2, both non-empty - compressed_pair_tester::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/current_function.html b/current_function.html deleted file mode 100644 index 31633f8..0000000 --- a/current_function.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - Boost: current_function.hpp documentation - - - - - - - - - - - -
- boost.png (6897 bytes) - -

current_function.hpp

-
 
-

- The header <boost/current_function.hpp> defines a single - macro, BOOST_CURRENT_FUNCTION, similar to the - C99 predefined identifier __func__. -

-

BOOST_CURRENT_FUNCTION expands to a string literal containing - the (fully qualified, if possible) name of the enclosing function. If there is - no enclosing function, the behavior is undefined.

-

Some compilers do not provide a way to obtain the name of the current enclosing - function. On such compilers, the string literal has an unspecified value.

-

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

- - diff --git a/current_function_test.cpp b/current_function_test.cpp deleted file mode 100644 index 1343901..0000000 --- a/current_function_test.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include - -#if defined(BOOST_MSVC) -#pragma warning(disable: 4786) // identifier truncated in debug info -#pragma warning(disable: 4710) // function not inlined -#pragma warning(disable: 4711) // function selected for automatic inline expansion -#pragma warning(disable: 4514) // unreferenced inline removed -#endif - -// -// current_function_test.cpp - a test for boost/current_function.hpp -// -// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// - -#include -#include -#include - -void message(char const * file, long line, char const * func, char const * msg) -{ -#if !defined(BOOST_NO_STDC_NAMESPACE) - using std::printf; -#endif - - printf("%s(%ld): %s in function '%s'\n", file, line, msg, func); -} - -#define MESSAGE(msg) message(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION, msg) - -int main() -{ - MESSAGE("assertion failed"); - - return 0; -} diff --git a/enable_if.html b/enable_if.html deleted file mode 100644 index 2b6ac0a..0000000 --- a/enable_if.html +++ /dev/null @@ -1,388 +0,0 @@ - - -enable_if - - - - - - - - - - -
-
- - -

-enable_if

-
-
-Copyright 2003 Jaakko Järvi, Jeremiah Willcock, Andrew Lumsdaine.
-
- - -

1  Introduction

- - -The enable_if family of templates is a set of tools to allow a function template or a class template specialization -to include or exclude itself from a set of matching functions or specializations -based on properties of its template arguments. -For example, one can define function templates that -are only enabled for, and thus only match, an arbitrary set of types -defined by a traits class. The enable_if templates can also be -applied to enable class template specializations. Applications of -enable_if are discussed in length -in [1] and [2].
-
- - -

1.1  Synopsis

- - -
namespace boost {
-  template <class Cond, class T = void> struct enable_if;
-  template <class Cond, class T = void> struct disable_if;
-  template <class Cond, class T> struct lazy_enable_if;
-  template <class Cond, class T> struct lazy_disable_if;
-
-  template <bool B, class T = void> struct enable_if_c;
-  template <bool B, class T = void> struct disable_if_c;
-  template <bool B, class T> struct lazy_enable_if_c;
-  template <bool B, class T> struct lazy_disable_if_c;
-}
-
- - -

1.2  Background

- - -Sensible operation of template function overloading in C++ relies -on the SFINAE (substitution-failure-is-not-an-error) -principle [3]: if an invalid argument -or return type is formed during the instantiation of a function -template, the instantiation is removed from the overload resolution -set instead of causing a compilation error. The following example, -taken from [1], -demonstrates why this is important: -
int negate(int i) { return -i; }
-
-template <class F>
-typename F::result_type negate(const F& f) { return -f(); }
-
-
-Suppose the compiler encounters the call negate(1). The first -definition is obviously a better match, but the compiler must -nevertheless consider (and instantiate the prototypes) of both -definitions to find this out. Instantiating the latter definition with -F as int would result in: -
int::result_type negate(const int&);
-
-
-where the return type is invalid. If this was an error, adding an unrelated function template -(that was never called) could break otherwise valid code. -Due to the SFINAE principle the above example is not, however, erroneous. -The latter definition of negate is simply removed from the overload resolution set.
-
-The enable_if templates are tools for controlled creation of the SFINAE -conditions.
-
- - -

2  The enable_if templates

- - -The names of the enable_if templates have three parts: an optional lazy_ tag, -either enable_if or disable_if, and an optional _c tag. -All eight combinations of these parts are supported. -The meaning of the lazy_ tag is described in Section 3.3. -The second part of the name indicates whether a true condition argument should -enable or disable the current overload. -The third part of the name indicates whether the condition argument is a bool value -(_c suffix), or a type containing a static bool constant named value (no suffix). -The latter version interoperates with Boost.MPL.
-
-The definitions of enable_if_c and enable_if are as follows (we use enable_if templates -unqualified but they are in the boost namespace). -
template <bool B, class T = void>
-struct enable_if_c {
-  typedef T type;
-};
-
-template <class T>
-struct enable_if_c<false, T> {};
-
-template <class Cond, class T = void>
-struct enable_if : public enable_if_c<Cond::value, T> {};
-
-
-An instantiation of the enable_if_c template with the parameter -B as true contains a member type type, defined -to be T. If B is -false, no such member is defined. Thus -enable_if_c<B, T>::type is either a valid or an invalid type -expression, depending on the value of B. -When valid, enable_if_c<B, T>::type equals T. -The enable_if_c template can thus be used for controlling when functions are considered for -overload resolution and when they are not. -For example, the following function is defined for all arithmetic types (according to the -classification of the Boost type_traits library): -
template <class T>
-typename enable_if_c<boost::is_arithmetic<T>::value, T>::type 
-foo(T t) { return t; }
-
-
-The disable_if_c template is provided as well, and has the -same functionality as enable_if_c except for the negated condition. The following -function is enabled for all non-arithmetic types. -
template <class T>
-typename disable_if_c<boost::is_arithmetic<T>::value, T>::type 
-bar(T t) { return t; }
-
-
-For easier syntax in some cases and interoperation with Boost.MPL we provide versions of -the enable_if templates taking any type with a bool member constant named -value as the condition argument. -The MPL bool_, and_, or_, and not_ templates are likely to be -useful for creating such types. Also, the traits classes in the Boost.Type_traits library -follow this convention. -For example, the above example function foo can be alternatively written as: -
template <class T>
-typename enable_if<boost::is_arithmetic<T>, T>::type 
-foo(T t) { return t; }
-
-
- - -

3  Using enable_if

- - -The enable_if templates are defined in -boost/utility/enable_if.hpp, which is included by boost/utility.hpp.
-
-The enable_if template can be used either as the return type, or as an -extra argument. For example, the foo function in the previous section could also be written -as: -
template <class T>
-T foo(T t, typename enable_if<boost::is_arithmetic<T> >::type* dummy = 0); 
-
-
Hence, an extra parameter of type void* is added, but it is given -a default value to keep the parameter hidden from client code. -Note that the second template argument was not given to enable_if, as the default -void gives the desired behavior.
-
-Whether to write the enabler as an argument or within the return type is -largely a matter of taste, but for certain functions, only one -alternative is possible: -
  • -Operators have a fixed number of arguments, thus enable_if must be used in the return type. -
  • Constructors and destructors do not have a return type; an extra argument is the only option. -
  • There does not seem to be a way to specify an enabler for a conversion operator. Converting constructors, -however, can have enablers as extra default arguments. -
- - -

3.1  Enabling template class specializations

- - -Class template specializations can be enabled or disabled with enable_if. -One extra template parameter needs to be added for the enabler expressions. -This parameter has the default value void. -For example: -
template <class T, class Enable = void> 
-class A { ... };
-
-template <class T>
-class A<T, typename enable_if<is_integral<T> >::type> { ... };
-
-template <class T>
-class A<T, typename enable_if<is_float<T> >::type> { ... };
-
-
Instantiating A with any integral type matches the first specialization, -whereas any floating point type matches the second one. All other types -match the primary template. -The condition can be any compile-time boolean expression that depends on the -template arguments of the class. -Note that again, the second argument to enable_if is not needed; the default (void) -is the correct value.
-
- - -

3.2  Overlapping enabler conditions

- - -Once the compiler has examined the enabling conditions and included the -function into the overload resolution set, normal C++ overload resolution -rules are used to select the best matching function. -In particular, there is no ordering between enabling conditions. -Function templates with enabling conditions that are not mutually exclusive can -lead to ambiguities. For example: -
template <class T>
-typename enable_if<boost::is_integral<T>, void>::type 
-foo(T t) {}
-
-template <class T>
-typename enable_if<boost::is_arithmetic<T>, void>::type 
-foo(T t) {}
-
-
-All integral types are also arithmetic. Therefore, say, for the call foo(1), -both conditions are true and both functions are thus in the overload resolution set. -They are both equally good matches and thus ambiguous. -Of course, more than one enabling condition can be simultaneously true as long as -other arguments disambiguate the functions.
-
-The above discussion applies to using enable_if in class template -partial specializations as well.
-
- - -

3.3  Lazy enable_if

- - -In some cases it is necessary to avoid instantiating part of a -function signature unless an enabling condition is true. For example: -
template <class T, class U> class mult_traits;
-
-template <class T, class U>
-typename enable_if<is_multipliable<T, U>, typename mult_traits<T, U>::type>::type
-operator*(const T& t, const U& u) { ... }
-
-
Assume the class template mult_traits is a traits class defining -the resulting type of a multiplication operator. The is_multipliable traits -class specifies for which types to enable the operator. Whenever -is_multipliable<A, B>::value is true for some types A and B, -then mult_traits<A, B>::type is defined.
-
-Now, trying to invoke (some other overload) of operator* with, say, operand types C and D -for which is_multipliable<C, D>::value is false -and mult_traits<C, D>::type is not defined is an error on some compilers. -The SFINAE principle is not applied because -the invalid type occurs as an argument to another template. The lazy_enable_if -and lazy_disable_if templates (and their _c versions) can be used in such -situations: -
template<class T, class U>
-typename lazy_enable_if<is_multipliable<T, U>, mult_traits<T, U> >::type
-operator*(const T& t, const U& u) { ... }
-
-
The second argument of lazy_enable_if must be a class type -that defines a nested type named type whenever the first -parameter (the condition) is true.
-
- - -
Note
- -Referring to one member type or static constant in a traits class -causes all of the members (type and static constant) of that -specialization to be instantiated. Therefore, if your traits classes -can sometimes contain invalid types, you should use two distinct -templates for describing the conditions and the type mappings. In the -above example, is_multipliable<T, U>::value defines when -mult_traits<T, U>::type is valid.
-
- - -

3.4  Compiler workarounds

- - -Some compilers flag functions as ambiguous if the only distinguishing factor is a different -condition in an enabler (even though the functions could never be ambiguous). For example, -some compilers (e.g. GCC 3.2) diagnose the following two functions as ambiguous: -
template <class T>
-typename enable_if<boost::is_arithmetic<T>, T>::type 
-foo(T t);
-
-template <class T>
-typename disable_if<boost::is_arithmetic<T>, T>::type 
-foo(T t);
-
-
Two workarounds can be applied: -
  • -Use an extra dummy parameter which disambiguates the functions. Use a default value for -it to hide the parameter from the caller. For example: -
    template <int> struct dummy { dummy(int) {} };
    -
    -template <class T>
    -typename enable_if<boost::is_arithmetic<T>, T>::type 
    -foo(T t, dummy<0> = 0);
    -
    -template <class T>
    -typename disable_if<boost::is_arithmetic<T>, T>::type 
    -foo(T t, dummy<1> = 0);
    -

    -
    -
  • Define the functions in different namespaces and bring them into a common -namespace with using declarations: -
    namespace A {
    -  template <class T>
    -  typename enable_if<boost::is_arithmetic<T>, T>::type 
    -  foo(T t);
    -}
    -
    -namespace B {
    -  template <class T>
    -  typename disable_if<boost::is_arithmetic<T>, T>::type 
    -  foo(T t);
    -}
    -
    -using A::foo;
    -using B::foo;
    -
    -
    -Note that the second workaround above cannot be used for member -templates. On the other hand, operators do not accept extra arguments, -which makes the first workaround unusable. As the net effect, -neither of the workarounds are of assistance for templated operators that -need to be defined as member functions (assignment and -subscript operators). -
- - -

4  Acknowledgements

- -We are grateful to Howard Hinnant, Jason Shirk, Paul Mensonides, and Richard -Smith whose findings have influenced the library.
-
- - -

References

-
[1]
-Jaakko Järvi, Jeremiah Willcock, Howard Hinnant, and Andrew Lumsdaine. -Function overloading based on arbitrary properties of types. -C/C++ Users Journal, 21(6):25--32, June 2003.
-
-
[2]
-Jaakko Järvi, Jeremiah Willcock, and Andrew Lumsdaine. -Concept-controlled polymorphism. -In Frank Pfennig and Yannis Smaragdakis, editors, Generative - Programming and Component Engineering, volume 2830 of LNCS, pages - 228--244. Springer Verlag, September 2003.
-
-
[3]
-David Vandevoorde and Nicolai M. Josuttis. -C++ Templates: The Complete Guide. -Addison-Wesley, 2002.
- - - - - -
- -Contributed by:
-Jaakko Järvi, Jeremiah Willcock and Andrew Lumsdaine
-{jajarvi|jewillco|lums}@osl.iu.edu
-Indiana University
-Open Systems Lab - - - -
-
This document was translated from LATEX by -HEVEA. -
- - \ No newline at end of file diff --git a/enable_if/test/Jamfile b/enable_if/test/Jamfile deleted file mode 100644 index f2e5ee3..0000000 --- a/enable_if/test/Jamfile +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright David Abrahams 2003. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -# For more information, see http://www.boost.org/ - -subproject libs/utility/enable_if/test ; - -# bring in rules for testing -import testing ; - -# Make tests run by default. -DEPENDS all : test ; - -{ - local test_monitor = @boost/libs/test/build/boost_test_exec_monitor ; - - # look in BOOST_ROOT for sources first, just in this Jamfile - local SEARCH_SOURCE = $(BOOST_ROOT) $(SEARCH_SOURCE) ; - - test-suite utility/enable_if - : - [ run libs/utility/enable_if/test/constructors.cpp $(test_monitor) ] - [ run libs/utility/enable_if/test/dummy_arg_disambiguation.cpp $(test_monitor) ] - [ run libs/utility/enable_if/test/lazy.cpp $(test_monitor) ] - [ run libs/utility/enable_if/test/lazy_test.cpp $(test_monitor) ] - [ run libs/utility/enable_if/test/member_templates.cpp $(test_monitor) ] - [ run libs/utility/enable_if/test/namespace_disambiguation.cpp $(test_monitor) ] - [ run libs/utility/enable_if/test/no_disambiguation.cpp $(test_monitor) ] - [ run libs/utility/enable_if/test/partial_specializations.cpp $(test_monitor) ] - ; -} diff --git a/enable_if/test/Jamfile.v2 b/enable_if/test/Jamfile.v2 deleted file mode 100644 index 77a8798..0000000 --- a/enable_if/test/Jamfile.v2 +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright David Abrahams 2003. -# Distributed under the Boost Software License, Version 1.0. -# (See accompanying file LICENSE_1_0.txt or copy at -# http://www.boost.org/LICENSE_1_0.txt) - -# For more information, see http://www.boost.org/ - -project - : requirements /boost/test//boost_test_exec_monitor - ; - -test-suite utility/enable_if - : - [ run constructors.cpp ] - [ run dummy_arg_disambiguation.cpp ] - [ run lazy.cpp ] - [ run lazy_test.cpp ] - [ run member_templates.cpp ] - [ run namespace_disambiguation.cpp ] - [ run no_disambiguation.cpp ] - [ run partial_specializations.cpp ] - ; - diff --git a/enable_if/test/constructors.cpp b/enable_if/test/constructors.cpp deleted file mode 100644 index 557b2f0..0000000 --- a/enable_if/test/constructors.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// Boost enable_if library - -// Copyright 2003 © The Trustees of Indiana University. - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Authors: Jaakko Järvi (jajarvi at osl.iu.edu) -// Jeremiah Willcock (jewillco at osl.iu.edu) -// Andrew Lumsdaine (lums at osl.iu.edu) - -#include - -#include -#include - -using boost::enable_if; -using boost::disable_if; -using boost::is_arithmetic; - -struct container { - bool my_value; - - template - container(const T&, const typename enable_if, T>::type * = 0): - my_value(true) {} - - template - container(const T&, const typename disable_if, T>::type * = 0): - my_value(false) {} -}; - -// example from Howard Hinnant (tests enable_if template members of a templated class) -template -struct xstring -{ - template - xstring(It begin, It end, typename - disable_if >::type* = 0) - : data(end-begin) {} - - int data; -}; - - -int test_main(int, char*[]) -{ - - BOOST_CHECK(container(1).my_value); - BOOST_CHECK(container(1.0).my_value); - - BOOST_CHECK(!container("1").my_value); - BOOST_CHECK(!container(static_cast(0)).my_value); - - char sa[] = "123456"; - BOOST_CHECK(xstring(sa, sa+6).data == 6); - - - return 0; -} - diff --git a/enable_if/test/dummy_arg_disambiguation.cpp b/enable_if/test/dummy_arg_disambiguation.cpp deleted file mode 100644 index bb9f733..0000000 --- a/enable_if/test/dummy_arg_disambiguation.cpp +++ /dev/null @@ -1,46 +0,0 @@ -// Boost enable_if library - -// Copyright 2003 © The Trustees of Indiana University. - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Authors: Jaakko Järvi (jajarvi at osl.iu.edu) -// Jeremiah Willcock (jewillco at osl.iu.edu) -// Andrew Lumsdaine (lums at osl.iu.edu) - -#include - -#include -#include - -using boost::enable_if; -using boost::disable_if; -using boost::is_arithmetic; - -template struct dummy { - dummy(int) {}; -}; - -template -typename enable_if, bool>::type -arithmetic_object(T t, dummy<0> = 0) { return true; } - -template -typename disable_if, bool>::type -arithmetic_object(T t, dummy<1> = 0) { return false; } - - -int test_main(int, char*[]) -{ - - BOOST_CHECK(arithmetic_object(1)); - BOOST_CHECK(arithmetic_object(1.0)); - - BOOST_CHECK(!arithmetic_object("1")); - BOOST_CHECK(!arithmetic_object(static_cast(0))); - - return 0; -} - diff --git a/enable_if/test/lazy.cpp b/enable_if/test/lazy.cpp deleted file mode 100644 index 6e7d650..0000000 --- a/enable_if/test/lazy.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// Boost enable_if library - -// Copyright 2003 © The Trustees of Indiana University. - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Authors: Jaakko Järvi (jajarvi at osl.iu.edu) -// Jeremiah Willcock (jewillco at osl.iu.edu) -// Andrew Lumsdaine (lums at osl.iu.edu) - -#include - -#include -#include - -using boost::enable_if_c; -using boost::lazy_enable_if_c; - -// This class provides a reduced example of a traits class for -// computing the result of multiplying two types. The member typedef -// 'type' in this traits class defines the return type of this -// operator. The return type member is invalid unless both arguments -// for mult_traits are values that mult_traits expects (ints in this -// case). This kind of situation may arise if a traits class only -// makes sense for some set of types, not all C++ types. - -template struct is_int { - BOOST_STATIC_CONSTANT(bool, value = (boost::is_same::value)); -}; - -template -struct mult_traits { - typedef typename T::does_not_exist type; -}; - -template <> -struct mult_traits { - typedef int type; -}; - - -// Next, a forwarding function mult() is defined. It is enabled only -// when both arguments are of type int. The first version, using -// non-lazy enable_if_c does not work. - -#if 0 -template -typename enable_if_c< - is_int::value && is_int::value, - typename mult_traits::type ->::type -mult(const T& x, const U& y) {return x * y;} -#endif - -// A correct version uses lazy_enable_if_c. -// This template removes compiler errors from invalid code used as an -// argument to enable_if_c. - -#if 1 -template -typename lazy_enable_if_c< - is_int::value && is_int::value, - mult_traits ->::type -mult(const T& x, const U& y) {return x * y;} -#endif - -double mult(int i, double d) { return (double)i * d; } - -int test_main(int, char*[]) -{ - - - BOOST_CHECK(mult(1, 2) == 2); - - BOOST_CHECK(mult(1, 3.0) == 3.0); - - return 0; -} - diff --git a/enable_if/test/lazy_test.cpp b/enable_if/test/lazy_test.cpp deleted file mode 100644 index d52d01e..0000000 --- a/enable_if/test/lazy_test.cpp +++ /dev/null @@ -1,100 +0,0 @@ -// Boost enable_if library - -// Copyright 2003 © The Trustees of Indiana University. - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Authors: Jaakko Järvi (jajarvi at osl.iu.edu) -// Jeremiah Willcock (jewillco at osl.iu.edu) -// Andrew Lumsdaine (lums at osl.iu.edu) - -// Testing all variations of lazy_enable_if. - -#include -#include - -#include -#include - -using boost::lazy_enable_if; -using boost::lazy_disable_if; - -using boost::lazy_enable_if_c; -using boost::lazy_disable_if_c; - - -template -struct is_int_or_double { - BOOST_STATIC_CONSTANT(bool, - value = (boost::is_same::value || - boost::is_same::value)); -}; - -template -struct some_traits { - typedef typename T::does_not_exist type; -}; - -template <> -struct some_traits { - typedef bool type; -}; - -template <> -struct some_traits { - typedef bool type; -}; - -template -struct make_bool { - typedef bool type; -}; - -template <> -struct make_bool {}; - -template <> -struct make_bool {}; - -namespace A { - - template - typename lazy_enable_if, some_traits >::type - foo(T t) { return true; } - - template - typename lazy_enable_if_c::value, some_traits >::type - foo2(T t) { return true; } -} - -namespace B { - template - typename lazy_disable_if, make_bool >::type - foo(T t) { return false; } - - template - typename lazy_disable_if_c::value, make_bool >::type - foo2(T t) { return false; } -} - -int test_main(int, char*[]) -{ - using namespace A; - using namespace B; - BOOST_CHECK(foo(1)); - BOOST_CHECK(foo(1.0)); - - BOOST_CHECK(!foo("1")); - BOOST_CHECK(!foo(static_cast(0))); - - BOOST_CHECK(foo2(1)); - BOOST_CHECK(foo2(1.0)); - - BOOST_CHECK(!foo2("1")); - BOOST_CHECK(!foo2(static_cast(0))); - - return 0; -} - diff --git a/enable_if/test/member_templates.cpp b/enable_if/test/member_templates.cpp deleted file mode 100644 index 23dd173..0000000 --- a/enable_if/test/member_templates.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Boost enable_if library - -// Copyright 2003 © The Trustees of Indiana University. - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Authors: Jaakko Järvi (jajarvi at osl.iu.edu) -// Jeremiah Willcock (jewillco at osl.iu.edu) -// Andrew Lumsdaine (lums at osl.iu.edu) - -#include - -#include -#include - -using boost::enable_if; -using boost::disable_if; -using boost::is_arithmetic; - -struct container { - template - typename enable_if, bool>::type - arithmetic_object(const T&, const int* /* disambiguate */ = 0) {return true;} - - template - typename disable_if, bool>::type - arithmetic_object(const T&) {return false;} -}; - -int test_main(int, char*[]) -{ - - BOOST_CHECK(container().arithmetic_object(1)); - BOOST_CHECK(container().arithmetic_object(1.0)); - - BOOST_CHECK(!container().arithmetic_object("1")); - BOOST_CHECK(!container().arithmetic_object(static_cast(0))); - - return 0; -} - diff --git a/enable_if/test/namespace_disambiguation.cpp b/enable_if/test/namespace_disambiguation.cpp deleted file mode 100644 index 90a98a1..0000000 --- a/enable_if/test/namespace_disambiguation.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Boost enable_if library - -// Copyright 2003 © The Trustees of Indiana University. - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Authors: Jaakko Järvi (jajarvi at osl.iu.edu) -// Jeremiah Willcock (jewillco at osl.iu.edu) -// Andrew Lumsdaine (lums at osl.iu.edu) - -#include -#include - -#include -#include - -using boost::enable_if; -using boost::mpl::not_; -using boost::is_arithmetic; - -namespace A { - template - typename enable_if, bool>::type - arithmetic_object(T t) { return true; } -} - -namespace B { - template - typename enable_if >, bool>::type - arithmetic_object(T t) { return false; } -} - -int test_main(int, char*[]) -{ - using namespace A; - using namespace B; - BOOST_CHECK(arithmetic_object(1)); - BOOST_CHECK(arithmetic_object(1.0)); - - BOOST_CHECK(!arithmetic_object("1")); - BOOST_CHECK(!arithmetic_object(static_cast(0))); - - return 0; -} - diff --git a/enable_if/test/no_disambiguation.cpp b/enable_if/test/no_disambiguation.cpp deleted file mode 100644 index f4936e8..0000000 --- a/enable_if/test/no_disambiguation.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Boost enable_if library - -// Copyright 2003 © The Trustees of Indiana University. - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Authors: Jaakko Järvi (jajarvi at osl.iu.edu) -// Jeremiah Willcock (jewillco at osl.iu.edu) -// Andrew Lumsdaine (lums at osl.iu.edu) - -#include -#include - -#include -#include - -using boost::mpl::not_; -using boost::enable_if; -using boost::is_arithmetic; - -template -typename enable_if, bool>::type -arithmetic_object(T t) { return true; } - -template -typename enable_if >, bool>::type -arithmetic_object(T t) { return false; } - - -int test_main(int, char*[]) -{ - - BOOST_CHECK(arithmetic_object(1)); - BOOST_CHECK(arithmetic_object(1.0)); - - BOOST_CHECK(!arithmetic_object("1")); - BOOST_CHECK(!arithmetic_object(static_cast(0))); - - return 0; -} - diff --git a/enable_if/test/partial_specializations.cpp b/enable_if/test/partial_specializations.cpp deleted file mode 100644 index 3dce799..0000000 --- a/enable_if/test/partial_specializations.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// Boost enable_if library - -// Copyright 2003 © The Trustees of Indiana University. - -// Use, modification, and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Authors: Jaakko Järvi (jajarvi at osl.iu.edu) -// Jeremiah Willcock (jewillco at osl.iu.edu) -// Andrew Lumsdaine (lums at osl.iu.edu) - -#include - -#include -#include - -using boost::enable_if_c; -using boost::disable_if_c; -using boost::enable_if; -using boost::disable_if; -using boost::is_arithmetic; - -template -struct tester; - -template -struct tester::value>::type> { - BOOST_STATIC_CONSTANT(bool, value = true); -}; - -template -struct tester::value>::type> { - BOOST_STATIC_CONSTANT(bool, value = false); -}; - -template -struct tester2; - -template -struct tester2 >::type> { - BOOST_STATIC_CONSTANT(bool, value = true); -}; - -template -struct tester2 >::type> { - BOOST_STATIC_CONSTANT(bool, value = false); -}; - -int test_main(int, char*[]) -{ - - BOOST_CHECK(tester::value); - BOOST_CHECK(tester::value); - - BOOST_CHECK(!tester::value); - BOOST_CHECK(!tester::value); - - BOOST_CHECK(tester2::value); - BOOST_CHECK(tester2::value); - - BOOST_CHECK(!tester2::value); - BOOST_CHECK(!tester2::value); - - return 0; -} - diff --git a/generator_iterator.htm b/generator_iterator.htm deleted file mode 100644 index fd3e3fc..0000000 --- a/generator_iterator.htm +++ /dev/null @@ -1,150 +0,0 @@ - - - - -Generator Iterator Adaptor Documentation - - - - -boost.png (6897 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 unspecified 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_generator_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/in_place_factories.html b/in_place_factories.html deleted file mode 100644 index 9b71559..0000000 --- a/in_place_factories.html +++ /dev/null @@ -1,297 +0,0 @@ - - - - - - - -Header - - - -

- -
-
-
-
-
-
-

Header <boost/utility/in_place_factory.hpp>

- -

Header <boost/utility/typed_in_place_factory.hpp>

- -
-
-
-
-
-
-

 

- -

Contents

-
-
Motivation
-
Framework
-
Specification
-
Container-side Usage
-
User-side Usage
-
- -
- -

Motivation

- -

Suppose we have a class

-
struct X
-{
-  X ( int, std:::string ) ;
-} ;
-

And a container for it which supports an empty state (that is, which can contain zero objects):

-
struct C
-{
-   C() : contained_(0) {}
-  ~C() { delete contained_ ; }
-  X* contained_ ;
-} ;
-

A container designed to support an empty state typically doesn't require the contained type to be DefaultConstructible, -but it typically requires it to be CopyConstructible as a mechanism to -initialize the object to store:

-
struct C
-{
-   C() : contained_(0) {}
-   C ( X const& v ) : contained_ ( new X(v) ) {}
-  ~C() { delete contained_ ; }
-  X* contained_ ;
-} ;
-

There is a subtle problem with this: since the mechanism used to initialize the stored object is copy construction, -there must exist a previously constructed source object to copy from. This -object is likely to be temporary and serve no purpose besides being the source

-
void foo()
-{
-  // Temporary object created.
-  C c( X(123,"hello") ) ;
-}
-
-

A solution to this problem is to support direct construction of the contained -object right in the container's storage.
-In this shceme, the user supplies the arguments for the X constructor -directly to the container:

-
struct C
-{
-   C() : contained_(0) {}
-   C ( X const& v ) : contained_ ( new X(v) ) {}
-   C ( int a0, std::string a1 ) : contained_ ( new X(a0,a1) ) {}
-  ~C() { delete contained_ ; }
-  X* contained_ ;
-} ;
-
void foo()
-{
-  // Wrapped object constructed in-place
-  // No temporary created.
-  C c(123,"hello") ;
-}
-
-

Clearly, this solution doesn't scale well since the container must duplicate all the constructor overloads from the contained type -(at least all those which are to be supported directly in the container).

- -

Framework

-

-This library proposes a framework to allow some containers to directly contruct contained objects in-place without requiring -the entire set of constructor overloads ftom the contained type. It also allows the container to remove the CopyConstuctible -requirement from the contained type since objects can be directly constructed in-place without need of a copy.
-The only requirement on the container is that it must provide proper storage (that is, correctly aligned and sized). -Naturally, the container will typically support uninitialized storage to avoid the in-place construction to override -a fully-constructed object (as this would defeat the purpose of in-place construction) -

-

For this purpose, the framework provides two families of classes collectively called: InPlaceFactories and TypedInPlaceFactories.
-Essentially, these classes hold a sequence of actual parameters and a method to contruct an object in place using these parameters. -Each member of the family differs only in the number (and type) of the parameter list. The first family -takes the type of the object to construct directly in method provided for that -purpose, whereas the second family incorporates that type in the factory class -itself..

-

From the container POV, using the framework amounts to calling the factory's method to contruct the object in place. -From the user POV, it amounts to creating the right factory object to hold the parameters and pass it to the container.
-The following simplified example shows the basic idea. A complete example follows the formal specification of the framework:

-
struct C
-{
-   template<class InPlaceFactory>
-   C ( InPlaceFactory const& aFactoty )
-    :
-    contained_ ( uninitialized_storage() )
-   {
-     aFactory.template apply<X>(contained_);
-   }
-
-  ~C() 
-  { 
-    contained_ -> X::~X();
-    delete[] contained_ ; 
-  }
-
-  char* uninitialized_storage() { return new char[sizeof(X)] ; }
-
-  char* contained_ ;
-} ;
-
-void foo()
-{
-  C c( in_place(123,"hello" ) ;
-}
-
- -
- -

Specification

- -

The following is the first member of the family of 'in_place_factory' classes, along with its corresponding helper template function. -The rest of the family varies only in the number and type of template (and constructor) parameters.

-
namespace boost {
-
-struct in_place_factory_base {} ;
-
-template<class A0>
-class in_place_factory : public in_place_factory_base
-{
-  public:
- -
    in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
-
-    template< class T >
-    void apply ( void* address ) const
-    {
-      new (address) T(m_a0);
-    }
-
-  private:
- -
    A0 const& m_a0 ;
-} ;
-
-template<class A0>
-in_place_factory<A0> in_place ( A0 const& a0 )
-{
-  return in_place_factory<A0>(a0);
-}
-
- -

Similarly, the following is the first member of the family of 'typed_in_place_factory' classes, along with its corresponding -helper template function. The rest of the family varies only in the number and type of template (and constructor) parameters.

-
namespace boost {
-
-struct typed_in_place_factory_base {} ;
-
-template<class T, class A0>
-class typed_in_place_factory : public typed_in_place_factory_base
-{
-  public:
- -
    typed_in_place_factory ( A0 const& a0 ) : m_a0(a0) {}
-
-    void apply ( void* address ) const
-    {
-      new (address) T(m_a0);
-    }
-
-  private:
- -
    A0 const& m_a0 ;
-} ;
-
-template<class T, class A0>
-typed_in_place_factory<A0> in_place ( A0 const& a0 )
-{
-  return typed_in_place_factory<T,A0>(a0);
-}
- -
}
-
- -

As you can see, the 'in_place_factory' and 'typed_in_place_factory' template classes varies only in the way they specify -the target type: in the first family, the type is given as a template argument to the apply member function while in the -second it is given directly as part of the factory class.
-When the container holds a unique non-polymorphic type (such as the case of Boost.Optional), it knows the exact dynamic-type -of the contained object and can pass it to the apply() method of a (non-typed) factory. -In this case, end users can use an 'in_place_factory' instance which can be constructed without the type of the object to construct.
-However, if the container holds heterogeneous or polymorphic objects (such as the case of Boost.Variant), the dynamic-type -of the object to be constructed must be known by the factory itslef. In this case, end users must use a 'typed_in_place_factory' -instead.

- -
- -

Container-side Usage

- -

As shown in the introductory simplified example, the container class must -contain methods that accept an instance of -these factories and pass the object's storage to the factory's apply method.
-However, the type of the factory class cannot be completly specified in the container class because that would -defeat the whole purpose of the factories which is to allow the container to accept a variadic argument list -for the constructor of its contained object.
-The correct function overload must be based on the only distinctive and common -characteristic of all the classes in each family, the base class.
-Depending on the container class, you can use 'enable_if' to generate the right overload, or use the following -dispatch technique (used in the Boost.Optional class): -

-
struct C
-{
-   C() : contained_(0) {}
-   C ( X const& v ) : contained_ ( new X(v) ) {}
-
-   template<class Expr>
-   C ( Expr const& expr )
-    :
-    contained_ ( uninitialized_storage() )
-   {
-    construct(expr,&expr)
-   }
-
-  ~C() { delete contained_ ; }
-
-  template<class InPlaceFactory>
-  void construct ( InPlaceFactory const& aFactory, boost::in_place_factory_base* )
-  {
-    aFactory.template apply<X>(contained_);
-  }
-
-  template<class TypedInPlaceFactory>
-  void construct ( TypedInPlaceFactory const& aFactory, boost::typed_in_place_factory_base* )
-  {
-    aFactory.apply(contained_);
-  }
-
-  X* uninitialized_storage() { return static_cast<X*>(new char[sizeof(X)]) ; }
-
-  X* contained_ ;
-} ;
-
- -
- -

User-side Usage

- -

End users pass to the container an instance of a factory object holding the actual parameters needed to construct the -contained object directly within the container. For this, the helper template function 'in_place' is used.
-The call 'in_place(a0,a1,a2,...,an)' constructs a (non-typed) 'in_place_factory' instance with the given argument list.
-The call 'in_place<T>(a0,a1,a2,...,an)' constructs a 'typed_in_place_factory' instance with the given argument list for the -type 'T'.

-
void foo()
-{
-  C a( in_place(123,"hello") ) ;    // in_place_factory passed
-  C b( in_place<X>(456,"world") ) ; // typed_in_place_factory passed
-}
-
- -

Revised September 17, 2004

-

© Copyright Fernando Luis Cacciola Carballal, 2004

-

Use, modification, and distribution are subject to the Boost Software -License, Version 1.0. (See accompanying file -LICENSE_1_0.txt or copy at -www.boost.org/LICENSE_1_0.txt)

-

Developed by Fernando Cacciola, -the latest version of this file can be found at www.boost.org, and the boost -discussion lists

- - \ No newline at end of file diff --git a/index.html b/index.html deleted file mode 100644 index 677539c..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:

-
-

- assert
- base_from_member
- call_traits
- checked_delete
- compressed_pair
- enable_if
- iterator_adaptors
- operators
- throw_exception
- utility
- value_init

-
-
-

Revised - 01 September, 2003

-

 

- - diff --git a/iterator_adaptors.htm b/iterator_adaptors.htm deleted file mode 100644 index 7232ac2..0000000 --- a/iterator_adaptors.htm +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - -This documentation moved to ../iterator/doc/index.html. - - diff --git a/iterators_test.cpp b/iterators_test.cpp deleted file mode 100644 index 7ac1191..0000000 --- a/iterators_test.cpp +++ /dev/null @@ -1,324 +0,0 @@ -// Demonstrate and test boost/operators.hpp on std::iterators --------------// - -// (C) Copyright Jeremy Siek 1999. -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 29 May 01 Factored implementation, added comparison tests, use Test Tools -// library (Daryle Walker) -// 12 Dec 99 Initial version with iterator operators (Jeremy Siek) - -#define BOOST_INCLUDE_MAIN -#include // 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::stringstream - -# 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 ); - - typedef std::string fruit_array_type[ fruit_length ]; - - static fruit_array_type fruit; - -}; // test_opr_base - -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -// A definition is required even for integral static constants -const std::size_t test_opr_base::fruit_length; -#endif - -template -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" }; - -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::stringstream oss; - for ( iter_type i = fruit_begin ; i != fruit_end ; ) - { - oss << *i++ << ' '; - } - - BOOST_CHECK( oss.str() == "apple orange pear peach grape plum "); -} - -// Test post-decrement -template -void -test_opr::post_decrement_test -( -) -{ - std::cout << "\tDoing post-decrement test." << std::endl; - - std::stringstream oss; - for ( iter_type i = fruit_end ; i != fruit_begin ; ) - { - i--; - oss << *i << ' '; - } - - BOOST_CHECK( oss.str() == "plum grape peach pear orange apple "); -} - -// Test indirect structure referral -template -void -test_opr::indirect_referral_test -( -) -{ - std::cout << "\tDoing indirect reference test." << std::endl; - - std::stringstream oss; - for ( iter_type i = fruit_begin ; i != fruit_end ; ++i ) - { - oss << i->size() << ' '; - } - - BOOST_CHECK( oss.str() == "5 6 4 5 5 4 "); -} - -// Test offset addition -template -void -test_opr::offset_addition_test -( -) -{ - std::cout << "\tDoing offset addition test." << std::endl; - - std::ptrdiff_t const two = 2; - std::stringstream oss; - for ( iter_type i = fruit_begin ; i != fruit_end ; i = i + two ) - { - oss << *i << ' '; - } - - BOOST_CHECK( oss.str() == "apple pear grape "); -} - -// Test offset addition, in reverse order -template -void -test_opr::reverse_offset_addition_test -( -) -{ - std::cout << "\tDoing reverse offset addition test." << std::endl; - - std::ptrdiff_t const two = 2; - std::stringstream oss; - for ( iter_type i = fruit_begin ; i != fruit_end ; i = two + i ) - { - oss << *i << ' '; - } - - BOOST_CHECK( oss.str() == "apple pear grape "); -} - -// Test offset subtraction -template -void -test_opr::offset_subtraction_test -( -) -{ - std::cout << "\tDoing offset subtraction test." << std::endl; - - std::ptrdiff_t const two = 2; - std::stringstream oss; - for ( iter_type i = fruit_end ; fruit_begin < i ; ) - { - i = i - two; - if ( (fruit_begin < i) || (fruit_begin == i) ) - { - oss << *i << ' '; - } - } - - BOOST_CHECK( oss.str() == "grape pear apple "); -} - -// Test comparisons -template -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_CHECK( (i != j) == (i_offset != j_offset) ); - BOOST_CHECK( (i > j) == (i_offset > j_offset) ); - BOOST_CHECK( (i <= j) == (i_offset <= j_offset) ); - BOOST_CHECK( (i >= j) == (i_offset >= j_offset) ); - } - } - cout << std::endl; -} - -// Test indexing -template -void -test_opr::indexing_test -( -) -{ - std::cout << "\tDoing indexing test." << std::endl; - - std::stringstream oss; - for ( std::size_t k = 0u ; k < fruit_length ; ++k ) - { - oss << fruit_begin[ k ] << ' '; - } - - BOOST_CHECK( oss.str() == "apple orange pear peach grape plum "); -} diff --git a/noncopyable_test.cpp b/noncopyable_test.cpp deleted file mode 100644 index d5d2994..0000000 --- a/noncopyable_test.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// boost class noncopyable test program ------------------------------------// - -// (C) Copyright Beman Dawes 1999. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 9 Jun 99 Add unnamed namespace -// 2 Jun 99 Initial Version - -#include -#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 9a32a3a..0000000 --- a/numeric_traits_test.cpp +++ /dev/null @@ -1,386 +0,0 @@ -// (C) Copyright David Abrahams 2001. -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 1 Apr 2001 Fixes for ICL; use BOOST_STATIC_CONSTANT -// 11 Feb 2001 Fixes for Borland (David Abrahams) -// 23 Jan 2001 Added test for wchar_t (David Abrahams) -// 23 Jan 2001 Now statically selecting a test for signed numbers to avoid -// warnings with fancy compilers. Added commentary and -// additional dumping of traits data for tested types (David -// Abrahams). -// 21 Jan 2001 Initial version (David Abrahams) - -#include -#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 necessary 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*) -{ - 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*) -{ - 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*) -{ - 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*) -{ - 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(), 0); -} - - -// 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< -#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 - 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(), 0); - 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< ::boost::long_long_type>(); - test< ::boost::ulong_long_type>(); -#elif defined(BOOST_MSVC) - // The problem of not having compile-time static class constants other than - // enums prevents this from working, since values get truncated. - // test(); - // test(); -#endif - return 0; -} diff --git a/operators.htm b/operators.htm deleted file mode 100644 index fca90e5..0000000 --- a/operators.htm +++ /dev/null @@ -1,2133 +0,0 @@ - - - - - - - - Header <boost/operators.hpp> Documentation - - - -

boost.png (6897 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:

- - - -

As Daniel Krügler pointed out, this technique violates 14.6.5/2 - and is thus non-portable. The reasoning is, that the operators injected - by the instantiation of e.g. - less_than_comparable<myclass> can not be found - by ADL according to the rules given by 3.4.2/2, since myclass is - not an associated class of - less_than_comparable<myclass>. - Thus only use this technique if all else fails.

- -

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>
bool operator==(const U&, const T&)
- bool operator!=(const U&, const T&)
- bool operator!=(const T&, const U&)
t == u.
- Return convertible to bool.
addable<T>
- addable1<T>
T operator+(const T&, const T&)T temp(t); temp += t1.
- Return convertible to T. See the Symmetry Note.
addable<T, U>
- addable2<T, U>
T operator+(const T&, const U&)
- T operator+(const U&, const T& )
T temp(t); temp += u.
- Return convertible to T. See the Symmetry Note.
subtractable<T>
- subtractable1<T>
T operator-(const T&, const T&)T temp(t); temp -= t1.
- Return convertible to T. See the Symmetry Note.
subtractable<T, - U>
- subtractable2<T, U>
T operator-(const T&, const U&)T temp(t); temp -= u.
- Return convertible to T. See the Symmetry Note.
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*(const T&, const T&)T temp(t); temp *= t1.
- Return convertible to T. See the Symmetry Note.
multipliable<T, - U>
- multipliable2<T, U>
T operator*(const T&, const U&)
- T operator*(const U&, const T&)
T temp(t); temp *= u.
- Return convertible to T. See the Symmetry Note.
dividable<T>
- dividable1<T>
T operator/(const T&, const T&)T temp(t); temp /= t1.
- Return convertible to T. See the Symmetry Note.
dividable<T, U>
- dividable2<T, U>
T operator/(const T&, const U&)T temp(t); temp /= u.
- Return convertible to T. See the Symmetry Note.
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%(const T&, const T&)T temp(t); temp %= t1.
- Return convertible to T. See the Symmetry Note.
modable<T, U>
- modable2<T, U>
T operator%(const T&, const U&)T temp(t); temp %= u.
- Return convertible to T. See the Symmetry Note.
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|(const T&, const T&)T temp(t); temp |= t1.
- Return convertible to T. See the Symmetry Note.
orable<T, U>
- orable2<T, U>
T operator|(const T&, const U&)
- T operator|(const U&, const T&)
T temp(t); temp |= u.
- Return convertible to T. See the Symmetry Note.
andable<T>
- andable1<T>
T operator&(const T&, const T&)T temp(t); temp &= t1.
- Return convertible to T. See the Symmetry Note.
andable<T, U>
- andable2<T, U>
T operator&(const T&, const U&)
- T operator&(const U&, const T&)
T temp(t); temp &= u.
- Return convertible to T. See the Symmetry Note.
xorable<T>
- xorable1<T>
T operator^(const T&, const T&)T temp(t); temp ^= t1.
- Return convertible to T. See the Symmetry Note.
xorable<T, U>
- xorable2<T, U>
T operator^(const T&, const U&)
- T operator^(const U&, const T&)
T temp(t); temp ^= u.
- Return convertible to T. See the Symmetry Note.
incrementable<T>T operator++(T&, int)T temp(t); ++t
- Return convertible to T.
decrementable<T>T operator--(T&, int)T temp(t); --t;
- Return convertible to T.
left_shiftable<T>
- left_shiftable1<T>
T operator<<(const T&, const T&)T temp(t); temp <<= t1.
- Return convertible to T. See the Symmetry Note.
left_shiftable<T, - U>
- left_shiftable2<T, U>
T operator<<(const T&, const U&)T temp(t); temp <<= u.
- Return convertible to T. See the Symmetry Note.
right_shiftable<T>
- right_shiftable1<T>
T operator>>(const T&, const T&)T temp(t); temp >>= t1.
- Return convertible to T. See the Symmetry Note.
right_shiftable<T, - U>
- right_shiftable2<T, U>
T operator>>(const T&, const U&)T temp(t); temp >>= u.
- Return convertible to T. See the Symmetry Note.
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.

- -

Symmetry Note

- -

Before talking about symmetry, we need to talk about optimizations to - understand the reasons for the different implementation styles of - operators. Let's have a look at operator+ for a class - T as an example:

-
-T operator+( const T& lhs, const T& rhs )
-{
-   return T( lhs ) += rhs;
-}
-
- This would be a normal implementation of operator+, but it - is not an efficient one. An unnamed local copy of lhs is - created, operator+= is called on it and it is copied to the - function return value (which is another unnamed object of type - T). The standard doesn't generally allow the intermediate - object to be optimized away: - -
- 3.7.2/2: Automatic storage duration
-
- If a named automatic object has initialization or a destructor with - side effects, it shall not be destroyed before the end of its block, - nor shall it be eliminated as an optimization even if it appears to be - unused, except that a class object or its copy may be eliminated as - specified in 12.8. -
- The reference to 12.8 is important for us: - -
- 12.8/15: Copying class objects
- ...
- For a function with a class return type, if the expression in the - return statement is the name of a local object, and the cv-unqualified - type of the local object is the same as the function return type, an - implementation is permitted to omit creating the temporary object to - hold the function return value, even if the class copy constructor or - destructor has side effects. -
- This optimization is known as the named return value optimization (NRVO), - which leads us to the following implementation for - operator+: -
-T operator+( const T& lhs, const T& rhs )
-{
-   T nrv( lhs );
-   nrv += rhs;
-   return nrv;
-}
-
- Given this implementation, the compiler is allowed to remove the - intermediate object. Sadly, not all compiler implement the NRVO, some - even implement it in an incorrect way which makes it useless here. - Without the NRVO, the NRVO-friendly code is no worse than the original - code showed above, but there is another possible implementation, which - has some very special properties: -
-T operator+( T lhs, const T& rhs )
-{
-   return lhs += rhs;
-}
-
- The difference to the first implementation is that lhs is - not taken as a constant reference used to create a copy; instead, - lhs is a by-value parameter, thus it is already the copy - needed. This allows another optimization (12.2/2) for some cases. - Consider a + b + c where the result of - a + b is not copied when used as lhs - when adding c. This is more efficient than the original - code, but not as efficient as a compiler using the NRVO. For most people, - it is still preferable for compilers that don't implement the NRVO, but - the operator+ now has a different function signature. Also, - the number of objects created differs for - (a + b ) + c and - a + ( b + c ). Most probably, - this won't be a problem for you, but if your code relies on the function - signature or a strict symmetric behaviour, you should set - BOOST_FORCE_SYMMETRIC_OPERATORS in your user-config. This - will force the NRVO-friendly implementation to be used even for compilers - that don't implement the NRVO.
-
- -

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.
- -
Daniel Frey
- -
Contributed the NRVO-friendly and symmetric implementation of - arithmetic operators.
- -
- -

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: 29 Oct 2004

- -

Copyright © Beman Dawes, David Abrahams, 1999-2001.

-

Copyright © Daniel Frey, 2002-2004.

-

Use, modification, and distribution is subject to the Boost Software - License, Version 1.0. (See accompanying file - LICENSE_1_0.txt or copy at - - www.boost.org/LICENSE_1_0.txt)

- - - diff --git a/operators_test.cpp b/operators_test.cpp deleted file mode 100644 index d42cb6a..0000000 --- a/operators_test.cpp +++ /dev/null @@ -1,897 +0,0 @@ -// Demonstrate and test boost/operators.hpp -------------------------------// - -// Copyright Beman Dawes 1999. Distributed under the Boost -// Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// See http://www.boost.org/libs/utility for documentation. - -// Revision History -// 01 Oct 01 Added tests for "left" operators -// and new grouped operators. (Helmut Zeisel) -// 20 May 01 Output progress messages. Added tests for new operator -// templates. Updated random number generator. Changed tests to -// use Boost Test Tools library. (Daryle Walker) -// 04 Jun 00 Added regression test for a bug I found (David Abrahams) -// 17 Jun 00 Fix for broken compilers (Aleksey Gurtovoy) -// ?? ??? 00 Major update to randomly test all one- and two- argument forms by -// wrapping integral types and comparing the results of operations -// to the results for the raw types (David Abrahams) -// 12 Dec 99 Minor update, output confirmation message. -// 15 Nov 99 Initial version - -#define BOOST_INCLUDE_MAIN - -#include // 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_CHECK( true_value(y1) == true_value(y2) ); - BOOST_CHECK( true_value(x1) == true_value(x2) ); - } - - template - void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - BOOST_CHECK( (x1 < y1) == (x2 < y2) ); - BOOST_CHECK( (x1 <= y1) == (x2 <= y2) ); - BOOST_CHECK( (x1 >= y1) == (x2 >= y2) ); - BOOST_CHECK( (x1 > y1) == (x2 > y2) ); - } - - template - 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_CHECK( (x1 == y1) == (x2 == y2) ); - BOOST_CHECK( (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_CHECK( (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_value_equality(A a, B b) - { - BOOST_CHECK(a.value() == b); - } - -#define TEST_OP_R(op) test_value_equality(x1 op y1, x2 op y2) -#define TEST_OP_L(op) test_value_equality(y1 op x1, y2 op x2) - - template - void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - TEST_OP_R(+); - } - - 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 ); - TEST_OP_R(-); - } - - template - void test_subtractable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - TEST_OP_L(-); - } - - template - void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - if ( y2 != 0 ) - TEST_OP_R(/); - } - - template - void test_dividable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - if ( x2 != 0 ) - TEST_OP_L(/); - } - - template - void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - if ( y2 != 0 ) - TEST_OP_R(%); - } - - template - void test_modable_left(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - if ( x2 != 0 ) - TEST_OP_L(%); - } - - template - void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - TEST_OP_R(^); - } - - 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) - { - TEST_OP_R(&); - } - - 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) - { - TEST_OP_R(|); - } - - 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 ); - TEST_OP_R(<<); - } - - template - void test_right_shiftable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check( x1, y1, x2, y2 ); - TEST_OP_R(>>); - } - - template - void test_incrementable(X1 x1, X2 x2) - { - sanity_check( x1, x1, x2, x2 ); - BOOST_CHECK( (x1++).value() == x2++ ); - BOOST_CHECK( x1.value() == x2 ); - } - - template - void test_decrementable(X1 x1, X2 x2) - { - sanity_check( x1, x1, x2, x2 ); - BOOST_CHECK( (x1--).value() == x2-- ); - BOOST_CHECK( 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 < 1300) -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_CHECK( ((e), (t)) ) - -int -test_main( int , char * [] ) -{ - using std::cout; - using std::endl; - - // Regression test. - Point x; - x = x + Point(3, 4); - x = x - Point(3, 4); - - cout << "Created point, and operated on it." << endl; - - for (int n = 0; n < 1000; ++n) // was 10,000 but took too long (Beman) - { - boost::minstd_rand r; - tester()(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_CHECK( i1.value() == 1 ); - BOOST_CHECK( i2.value() == 2 ); - BOOST_CHECK( i.value() == 0 ); - - cout << "Created MyInt objects.\n"; - - PRIVATE_EXPR_TEST( (i = i2), (i.value() == 2) ); - - BOOST_CHECK( i2 == i ); - BOOST_CHECK( i1 != i2 ); - BOOST_CHECK( i1 < i2 ); - BOOST_CHECK( i1 <= i2 ); - BOOST_CHECK( i <= i2 ); - BOOST_CHECK( i2 > i1 ); - BOOST_CHECK( i2 >= i1 ); - BOOST_CHECK( i2 >= i ); - - PRIVATE_EXPR_TEST( (i = i1 + i2), (i.value() == 3) ); - PRIVATE_EXPR_TEST( (i = i + i2), (i.value() == 5) ); - PRIVATE_EXPR_TEST( (i = i - i1), (i.value() == 4) ); - PRIVATE_EXPR_TEST( (i = i * i2), (i.value() == 8) ); - PRIVATE_EXPR_TEST( (i = i / i2), (i.value() == 4) ); - PRIVATE_EXPR_TEST( (i = i % ( i - i1 )), (i.value() == 1) ); - PRIVATE_EXPR_TEST( (i = i2 + i2), (i.value() == 4) ); - PRIVATE_EXPR_TEST( (i = i1 | i2 | i), (i.value() == 7) ); - PRIVATE_EXPR_TEST( (i = i & i2), (i.value() == 2) ); - PRIVATE_EXPR_TEST( (i = i + i1), (i.value() == 3) ); - PRIVATE_EXPR_TEST( (i = i ^ i1), (i.value() == 2) ); - PRIVATE_EXPR_TEST( (i = ( i + i1 ) * ( i2 | i1 )), (i.value() == 9) ); - - PRIVATE_EXPR_TEST( (i = i1 << i2), (i.value() == 4) ); - PRIVATE_EXPR_TEST( (i = i2 >> i1), (i.value() == 1) ); - - cout << "Performed tests on MyInt objects.\n"; - - MyLong j1(1); - MyLong j2(2); - MyLong j; - - BOOST_CHECK( j1.value() == 1 ); - BOOST_CHECK( j2.value() == 2 ); - BOOST_CHECK( j.value() == 0 ); - - cout << "Created MyLong objects.\n"; - - PRIVATE_EXPR_TEST( (j = j2), (j.value() == 2) ); - - BOOST_CHECK( j2 == j ); - BOOST_CHECK( 2 == j ); - BOOST_CHECK( j2 == 2 ); - BOOST_CHECK( j == j2 ); - BOOST_CHECK( j1 != j2 ); - BOOST_CHECK( j1 != 2 ); - BOOST_CHECK( 1 != j2 ); - BOOST_CHECK( j1 < j2 ); - BOOST_CHECK( 1 < j2 ); - BOOST_CHECK( j1 < 2 ); - BOOST_CHECK( j1 <= j2 ); - BOOST_CHECK( 1 <= j2 ); - BOOST_CHECK( j1 <= j ); - BOOST_CHECK( j <= j2 ); - BOOST_CHECK( 2 <= j2 ); - BOOST_CHECK( j <= 2 ); - BOOST_CHECK( j2 > j1 ); - BOOST_CHECK( 2 > j1 ); - BOOST_CHECK( j2 > 1 ); - BOOST_CHECK( j2 >= j1 ); - BOOST_CHECK( 2 >= j1 ); - BOOST_CHECK( j2 >= 1 ); - BOOST_CHECK( j2 >= j ); - BOOST_CHECK( 2 >= j ); - BOOST_CHECK( j2 >= 2 ); - - BOOST_CHECK( (j1 + 2) == 3 ); - BOOST_CHECK( (1 + j2) == 3 ); - PRIVATE_EXPR_TEST( (j = j1 + j2), (j.value() == 3) ); - - BOOST_CHECK( (j + 2) == 5 ); - BOOST_CHECK( (3 + j2) == 5 ); - PRIVATE_EXPR_TEST( (j = j + j2), (j.value() == 5) ); - - BOOST_CHECK( (j - 1) == 4 ); - PRIVATE_EXPR_TEST( (j = j - j1), (j.value() == 4) ); - - BOOST_CHECK( (j * 2) == 8 ); - BOOST_CHECK( (4 * j2) == 8 ); - PRIVATE_EXPR_TEST( (j = j * j2), (j.value() == 8) ); - - BOOST_CHECK( (j / 2) == 4 ); - PRIVATE_EXPR_TEST( (j = j / j2), (j.value() == 4) ); - - BOOST_CHECK( (j % 3) == 1 ); - PRIVATE_EXPR_TEST( (j = j % ( j - j1 )), (j.value() == 1) ); - - PRIVATE_EXPR_TEST( (j = j2 + j2), (j.value() == 4) ); - - BOOST_CHECK( (1 | j2 | j) == 7 ); - BOOST_CHECK( (j1 | 2 | j) == 7 ); - BOOST_CHECK( (j1 | j2 | 4) == 7 ); - PRIVATE_EXPR_TEST( (j = j1 | j2 | j), (j.value() == 7) ); - - BOOST_CHECK( (7 & j2) == 2 ); - BOOST_CHECK( (j & 2) == 2 ); - PRIVATE_EXPR_TEST( (j = j & j2), (j.value() == 2) ); - - PRIVATE_EXPR_TEST( (j = j | j1), (j.value() == 3) ); - - BOOST_CHECK( (3 ^ j1) == 2 ); - BOOST_CHECK( (j ^ 1) == 2 ); - PRIVATE_EXPR_TEST( (j = j ^ j1), (j.value() == 2) ); - - PRIVATE_EXPR_TEST( (j = ( j + j1 ) * ( j2 | j1 )), (j.value() == 9) ); - - BOOST_CHECK( (j1 << 2) == 4 ); - BOOST_CHECK( (j2 << 1) == 4 ); - PRIVATE_EXPR_TEST( (j = j1 << j2), (j.value() == 4) ); - - BOOST_CHECK( (j >> 2) == 1 ); - BOOST_CHECK( (j2 >> 1) == 1 ); - PRIVATE_EXPR_TEST( (j = j2 >> j1), (j.value() == 1) ); - - cout << "Performed tests on MyLong objects.\n"; - - MyChar k1(1); - MyChar k2(2); - MyChar k; - - BOOST_CHECK( k1.value() == 1 ); - BOOST_CHECK( k2.value() == 2 ); - BOOST_CHECK( k.value() == 0 ); - - cout << "Created MyChar objects.\n"; - - PRIVATE_EXPR_TEST( (k = k2), (k.value() == 2) ); - - BOOST_CHECK( k2 == k ); - BOOST_CHECK( k1 != k2 ); - BOOST_CHECK( k1 < k2 ); - BOOST_CHECK( k1 <= k2 ); - BOOST_CHECK( k <= k2 ); - BOOST_CHECK( k2 > k1 ); - BOOST_CHECK( k2 >= k1 ); - BOOST_CHECK( k2 >= k ); - - cout << "Performed tests on MyChar objects.\n"; - - MyShort l1(1); - MyShort l2(2); - MyShort l; - - BOOST_CHECK( l1.value() == 1 ); - BOOST_CHECK( l2.value() == 2 ); - BOOST_CHECK( l.value() == 0 ); - - cout << "Created MyShort objects.\n"; - - PRIVATE_EXPR_TEST( (l = l2), (l.value() == 2) ); - - BOOST_CHECK( l2 == l ); - BOOST_CHECK( 2 == l ); - BOOST_CHECK( l2 == 2 ); - BOOST_CHECK( l == l2 ); - BOOST_CHECK( l1 != l2 ); - BOOST_CHECK( l1 != 2 ); - BOOST_CHECK( 1 != l2 ); - BOOST_CHECK( l1 < l2 ); - BOOST_CHECK( 1 < l2 ); - BOOST_CHECK( l1 < 2 ); - BOOST_CHECK( l1 <= l2 ); - BOOST_CHECK( 1 <= l2 ); - BOOST_CHECK( l1 <= l ); - BOOST_CHECK( l <= l2 ); - BOOST_CHECK( 2 <= l2 ); - BOOST_CHECK( l <= 2 ); - BOOST_CHECK( l2 > l1 ); - BOOST_CHECK( 2 > l1 ); - BOOST_CHECK( l2 > 1 ); - BOOST_CHECK( l2 >= l1 ); - BOOST_CHECK( 2 >= l1 ); - BOOST_CHECK( l2 >= 1 ); - BOOST_CHECK( l2 >= l ); - BOOST_CHECK( 2 >= l ); - BOOST_CHECK( l2 >= 2 ); - - cout << "Performed tests on MyShort objects.\n"; - - MyDoubleInt di1(1); - MyDoubleInt di2(2.); - MyDoubleInt half(0.5); - MyDoubleInt di; - MyDoubleInt tmp; - - BOOST_CHECK( di1.value() == 1 ); - BOOST_CHECK( di2.value() == 2 ); - BOOST_CHECK( di2.value() == 2 ); - BOOST_CHECK( di.value() == 0 ); - - cout << "Created MyDoubleInt objects.\n"; - - PRIVATE_EXPR_TEST( (di = di2), (di.value() == 2) ); - - BOOST_CHECK( di2 == di ); - BOOST_CHECK( 2 == di ); - BOOST_CHECK( di == 2 ); - BOOST_CHECK( di1 < di2 ); - BOOST_CHECK( 1 < di2 ); - BOOST_CHECK( di1 <= di2 ); - BOOST_CHECK( 1 <= di2 ); - BOOST_CHECK( di2 > di1 ); - BOOST_CHECK( di2 > 1 ); - BOOST_CHECK( di2 >= di1 ); - BOOST_CHECK( di2 >= 1 ); - BOOST_CHECK( di1 / di2 == half ); - BOOST_CHECK( di1 / 2 == half ); - BOOST_CHECK( 1 / di2 == half ); - PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=2) == half) ); - PRIVATE_EXPR_TEST( (tmp=di1), ((tmp/=di2) == half) ); - BOOST_CHECK( di1 * di2 == di2 ); - BOOST_CHECK( di1 * 2 == di2 ); - BOOST_CHECK( 1 * di2 == di2 ); - PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=2) == di2) ); - PRIVATE_EXPR_TEST( (tmp=di1), ((tmp*=di2) == di2) ); - BOOST_CHECK( di2 - di1 == di1 ); - BOOST_CHECK( di2 - 1 == di1 ); - BOOST_CHECK( 2 - di1 == di1 ); - PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=1) == di1) ); - PRIVATE_EXPR_TEST( (tmp=di2), ((tmp-=di1) == di1) ); - BOOST_CHECK( di1 + di1 == di2 ); - BOOST_CHECK( di1 + 1 == di2 ); - BOOST_CHECK( 1 + di1 == di2 ); - PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=1) == di2) ); - PRIVATE_EXPR_TEST( (tmp=di1), ((tmp+=di1) == di2) ); - - cout << "Performed tests on MyDoubleInt objects.\n"; - - MyLongInt li1(1); - MyLongInt li2(2); - MyLongInt li; - MyLongInt tmp2; - - BOOST_CHECK( li1.value() == 1 ); - BOOST_CHECK( li2.value() == 2 ); - BOOST_CHECK( li.value() == 0 ); - - cout << "Created MyLongInt objects.\n"; - - PRIVATE_EXPR_TEST( (li = li2), (li.value() == 2) ); - - BOOST_CHECK( li2 == li ); - BOOST_CHECK( 2 == li ); - BOOST_CHECK( li == 2 ); - BOOST_CHECK( li1 < li2 ); - BOOST_CHECK( 1 < li2 ); - BOOST_CHECK( li1 <= li2 ); - BOOST_CHECK( 1 <= li2 ); - BOOST_CHECK( li2 > li1 ); - BOOST_CHECK( li2 > 1 ); - BOOST_CHECK( li2 >= li1 ); - BOOST_CHECK( li2 >= 1 ); - BOOST_CHECK( li1 % li2 == li1 ); - BOOST_CHECK( li1 % 2 == li1 ); - BOOST_CHECK( 1 % li2 == li1 ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=2) == li1) ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2%=li2) == li1) ); - BOOST_CHECK( li1 / li2 == 0 ); - BOOST_CHECK( li1 / 2 == 0 ); - BOOST_CHECK( 1 / li2 == 0 ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=2) == 0) ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2/=li2) == 0) ); - BOOST_CHECK( li1 * li2 == li2 ); - BOOST_CHECK( li1 * 2 == li2 ); - BOOST_CHECK( 1 * li2 == li2 ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=2) == li2) ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2*=li2) == li2) ); - BOOST_CHECK( li2 - li1 == li1 ); - BOOST_CHECK( li2 - 1 == li1 ); - BOOST_CHECK( 2 - li1 == li1 ); - PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=1) == li1) ); - PRIVATE_EXPR_TEST( (tmp2=li2), ((tmp2-=li1) == li1) ); - BOOST_CHECK( li1 + li1 == li2 ); - BOOST_CHECK( li1 + 1 == li2 ); - BOOST_CHECK( 1 + li1 == li2 ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=1) == li2) ); - PRIVATE_EXPR_TEST( (tmp2=li1), ((tmp2+=li1) == li2) ); - - cout << "Performed tests on MyLongInt objects.\n"; - - return boost::exit_success; -} diff --git a/ref_ct_test.cpp b/ref_ct_test.cpp deleted file mode 100644 index a3b5eea..0000000 --- a/ref_ct_test.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright David Abrahams and Aleksey Gurtovoy -// 2002-2004. Distributed under the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// compile-time test for "boost/ref.hpp" header content -// see 'ref_test.cpp' for run-time part - -#include -#include -#include -#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) -{ -#if BOOST_WORKAROUND(__BORLANDC__, < 0x600) - typedef typename boost::remove_const::type ref; - BOOST_STATIC_ASSERT((boost::is_same::value)); -#else - BOOST_STATIC_ASSERT((boost::is_same::value)); -#endif -} - -template< typename R, typename Ref > -void unwrap_reference_test(Ref) -{ -#if BOOST_WORKAROUND(__BORLANDC__, < 0x600) - typedef typename boost::remove_const::type ref; - typedef typename boost::unwrap_reference::type type; -#else - typedef typename boost::unwrap_reference::type type; -#endif - 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 63fc9e5..0000000 --- a/ref_test.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright David Abrahams and Aleksey Gurtovoy -// 2002-2004. Distributed under the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// run-time test for "boost/ref.hpp" header content -// see 'ref_ct_test.cpp' for compile-time part - -#if defined(_MSC_VER) && !defined(__ICL) -# pragma warning(disable: 4786) // identifier truncated in debug info -# pragma warning(disable: 4710) // function not inlined -# pragma warning(disable: 4711) // function selected for automatic inline expansion -# pragma warning(disable: 4514) // unreferenced inline removed -#endif - -#include - -#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_CHECK(passthru(ref(x)) == &x); - BOOST_CHECK(&ref(x).get() == &x); - - BOOST_CHECK(cref_passthru(cref(x)) == &x); - BOOST_CHECK(&cref(x).get() == &x); - } -}; - -} // namespace unnamed - -int test_main(int, char * []) -{ - ref_wrapper::test(1); - ref_wrapper::test(1); - return 0; -} diff --git a/shared_container_iterator.html b/shared_container_iterator.html deleted file mode 100644 index dfef648..0000000 --- a/shared_container_iterator.html +++ /dev/null @@ -1,322 +0,0 @@ - - - - - - -Shared Container Iterator Documentation - - - - -boost.png (6897 bytes) - -

Shared Container Iterator

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

-The purpose of the shared container iterator is to attach the lifetime -of a container to the lifetime of its iterators. In other words, the -container will not be deleted until after all its iterators are -destroyed. The shared container iterator is typically used to -implement functions that return iterators over a range of objects that -only need to exist for the lifetime of the iterators. By returning a -pair of shared iterators from a function, the callee can return a -heap-allocated range of objects whose lifetime is automatically managed. -

-The shared container iterator augments an iterator over a shared -container. It maintains a reference count on the shared -container. If only shared container iterators hold references to -the container, the container's lifetime will end when the last shared -container iterator over it is destroyed. In any case, the shared -container is guaranteed to persist beyond the lifetime of all -the iterators. In all other ways, the -shared container iterator behaves the same as its base iterator. - - -

Synopsis

- -
-namespace boost {
-  template <typename Container>
-  class shared_container_iterator;
-
-  template <typename Container>
-  shared_container_iterator<Container>
-  make_shared_container_iterator(typename Container::iterator base, 
-    boost::shared_ptr<Container> const& container);
-
-  std::pair<
-    typename shared_container_iterator<Container>,
-    typename shared_container_iterator<Container>
-  >
-  make_shared_container_range(boost::shared_ptr<Container> const& container);
-}
-
- -
- -

The Shared Container Iterator Type

- -
-template <typename Container> class shared_container_iterator;
-
- -The class template shared_container_iterator -is the shared container iterator type. The Container template -type argument must model the -Container -concept. - -

Example

- -

-The following example illustrates how to create an iterator that -regulates the lifetime of a reference counted std::vector. -Though the original shared pointer ints ceases to exist -after set_range() returns, the -shared_counter_iterator objects maintain references to the - underlying vector and thereby extend the container's lifetime. -

-shared_iterator_example1.cpp: -

-#include "shared_container_iterator.hpp"
-#include "boost/shared_ptr.hpp"
-#include <algorithm>
-#include <iostream>
-#include <vector>
-
-typedef boost::shared_container_iterator< std::vector<int> > iterator;
-
-
-void set_range(iterator& i, iterator& end)  {
-
-  boost::shared_ptr< std::vector<int> > ints(new std::vector<int>());
-  
-  ints->push_back(0);
-  ints->push_back(1);
-  ints->push_back(2);
-  ints->push_back(3);
-  ints->push_back(4);
-  ints->push_back(5);
-  
-  i = iterator(ints->begin(),ints);
-  end = iterator(ints->end(),ints);
-}
-
-
-int main() {
-
-  iterator i,end;
-
-  set_range(i,end);
-
-  std::copy(i,end,std::ostream_iterator<int>(std::cout,","));
-  std::cout.put('\n');
-
-  return 0;
-}
-
- -The output from this part is: -
-0,1,2,3,4,5,
-
- -

Template Parameters

- - - - - - - - - - -
ParameterDescription
ContainerThe type of the container that we wish to iterate over. It must be -a model of the -Container -concept. -
- -

Model of

- -The shared_container_iterator type models the -same iterator concept as the base iterator - (Container::iterator). - -

Members

- -The shared container iterator type implements the member functions and -operators required of the Random Access Iterator -concept, though only operations defined for the base iterator will be valid. -In addition it has the following constructor: - -
-shared_container_iterator(Container::iterator const& it,
-                          boost::shared_ptr<Container> const& container)
-
- -

-


-

- - -

The Shared Container Iterator Object Generator

- -
-template <typename Container>
-shared_container_iterator<Container>
-make_shared_container_iterator(Container::iterator base,
-                               boost::shared_ptr<Container> const& container)
-
- -This function provides an alternative to directly constructing a -shared container iterator. Using the object generator, a shared -container iterator can be created and passed to a function without -explicitly specifying its type. - -

Example

- -This example, similar to the previous, uses -make_shared_container_iterator() to create the iterators. - -

-shared_iterator_example2.cpp: - -

-#include "shared_container_iterator.hpp"
-#include "boost/shared_ptr.hpp"
-#include <algorithm>
-#include <iterator>
-#include <iostream>
-#include <vector>
-
-
-template <typename Iterator>
-void print_range_nl (Iterator begin, Iterator end) {
-  typedef typename std::iterator_traits<Iterator>::value_type val;
-  std::copy(begin,end,std::ostream_iterator<val>(std::cout,","));
-  std::cout.put('\n');
-}
-
-
-int main() {
-
-  typedef boost::shared_ptr< std::vector<int> > ints_t;
-  {
-    ints_t ints(new std::vector<int>());
-
-    ints->push_back(0);
-    ints->push_back(1);
-    ints->push_back(2);
-    ints->push_back(3);
-    ints->push_back(4);
-    ints->push_back(5);
-
-    print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints),
-		   boost::make_shared_container_iterator(ints->end(),ints));
-  }
-  
-
-
-  return 0;
-}
-
- -Observe that the shared_container_iterator type is never -explicitly named. The output from this example is the same as the previous. - -

The Shared Container Iterator Range Generator

- -
-template <typename Container>
-std::pair<
-  shared_container_iterator<Container>,
-  shared_container_iterator<Container>
->
-make_shared_container_range(boost::shared_ptr<Container> const& container);
-
- -Class shared_container_iterator is meant primarily to return, -using iterators, a range of values that we can guarantee will be alive as -long as the iterators are. This is a convenience -function to do just that. It is equivalent to - -
-std::make_pair(make_shared_container_iterator(container->begin(),container),
-               make_shared_container_iterator(container->end(),container));
-
- -

Example

- -In the following example, a range of values is returned as a pair of -shared_container_iterator objects. - - -

-shared_iterator_example3.cpp: - -

-#include "shared_container_iterator.hpp"
-#include "boost/shared_ptr.hpp"
-#include "boost/tuple/tuple.hpp" // for boost::tie
-#include <algorithm>              // for std::copy
-#include <iostream>              
-#include <vector>
-
-
-typedef boost::shared_container_iterator< std::vector<int> > iterator; 
-
-std::pair<iterator,iterator>
-return_range() {
-  boost::shared_ptr< std::vector<int> > range(new std::vector<int>());
-  range->push_back(0);
-  range->push_back(1);
-  range->push_back(2);
-  range->push_back(3);
-  range->push_back(4);
-  range->push_back(5);
-  return boost::make_shared_container_range(range);
-}
-
-
-int main() {
-
-
-  iterator i,end;
-  
-  boost::tie(i,end) = return_range();
-
-  std::copy(i,end,std::ostream_iterator<int>(std::cout,","));
-  std::cout.put('\n');
-
-  return 0;
-}
-
- -Though the range object only lives for the duration of the -return_range call, the reference counted -std::vector will live until i and end -are both destroyed. The output from this example is the same as -the previous two. - - -
- -Last modified: Mon Aug 11 11:27:03 EST 2003 - -

© Copyright 2003 The Trustees of Indiana University. - Use, modification and distribution is subject to the Boost Software - License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at - http:www.boost.org/LICENSE_1_0.txt)

- - - - diff --git a/shared_iterator_example1.cpp b/shared_iterator_example1.cpp deleted file mode 100644 index f88e094..0000000 --- a/shared_iterator_example1.cpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2003 The Trustees of Indiana University. - -// Use, modification and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include "boost/shared_container_iterator.hpp" -#include "boost/shared_ptr.hpp" -#include -#include -#include - -typedef boost::shared_container_iterator< std::vector > iterator; - - -void set_range(iterator& i, iterator& end) { - - boost::shared_ptr< std::vector > ints(new std::vector()); - - ints->push_back(0); - ints->push_back(1); - ints->push_back(2); - ints->push_back(3); - ints->push_back(4); - ints->push_back(5); - - i = iterator(ints->begin(),ints); - end = iterator(ints->end(),ints); -} - - -int main() { - - iterator i,end; - - set_range(i,end); - - std::copy(i,end,std::ostream_iterator(std::cout,",")); - std::cout.put('\n'); - - return 0; -} diff --git a/shared_iterator_example2.cpp b/shared_iterator_example2.cpp deleted file mode 100644 index a957707..0000000 --- a/shared_iterator_example2.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2003 The Trustees of Indiana University. - -// Use, modification and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include "boost/shared_container_iterator.hpp" -#include "boost/shared_ptr.hpp" -#include -#include -#include -#include - - -template -void print_range_nl (Iterator begin, Iterator end) { - typedef typename std::iterator_traits::value_type val; - std::copy(begin,end,std::ostream_iterator(std::cout,",")); - std::cout.put('\n'); -} - - -int main() { - - typedef boost::shared_ptr< std::vector > ints_t; - { - ints_t ints(new std::vector()); - - ints->push_back(0); - ints->push_back(1); - ints->push_back(2); - ints->push_back(3); - ints->push_back(4); - ints->push_back(5); - - print_range_nl(boost::make_shared_container_iterator(ints->begin(),ints), - boost::make_shared_container_iterator(ints->end(),ints)); - } - - - - return 0; -} diff --git a/shared_iterator_example3.cpp b/shared_iterator_example3.cpp deleted file mode 100644 index 5615d45..0000000 --- a/shared_iterator_example3.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2003 The Trustees of Indiana University. - -// Use, modification and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -#include "boost/shared_container_iterator.hpp" -#include "boost/shared_ptr.hpp" -#include "boost/tuple/tuple.hpp" // for boost::tie -#include // for std::copy -#include -#include - - -typedef boost::shared_container_iterator< std::vector > iterator; - -std::pair -return_range() { - boost::shared_ptr< std::vector > range(new std::vector()); - range->push_back(0); - range->push_back(1); - range->push_back(2); - range->push_back(3); - range->push_back(4); - range->push_back(5); - return boost::make_shared_container_range(range); -} - - -int main() { - - - iterator i,end; - - boost::tie(i,end) = return_range(); - - std::copy(i,end,std::ostream_iterator(std::cout,",")); - std::cout.put('\n'); - - return 0; -} diff --git a/shared_iterator_test.cpp b/shared_iterator_test.cpp deleted file mode 100644 index ff5b9c6..0000000 --- a/shared_iterator_test.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2003 The Trustees of Indiana University. - -// Use, modification and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Shared container iterator adaptor -// Author: Ronald Garcia -// See http://boost.org/libs/utility/shared_container_iterator.html -// for documentation. - -// -// shared_iterator_test.cpp - Regression tests for shared_container_iterator. -// - - -#include "boost/shared_container_iterator.hpp" -#include "boost/shared_ptr.hpp" -#include -#include - -struct resource { - static int count; - resource() { ++count; } - resource(resource const&) { ++count; } - ~resource() { --count; } -}; -int resource::count = 0; - -typedef std::vector resources_t; - -typedef boost::shared_container_iterator< resources_t > iterator; - - -void set_range(iterator& i, iterator& end) { - - boost::shared_ptr< resources_t > objs(new resources_t()); - - for (int j = 0; j != 6; ++j) - objs->push_back(resource()); - - i = iterator(objs->begin(),objs); - end = iterator(objs->end(),objs); - assert(resource::count == 6); -} - - -int main() { - - assert(resource::count == 0); - - { - iterator i; - { - iterator end; - set_range(i,end); - assert(resource::count == 6); - } - assert(resource::count == 6); - } - assert(resource::count == 0); - - return 0; -} diff --git a/test/Jamfile b/test/Jamfile deleted file mode 100755 index 89d77d0..0000000 --- a/test/Jamfile +++ /dev/null @@ -1,43 +0,0 @@ -# Copyright David Abrahams 2003. Permission to copy, use, -# modify, sell and distribute this software is granted provided this -# copyright notice appears in all copies. This software is provided -# "as is" without express or implied warranty, and with no claim as -# to its suitability for any purpose. - -# For more information, see http://www.boost.org/ - -subproject libs/utility/test ; - -# bring in rules for testing -import testing ; - -# Make tests run by default. -DEPENDS all : test ; - -local test_monitor = @boost/libs/test/build/boost_test_exec_monitor ; - -# Please keep the tests ordered by filename -test-suite utility - : - [ run ../addressof_test.cpp ] - [ run ../assert_test.cpp ] - [ run ../base_from_member_test.cpp ] - [ run ../binary_search_test.cpp ] - [ run ../call_traits_test.cpp : -u ] - [ compile-fail ../checked_delete_test.cpp ] - [ run ../compressed_pair_test.cpp $(test_monitor) : -u ] - [ run ../current_function_test.cpp : : : always_show_run_output ] - [ run ../iterators_test.cpp $(test_monitor) ] - [ run next_prior_test.cpp $(test_monitor) ] - [ compile-fail ../noncopyable_test.cpp ] - [ run ../numeric_traits_test.cpp ] - [ run ../operators_test.cpp $(test_monitor) ] - [ compile ../ref_ct_test.cpp ] - [ run ../ref_test.cpp $(test_monitor) ] - [ compile result_of_test.cpp ] - [ run ../shared_iterator_test.cpp ] - [ run ../value_init_test.cpp ] - [ compile-fail ../value_init_test_fail1.cpp ] - [ compile-fail ../value_init_test_fail2.cpp ] - [ compile-fail ../value_init_test_fail3.cpp ] - ; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 deleted file mode 100644 index 493011d..0000000 --- a/test/Jamfile.v2 +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright David Abrahams 2003. Permission to copy, use, -# modify, sell and distribute this software is granted provided this -# copyright notice appears in all copies. This software is provided -# "as is" without express or implied warranty, and with no claim as -# to its suitability for any purpose. - -# For more information, see http://www.boost.org/ - -# bring in rules for testing -import testing ; - -# Please keep the tests ordered by filename -test-suite utility - : - [ run ../addressof_test.cpp ] - [ run ../assert_test.cpp ] - [ run ../base_from_member_test.cpp ] - [ run ../binary_search_test.cpp ] - [ run ../call_traits_test.cpp : -u ] - [ compile-fail ../checked_delete_test.cpp ] - [ run ../compressed_pair_test.cpp ../../test/build//boost_test_exec_monitor : -u ] - [ run ../current_function_test.cpp : : : always_show_run_output ] - [ run ../iterators_test.cpp ../../test/build//boost_test_exec_monitor ] - [ run next_prior_test.cpp ../../test/build//boost_test_exec_monitor ] - [ compile-fail ../noncopyable_test.cpp ] - [ run ../numeric_traits_test.cpp ] - [ run ../operators_test.cpp ../../test/build//boost_test_exec_monitor ] - [ compile ../ref_ct_test.cpp ] - [ run ../ref_test.cpp ../../test/build//boost_test_exec_monitor ] - [ compile result_of_test.cpp ] - [ run ../shared_iterator_test.cpp ] - [ run ../value_init_test.cpp ] - [ compile-fail ../value_init_test_fail1.cpp ] - [ compile-fail ../value_init_test_fail2.cpp ] - [ compile-fail ../value_init_test_fail3.cpp ] - ; diff --git a/test/next_prior_test.cpp b/test/next_prior_test.cpp deleted file mode 100755 index ebce472..0000000 --- a/test/next_prior_test.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// Boost test program for next() and prior() utilities. - -// Copyright 2003 Daniel Walker. Use, modification, and distribution -// are subject to the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or a copy at -// http://www.boost.org/LICENSE_1_0.txt.) - -// See http://www.boost.org/libs/utility for documentation. - -// Revision History 13 Dec 2003 Initial Version (Daniel Walker) - -// next() and prior() are replacements for operator+ and operator- for -// non-random-access iterators. The semantics of these operators are -// such that after executing j = i + n, std::distance(i, j) equals -// n. Tests are provided to ensure next() has the same -// result. Parallel tests are provided for prior(). The tests call -// next() and prior() several times. next() and prior() are very -// simple functions, though, and it would be very strange if these -// tests were to fail. - -#define BOOST_INCLUDE_MAIN -#include - -#include -#include - -#include - -template -bool plus_one_test(RandomAccessIterator first, RandomAccessIterator last, ForwardIterator first2) -{ - RandomAccessIterator i = first; - ForwardIterator j = first2; - while(i != last) - i = i + 1, j = boost::next(j); - return std::distance(first, i) == std::distance(first2, j); -} - -template -bool plus_n_test(RandomAccessIterator first, RandomAccessIterator last, ForwardIterator first2) -{ - RandomAccessIterator i = first; - ForwardIterator j = first2; - for(int n = 0; i != last; ++n) - i = first + n, j = boost::next(first2, n); - return std::distance(first, i) == std::distance(first2, j); -} - -template -bool minus_one_test(RandomAccessIterator first, RandomAccessIterator last, BidirectionalIterator last2) -{ - RandomAccessIterator i = last; - BidirectionalIterator j = last2; - while(i != first) - i = i - 1, j = boost::prior(j); - return std::distance(i, last) == std::distance(j, last2); -} - -template -bool minus_n_test(RandomAccessIterator first, RandomAccessIterator last, BidirectionalIterator last2) -{ - RandomAccessIterator i = last; - BidirectionalIterator j = last2; - for(int n = 0; i != first; ++n) - i = last - n, j = boost::prior(last2, n); - return std::distance(i, last) == std::distance(j, last2); -} - -int test_main(int, char*[]) -{ - std::vector x(8); - std::list y(x.begin(), x.end()); - - BOOST_REQUIRE(plus_one_test(x.begin(), x.end(), y.begin())); - BOOST_REQUIRE(plus_n_test(x.begin(), x.end(), y.begin())); - BOOST_REQUIRE(minus_one_test(x.begin(), x.end(), y.end())); - BOOST_REQUIRE(minus_n_test(x.begin(), x.end(), y.end())); - return 0; -} diff --git a/test/result_of_test.cpp b/test/result_of_test.cpp deleted file mode 100644 index af7aba2..0000000 --- a/test/result_of_test.cpp +++ /dev/null @@ -1,53 +0,0 @@ -// Boost result_of library - -// Copyright Douglas Gregor 2003-2004. Use, modification and -// distribution is subject to the Boost Software License, Version -// 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// For more information, see http://www.boost.org/libs/utility -#include -#include -#include -#include - -struct int_result_type { typedef int result_type; }; - -struct int_result_of -{ - template struct result { typedef int type; }; -}; - -struct int_result_type_and_float_result_of -{ - typedef int result_type; - template struct result { typedef float type; }; -}; - -struct X {}; - -int main() -{ - using namespace boost; - - typedef int (*func_ptr)(float, double); - typedef int (&func_ref)(float, double); - typedef int (X::*mem_func_ptr)(float); - typedef int (X::*mem_func_ptr_c)(float) const; - typedef int (X::*mem_func_ptr_v)(float) volatile; - typedef int (X::*mem_func_ptr_cv)(float) const volatile; - - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same::type, void>::value)); - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same::type, void>::value)); - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - BOOST_STATIC_ASSERT((is_same::type, int>::value)); - return 0; -} diff --git a/throw_exception.html b/throw_exception.html deleted file mode 100644 index b5bbbc7..0000000 --- a/throw_exception.html +++ /dev/null @@ -1,60 +0,0 @@ - - - - Boost: throw_exception.hpp documentation - - - - - - - - - - - -
- boost.png (6897 bytes) - -

throw_exception.hpp

-
 
-

- The header <boost/throw_exception.hpp> defines the - helper function boost::throw_exception. It is intended to be - used in Boost libraries that need to throw exceptions, but support - configurations and platforms where exceptions aren't available, as indicated by - the presence of the BOOST_NO_EXCEPTIONS - configuration macro. -

-

When BOOST_NO_EXCEPTIONS is not defined, boost::throw_exception(e) - is equivalent to throw e. Otherwise, the function is left undefined, - and the user is expected to supply an appropriate definition. Callers of throw_exception - are allowed to assume that the function never returns; therefore, if the - user-defined throw_exception returns, the behavior is undefined.

-

Synopsis

-
-namespace boost
-{
-
-#ifdef BOOST_NO_EXCEPTIONS
-
-void throw_exception(std::exception const & e); // user defined
-
-#else
-
-template<class E> void throw_exception(E const & e)
-{
-    throw e;
-}
-
-#endif
-
-}
-
-


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

- - diff --git a/utility.htm b/utility.htm deleted file mode 100644 index 16616ad..0000000 --- a/utility.htm +++ /dev/null @@ -1,193 +0,0 @@ - - - - Header boost/utility.hpp Documentation - - -

boost.png (6897 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()

-

See separate documentation.

-

- 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 T, class Distance>
-T next(T x, Distance n)
-{
-    std::advance(x, n);
-    return x;
-}
-
-template <class T>
-T prior(T x) { return --x; }
-
-template <class T, class Distance>
-T prior(T x, Distance n)
-{
-    std::advance(x, -n);
-    return x;
-}
-
-

Usage is simple:

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

The distance from the given iterator should be supplied as an absolute value. For - example, the iterator four iterators prior to the given iterator p - may be obtained by prior(p, 4).

-

Contributed by Dave Abrahams. Two-argument versions by Daniel Walker.

-

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 template - result_of

The class template - result_of helps determine the type of a - call expression. Given an lvalue f of - type F and lvalues t1, - t2, ..., tN of - types T1, T2, ..., - TN, respectively, the type - result_of<F(T1, T2, ..., - TN)>::type defines the result type - of the expression f(t1, t2, - ...,tN). The implementation permits - the type F to be a function pointer, - function reference, member function pointer, or class - type. When F is a class type with a - member type result_type, - result_of<F(T1, T2, ..., - TN)> is - F::result_type. Otherwise, - result_of<F(T1, T2, ..., - TN)> is F::result<F(T1, - T2, ..., TN)>::type when - N > 0 or void - when N = 0. For additional - information about result_of, see the - current draft of the C++ Library TR, N1647, - or the result_of proposal.

- -

Class template result_of resides in - the header <boost/utility/result_of.hpp>. By - default, N may be any value between 0 and - 10. To change the upper limit, define the macro - BOOST_RESULT_OF_NUM_ARGS to the maximum - value for N.

- - -

This implementation of result_of requires class template partial specialization, the ability to parse function types properly, and support for SFINAE. If result_of is not supported by your compiler, including the header boost/utility/result_of.hpp will define the macro BOOST_NO_RESULT_OF. Contributed by Doug Gregor.

- -

Class templates for the Base-from-Member Idiom

-

See separate documentation.

-
-

Revised  02 May, 2004 -

-

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

- - diff --git a/value_init.htm b/value_init.htm deleted file mode 100644 index d8c28e3..0000000 --- a/value_init.htm +++ /dev/null @@ -1,219 +0,0 @@ - - - - - value_initialized - - - - -

- Header <boost/utility/value_init.hpp> -

- -

Contents

- -
-
Rationale
-
Introduction
-
- - - -
-
Types
-
- - - Acknowledgements
-
- -
-

Rationale

- -

Constructing and initializing objects in a generic way is difficult in - C++. The problem is that there are several different rules that apply -for initialization. Depending on the type, the value of a newly constructed - object can be zero-initialized (logically 0), default-constructed (using - the default constructor), or indeterminate. When writing generic code, -this problem must be addressed. value_initialized provides -a solution with consistent syntax for value initialization of scalar, -union and class types.
-

- -

Introduction

- -

The C++ standard [1] contains the definitions - of zero-initialization and default-initialization. - Informally, zero-initialization means that the object is given the initial - value 0 (converted to the type) and default-initialization means that - POD [2] types are zero-initialized, while class - types are initialized with their corresponding default constructors. A -declaration can contain an initializer, which specifies the -object's initial value. The initializer can be just '()', which states that -the object shall be default-initialized (but see below). However, if a declaration - has no initializer and it is of a non-const, non-static - POD type, the initial value is indeterminate:(see §8.5 for the - accurate definitions).

- -
int x ; // no initializer. x value is indeterminate.
std::string s ; // no initializer, s is default-constructed.

int y = int() ;
// y is initialized using copy-initialization
// but the temporary uses an empty set of parentheses as the initializer,
// so it is default-constructed.
// A default constructed POD type is zero-initialized,
// therefore, y == 0.

void foo ( std::string ) ;
foo ( std::string() ) ;
// the temporary string is default constructed
// as indicated by the initializer ()
- -

value-initialization

- -

The first Technical - Corrigendum for the C++ Standard (TC1), whose draft was released to - the public in November 2001, introduced Core - Issue 178 (among many other issues, of course).

- -

That issue introduced the new concept of value-initialization - (it also fixed the wording for zero-initialization). Informally, value-initialization - is similar to default-initialization with the exception that in some cases - non-static data members and base class sub-objects are also value-initialized. - The difference is that an object that is value-initialized won't have -(or at least is less likely to have) indeterminate values for data members - and base class sub-objects; unlike the case of an object default constructed. - (see Core Issue 178 for a normative description).

- -

In order to specify value-initialization of an object we need to use the - empty-set initializer: ().

- -

(but recall that the current C++ Standard states that '()' invokes default-initialization, -not value-initialization)

- -

As before, a declaration with no intializer specifies default-initialization, - and a declaration with a non-empty initializer specifies copy (=xxx) or - direct (xxx) initialization.

- -
template<class T> void eat(T);
int x ; // indeterminate initial value.
std::string s; // default-initialized.
eat ( int() ) ; // value-initialized
eat ( std::string() ) ; // value-initialied
- -

value-initialization syntax

- -

Value initialization is specified using (). However, the empty set of -parentheses is not permitted by the syntax of initializers because it is -parsed as the declaration of a function taking no arguments:

- -
int x() ; // declares function int(*)()
int y ( int() ) ; // decalares function int(*)( int(*)() )
- -

Thus, the empty () must be put in some other initialization context.

- -

One alternative is to use copy-initialization syntax:

- -
int x = int() ;
- -

This works perfectly fine for POD types. But for non-POD class types, -copy-initialization searches for a suitable constructor, which could be, -for instance, the copy-constructor (it also searches for a suitable conversion -sequence but this doesn't apply in this context). For an arbitrary unknown -type, using this syntax may not have the value-initialization effect intended -because we don't know if a copy from a default constructed object is exactly -the same as a default constructed object, and the compiler is allowed (in -some cases), but never required to, optimize the copy away.

- -

One possible generic solution is to use value-initialization of a non static -data member:

- -
template<class T> 
struct W
{
// value-initialization of 'data' here.
W() : data() {}
T data ;
} ;
W<int> w ;
// w.data is value-initialized for any type.
- -

This is the solution supplied by the value_initialized<> template - class.

- -

Types

- -

template class value_initialized<T>

- -
namespace boost {

template<class T>
class value_initialized
{
public :
value_initialized() : x() {}
operator T&() const { return x ; }
T& data() const { return x ; }

private :
unspecified x ;
} ;

template<class T>
T const& get ( value_initialized<T> const& x )
{
return x.data() ;
}

template<class T>
T& get ( value_initialized<T>& x )
{
return x.data() ;
}

} // namespace boost
- -

An object of this template class is a T-wrapper convertible - to 'T&' whose wrapped object (data member of type T) - is value-initialized upon default-initialization - of this wrapper class:

- -
int zero = 0 ;
value_initialized<int> x ;
assert ( x == zero ) ;

std::string def ;
value_initialized< std::string > y ;
assert ( y == def ) ;
- -

The purpose of this wrapper is to provide a consistent syntax for value - initialization of scalar, union and class types (POD and non-POD) since - the correct syntax for value initialization varies (see value-initialization syntax)

- -

The wrapped object can be accessed either through the conversion operator - T&, the member function data(), or the -non-member function get():

- -
void watch(int);
value_initialized<int> x;

watch(x) ; // operator T& used.
watch(x.data());
watch( get(x) ) // function get() used
- -

Both const and non-const objects can be wrapped. - Mutable objects can be modified directly from within the wrapper but constant - objects cannot:

- -
value_initialized<int> x ; 
static_cast<int&>(x) = 1 ; // OK
get(x) = 1 ; // OK

value_initialized<int const> y ;
static_cast<int&>(y) = 1 ; // ERROR: cannot cast to int&
static_cast<int const&>(y) = 1 ; // ERROR: cannot modify a const value
get(y) = 1 ; // ERROR: cannot modify a const value
- -

Warning:

- -

Both the conversion operator and the data() member function - are const in order to allow access to the wrapped object -from a constant wrapper:

- -
void foo(int);
value_initialized<int> const x ;
foo(x);
- -

But notice that this conversion operator is to T& although - it is itself const. As a consequence, if T is - a non-const type, you can modify the wrapped object even from - within a constant wrapper:

- -
value_initialized<int> const x_c ;
int& xr = x_c ; // OK, conversion to int& available even though x_c is itself const.
xr = 2 ;
- -

The reason for this obscure behavior is that some commonly used compilers - just don't accept the following valid code:

- -
struct X
{
operator int&() ;
operator int const&() const ;
};
X x ;
(x == 1 ) ; // ERROR HERE!
- -

These compilers complain about ambiguity between the conversion operators. - This complaint is incorrect, but the only workaround that I know of is - to provide only one of them, which leads to the obscure behavior just explained.
-

- -

Recommended practice: The non-member get() idiom

- -

The obscure behavior of being able to modify a non-const -wrapped object from within a constant wrapper can be avoided if access to -the wrapped object is always performed with the get() idiom:

- -
value_initialized<int> x ;
get(x) = 1 ; // OK

value_initialized<int const> cx ;
get(x) = 1 ; // ERROR: Cannot modify a const object

value_initialized<int> const x_c ;
get(x_c) = 1 ; // ERROR: Cannot modify a const object

value_initialized<int const> const cx_c ;
get(cx_c) = 1 ; // ERROR: Cannot modify a const object
- -

References

- [1] The C++ Standard, ISO/IEC 14882:98
- [2] Plain Old Data -

Acknowledgements

- value_initialized was developed by Fernando Cacciola, with help and -suggestions from David Abrahams and Darin Adler.
-Special thanks to Björn Karlsson who carefully edited and completed this documentation. -
 
- -
-

Revised 19 September 2002

- -

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

- -

Developed by Fernando Cacciola, - 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/value_init_test.cpp b/value_init_test.cpp deleted file mode 100644 index fe73cc1..0000000 --- a/value_init_test.cpp +++ /dev/null @@ -1,107 +0,0 @@ -// (C) 2002, Fernando Luis Cacciola Carballal. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Test program for "boost/utility/value_init.hpp" -// -// Initial: 21 Agu 2002 - -#include -#include - -#include "boost/utility/value_init.hpp" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#include "boost/test/minimal.hpp" - -// -// Sample POD type -// -struct POD -{ - POD () : c(0), i(0), f(0) {} - - POD ( char c_, int i_, float f_ ) : c(c_), i(i_), f(f_) {} - - friend std::ostream& operator << ( std::ostream& os, POD const& pod ) - { return os << '(' << pod.c << ',' << pod.i << ',' << pod.f << ')' ; } - - friend bool operator == ( POD const& lhs, POD const& rhs ) - { return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; } - - float f; - char c; - int i; -} ; - -// -// Sample non POD type -// -struct NonPODBase -{ - virtual ~NonPODBase() {} -} ; -struct NonPOD : NonPODBase -{ - NonPOD () : id() {} - NonPOD ( std::string const& id_) : id(id_) {} - - friend std::ostream& operator << ( std::ostream& os, NonPOD const& npod ) - { return os << '(' << npod.id << ')' ; } - - friend bool operator == ( NonPOD const& lhs, NonPOD const& rhs ) - { return lhs.id == rhs.id ; } - - std::string id ; -} ; - -template -void test ( T const& y, T const& z ) -{ - boost::value_initialized x ; - BOOST_CHECK ( y == x ) ; - BOOST_CHECK ( y == boost::get(x) ) ; - static_cast(x) = z ; - boost::get(x) = z ; - BOOST_CHECK ( x == z ) ; - - boost::value_initialized const x_c ; - BOOST_CHECK ( y == x_c ) ; - BOOST_CHECK ( y == boost::get(x_c) ) ; - T& x_c_ref = x_c ; - x_c_ref = z ; - BOOST_CHECK ( x_c == z ) ; - -#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) - boost::value_initialized cx ; - BOOST_CHECK ( y == cx ) ; - BOOST_CHECK ( y == boost::get(cx) ) ; - - boost::value_initialized const cx_c ; - BOOST_CHECK ( y == cx_c ) ; - BOOST_CHECK ( y == boost::get(cx_c) ) ; -#endif -} - -int test_main(int, char **) -{ - test( 0,1234 ) ; - test( 0.0,12.34 ) ; - test( POD(0,0,0.0), POD('a',1234,56.78) ) ; - test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ; - - return 0; -} - - -unsigned int expected_failures = 0; - - - - - diff --git a/value_init_test_fail1.cpp b/value_init_test_fail1.cpp deleted file mode 100644 index 8904732..0000000 --- a/value_init_test_fail1.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// (C) 2002, Fernando Luis Cacciola Carballal. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Test program for "boost/utility/value_init.hpp" -// -// Initial: 21 Agu 2002 - -#include -#include - -#include "boost/utility/value_init.hpp" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#include "boost/test/minimal.hpp" - -int test_main(int, char **) -{ - boost::value_initialized const x_c ; - - get(x_c) = 1234 ; // this should produce an ERROR - - return 0; -} - - -unsigned int expected_failures = 0; - - - - - diff --git a/value_init_test_fail2.cpp b/value_init_test_fail2.cpp deleted file mode 100644 index 1f40061..0000000 --- a/value_init_test_fail2.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// (C) 2002, Fernando Luis Cacciola Carballal. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Test program for "boost/utility/value_init.hpp" -// -// Initial: 21 Agu 2002 - -#include -#include - -#include "boost/utility/value_init.hpp" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#include "boost/test/minimal.hpp" - -int test_main(int, char **) -{ - boost::value_initialized cx ; - - get(cx) = 1234 ; // this should produce an ERROR - - return 0; -} - -unsigned int expected_failures = 0; - - - - - diff --git a/value_init_test_fail3.cpp b/value_init_test_fail3.cpp deleted file mode 100644 index 72fd761..0000000 --- a/value_init_test_fail3.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// (C) 2002, Fernando Luis Cacciola Carballal. -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) -// -// Test program for "boost/utility/value_init.hpp" -// -// Initial: 21 Agu 2002 - -#include -#include - -#include "boost/utility/value_init.hpp" - -#ifdef __BORLANDC__ -#pragma hdrstop -#endif - -#include "boost/test/minimal.hpp" - -int test_main(int, char **) -{ - boost::value_initialized const cx_c ; - - get(cx_c) = 1234 ; // this should produce an ERROR - - return 0; -} - - -unsigned int expected_failures = 0; - - - - -