From f02dc90bfcb52e5be1e72394c9e38fa79a2b5736 Mon Sep 17 00:00:00 2001 From: nobody Date: Sat, 27 Jan 2001 17:35:01 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create branch 'unlabeled-1.1.2'. [SVN r8787] --- Assignable.html | 116 --- CopyConstructible.html | 210 ----- LessThanComparable.html | 212 ----- MultiPassInputIterator.html | 92 --- algo_opt_examples.cpp | 424 ---------- c++_type_traits.htm | 489 ------------ call_traits.htm | 754 ------------------ call_traits_test.cpp | 366 --------- compressed_pair.htm | 92 --- compressed_pair_test.cpp | 159 ---- include/boost/call_traits.hpp | 23 - include/boost/compressed_pair.hpp | 23 - include/boost/detail/call_traits.hpp | 138 ---- include/boost/detail/compressed_pair.hpp | 424 ---------- include/boost/detail/ob_call_traits.hpp | 125 --- include/boost/detail/ob_compressed_pair.hpp | 474 ----------- include/boost/operators.hpp | 563 -------------- include/boost/utility.hpp | 96 --- iterator_adaptor_examples.cpp | 47 -- iterator_adaptor_test.cpp | 190 ----- iterator_adaptors.htm | 819 -------------------- iterator_traits_test.cpp | 141 ---- iterators_test.cpp | 169 ---- noncopyable_test.cpp | 38 - numeric_traits_test.cpp | 385 --------- operators.htm | 597 -------------- operators_test.cpp | 481 ------------ tie.html | 137 ---- tie_example.cpp | 61 -- type_traits.htm | 620 --------------- type_traits_test.cpp | 659 ---------------- type_traits_test.hpp | 114 --- utility.htm | 104 --- 33 files changed, 9342 deletions(-) delete mode 100644 Assignable.html delete mode 100644 CopyConstructible.html delete mode 100644 LessThanComparable.html delete mode 100644 MultiPassInputIterator.html delete mode 100644 algo_opt_examples.cpp delete mode 100644 c++_type_traits.htm delete mode 100644 call_traits.htm delete mode 100644 call_traits_test.cpp delete mode 100644 compressed_pair.htm delete mode 100644 compressed_pair_test.cpp delete mode 100644 include/boost/call_traits.hpp delete mode 100644 include/boost/compressed_pair.hpp delete mode 100644 include/boost/detail/call_traits.hpp delete mode 100644 include/boost/detail/compressed_pair.hpp delete mode 100644 include/boost/detail/ob_call_traits.hpp delete mode 100644 include/boost/detail/ob_compressed_pair.hpp delete mode 100644 include/boost/operators.hpp delete mode 100644 include/boost/utility.hpp delete mode 100644 iterator_adaptor_examples.cpp delete mode 100644 iterator_adaptor_test.cpp delete mode 100644 iterator_adaptors.htm delete mode 100644 iterator_traits_test.cpp delete mode 100644 iterators_test.cpp delete mode 100644 noncopyable_test.cpp delete mode 100644 numeric_traits_test.cpp delete mode 100644 operators.htm delete mode 100644 operators_test.cpp delete mode 100644 tie.html delete mode 100644 tie_example.cpp delete mode 100644 type_traits.htm delete mode 100644 type_traits_test.cpp delete mode 100644 type_traits_test.hpp delete mode 100644 utility.htm diff --git a/Assignable.html b/Assignable.html deleted file mode 100644 index c3109df..0000000 --- a/Assignable.html +++ /dev/null @@ -1,116 +0,0 @@ - - - -Assignable - - -C++ Boost - -
-

Assignable

- -

Description

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

Notation

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

Definitions

-

Valid expressions

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

Models

- - - -

See also

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

CopyConstructible

- -

Description

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

Notation

- - - - - - - - - - - - - - - - -
-T - -is type that is a model of CopyConstructible -
-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

-DefaultConstructible -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 294101c..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 99ee2fc..0000000 --- a/MultiPassInputIterator.html +++ /dev/null @@ -1,92 +0,0 @@ - - - -MultiPassInputIterator - -C++ Boost - -
- -

- -MultiPassInputIterator -

- -This concept is a refinement of InputIterator, -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 -MultiPassInputIterator is very similar to the ForwardIterator. The -only difference is that a ForwardIterator -requires the reference type to be value_type&, whereas -MultiPassInputIterator is like InputIterator -in that the reference type merely has to be convertible to -value_type. - - -

Design Notes

- -comments by Valentin Bonnard: - -

I think that introducing MultiPassInputIterator isn't the right -solution. Do you also want to define MultiPassBidirectionnalIterator -and MultiPassRandomAccessIterator ? 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 RandomAccess 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 MultiPassInputIterator -is just called a ForwardIterator. - -

-Other translations are:
-std::ForwardIterator -> ForwardIterator & LvalueIterator
-std::BidirectionnalIterator -> BidirectionnalIterator & LvalueIterator
-std::RandomAccessIterator -> RandomAccessIterator & LvalueIterator
- -

-Note that in practice the only operation not allowed on my -ForwardIterator which is allowed on std::ForwardIterator 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 ForwardIterator. The right course -of action is to get ForwardIterator, etc. changed in the C++ standard. -Once that is done we can drop MultiPassInputIterator. - - -
-


- - -
Copyright © 2000 -Jeremy Siek, Univ.of Notre Dame (jsiek@lsc.nd.edu) -
- - - diff --git a/algo_opt_examples.cpp b/algo_opt_examples.cpp deleted file mode 100644 index c30587c..0000000 --- a/algo_opt_examples.cpp +++ /dev/null @@ -1,424 +0,0 @@ - -/* - * - * Copyright (c) 1999 - * Dr John Maddock - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Dr John Maddock makes no representations - * about the suitability of this software for any purpose. - * It is provided "as is" without express or implied warranty. - * - * This file provides some example of type_traits usage - - * by "optimising" various algorithms: - * - * opt::copy - optimised for trivial copy (cf std::copy) - * opt::fill - optimised for trivial copy/small types (cf std::fill) - * opt::destroy_array - an example of optimisation based upon omitted destructor calls - * opt::iter_swap - uses type_traits to determine whether the iterator is a proxy - * in which case it uses a "safe" approach, otherwise calls swap - * on the assumption that swap may be specialised for the pointed-to type. - * - */ - -/* Release notes: - 23rd July 2000: - Added explicit failure for broken compilers that don't support these examples. - Fixed broken gcc support (broken using directive). - Reordered tests slightly. -*/ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -using std::cout; -using std::endl; -using std::cin; - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#error "Sorry, without template partial specialisation support there isn't anything to test here..." -#endif - -namespace opt{ - -// -// algorithm destroy_array: -// The reverse of std::unitialized_copy, takes a block of -// unitialized memory and calls destructors on all objects therein. -// - -namespace detail{ - -template -struct array_destroyer -{ - template - static void destroy_array(T* i, T* j){ do_destroy_array(i, j); } -}; - -template <> -struct array_destroyer -{ - template - static void destroy_array(T*, T*){} -}; - -template -void do_destroy_array(T* first, T* last) -{ - while(first != last) - { - first->~T(); - ++first; - } -} - -}; // namespace detail - -template -inline void destroy_array(T* p1, T* p2) -{ - detail::array_destroyer::value>::destroy_array(p1, p2); -} - -// -// unoptimised versions of destroy_array: -// -template -void destroy_array1(T* first, T* last) -{ - while(first != last) - { - first->~T(); - ++first; - } -} -template -void destroy_array2(T* first, T* last) -{ - for(; first != last; ++first) first->~T(); -} - - -// -// opt::copy -// same semantics as std::copy -// calls memcpy where appropiate. -// - -namespace detail{ - -template -struct copier -{ - template - static I2 do_copy(I1 first, I1 last, I2 out); -}; - -template -template -I2 copier::do_copy(I1 first, I1 last, I2 out) -{ - while(first != last) - { - *out = *first; - ++out; - ++first; - } - return out; -} - -template <> -struct copier -{ - template - static I2* do_copy(I1* first, I1* last, I2* out) - { - memcpy(out, first, (last-first)*sizeof(I2)); - return out+(last-first); - } -}; - - -} - -template -inline I2 copy(I1 first, I1 last, I2 out) -{ - typedef typename boost::remove_cv::value_type>::type v1_t; - typedef typename boost::remove_cv::value_type>::type v2_t; - enum{ can_opt = boost::is_same::value - && boost::is_pointer::value - && boost::is_pointer::value - && boost::has_trivial_assign::value }; - return detail::copier::do_copy(first, last, out); -} - -// -// fill -// same as std::fill, uses memset where appropriate, along with call_traits -// to "optimise" parameter passing. -// -namespace detail{ - -template -struct filler -{ - template - static void do_fill(I first, I last, typename boost::call_traits::param_type val); - }; - -template -template -void filler::do_fill(I first, I last, typename boost::call_traits::param_type val) -{ - while(first != last) - { - *first = val; - ++first; - } -} - -template <> -struct filler -{ - template - static void do_fill(I first, I last, T val) - { - std::memset(first, val, last-first); - } -}; - -} - -template -inline void fill(I first, I last, const T& val) -{ - enum{ can_opt = boost::is_pointer::value - && boost::is_arithmetic::value - && (sizeof(T) == 1) }; - typedef detail::filler filler_t; - filler_t::template do_fill(first, last, val); -} - -// -// iter_swap: -// tests whether iterator is a proxying iterator or not, and -// uses optimal form accordingly: -// -namespace detail{ - -template -struct swapper -{ - template - static void do_swap(I one, I two) - { - typedef typename std::iterator_traits::value_type v_t; - v_t v = *one; - *one = *two; - *two = v; - } -}; - -#ifdef __GNUC__ -using std::swap; -#endif - -template <> -struct swapper -{ - template - static void do_swap(I one, I two) - { - using std::swap; - swap(*one, *two); - } -}; - -} - -template -inline void iter_swap(I1 one, I2 two) -{ - typedef typename std::iterator_traits::reference r1_t; - typedef typename std::iterator_traits::reference r2_t; - enum{ can_opt = boost::is_reference::value && boost::is_reference::value && boost::is_same::value }; - detail::swapper::do_swap(one, two); -} - - -}; // namespace opt - -// -// define some global data: -// -const int array_size = 1000; -int i_array[array_size] = {0,}; -const int ci_array[array_size] = {0,}; -char c_array[array_size] = {0,}; -const char cc_array[array_size] = { 0,}; - -const int iter_count = 1000000; - - -int main() -{ - // - // test destroy_array, - // compare destruction time of an array of ints - // with unoptimised form. - // - cout << "Measuring times in micro-seconds per 1000 elements processed" << endl << endl; - cout << "testing destroy_array...\n" - "[Some compilers may be able to optimise the \"unoptimised\"\n versions as well as type_traits does.]" << endl; - /*cache load*/ opt::destroy_array(i_array, i_array + array_size); - boost::timer t; - double result; - int i; - for(i = 0; i < iter_count; ++i) - { - opt::destroy_array(i_array, i_array + array_size); - } - result = t.elapsed(); - cout << "destroy_array: " << result << endl; - /*cache load*/ opt::destroy_array1(i_array, i_array + array_size); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::destroy_array1(i_array, i_array + array_size); - } - result = t.elapsed(); - cout << "destroy_array(unoptimised#1): " << result << endl; - /*cache load*/ opt::destroy_array2(i_array, i_array + array_size); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::destroy_array2(i_array, i_array + array_size); - } - result = t.elapsed(); - cout << "destroy_array(unoptimised#2): " << result << endl << endl; - - cout << "testing fill(char)...\n" - "[Some standard library versions may already perform this optimisation.]" << endl; - /*cache load*/ opt::fill(c_array, c_array + array_size, (char)3); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::fill(c_array, c_array + array_size, (char)3); - } - result = t.elapsed(); - cout << "opt::fill: " << result << endl; - /*cache load*/ std::fill(c_array, c_array + array_size, (char)3); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - std::fill(c_array, c_array + array_size, (char)3); - } - result = t.elapsed(); - cout << "std::fill: " << result << endl << endl; - - cout << "testing fill(int)...\n" - "[Tests the effect of call_traits pass-by-value optimisation -\nthe value of this optimisation may depend upon hardware characteristics.]" << endl; - /*cache load*/ opt::fill(i_array, i_array + array_size, 3); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::fill(i_array, i_array + array_size, 3); - } - result = t.elapsed(); - cout << "opt::fill: " << result << endl; - /*cache load*/ std::fill(i_array, i_array + array_size, 3); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - std::fill(i_array, i_array + array_size, 3); - } - result = t.elapsed(); - cout << "std::fill: " << result << endl << endl; - - cout << "testing copy...\n" - "[Some standard library versions may already perform this optimisation.]" << endl; - /*cache load*/ opt::copy(ci_array, ci_array + array_size, i_array); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::copy(ci_array, ci_array + array_size, i_array); - } - result = t.elapsed(); - cout << "opt::copy: " << result << endl; - /*cache load*/ std::copy(ci_array, ci_array + array_size, i_array); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - std::copy(ci_array, ci_array + array_size, i_array); - } - result = t.elapsed(); - cout << "std::copy: " << result << endl; - /*cache load*/ opt::detail::copier::template do_copy(ci_array, ci_array + array_size, i_array); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::detail::copier::template do_copy(ci_array, ci_array + array_size, i_array); - } - result = t.elapsed(); - cout << "standard \"unoptimised\" copy: " << result << endl << endl; - - /*cache load*/ opt::copy(cc_array, cc_array + array_size, c_array); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::copy(cc_array, cc_array + array_size, c_array); - } - result = t.elapsed(); - cout << "opt::copy: " << result << endl; - /*cache load*/ std::copy(cc_array, cc_array + array_size, c_array); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - std::copy(cc_array, cc_array + array_size, c_array); - } - result = t.elapsed(); - cout << "std::copy: " << result << endl; - /*cache load*/ opt::detail::copier::template do_copy(cc_array, cc_array + array_size, c_array); - t.restart(); - for(i = 0; i < iter_count; ++i) - { - opt::detail::copier::template do_copy(cc_array, cc_array + array_size, c_array); - } - result = t.elapsed(); - cout << "standard \"unoptimised\" copy: " << result << endl << endl; - - - // - // testing iter_swap - // really just a check that it does in fact compile... - std::vector v1; - v1.push_back(0); - v1.push_back(1); - std::vector v2; - v2.push_back(0); - v2.push_back(1); - opt::iter_swap(v1.begin(), v1.begin()+1); - opt::iter_swap(v2.begin(), v2.begin()+1); - - cout << "Press any key to exit..."; - cin.get(); -} - - - - - - diff --git a/c++_type_traits.htm b/c++_type_traits.htm deleted file mode 100644 index 3cbb786..0000000 --- a/c++_type_traits.htm +++ /dev/null @@ -1,489 +0,0 @@ - - - - - - -C++ Type traits - - - - -

C++ Type traits

-

by John Maddock and Steve Cleary

-

This is a draft of an article that will appear in a future -issue of Dr Dobb's Journal

-

Generic programming (writing code which works with any data type meeting a -set of requirements) has become the method of choice for providing reusable -code. However, there are times in generic programming when "generic" -just isn't good enough - sometimes the differences between types are too large -for an efficient generic implementation. This is when the traits technique -becomes important - by encapsulating those properties that need to be considered -on a type by type basis inside a traits class, we can minimise the amount of -code that has to differ from one type to another, and maximise the amount of -generic code.

-

Consider an example: when working with character strings, one common -operation is to determine the length of a null terminated string. Clearly it's -possible to write generic code that can do this, but it turns out that there are -much more efficient methods available: for example, the C library functions strlen -and wcslen are usually written in -assembler, and with suitable hardware support can be considerably faster than a -generic version written in C++. The authors of the C++ standard library realised -this, and abstracted the properties of char -and wchar_t into the class char_traits. -Generic code that works with character strings can simply use char_traits<>::length -to determine the length of a null terminated string, safe in the knowledge that -specialisations of char_traits will use -the most appropriate method available to them.

-

Type traits

-

Class char_traits is a classic -example of a collection of type specific properties wrapped up in a single class -- what Nathan Myers termed a baggage class[1]. In the Boost type-traits -library, we[2] have written a set of very specific traits classes, each of which -encapsulate a single trait from the C++ type system; for example, is a type a -pointer or a reference type? Or does a type have a trivial constructor, or a -const-qualifier? The type-traits classes share a unified design: each class has -a single member value, a compile-time constant that is true if the type -has the specified property, and false otherwise. As we will show, these classes -can be used in generic programming to determine the properties of a given type -and introduce optimisations that are appropriate for that case.

-

The type-traits library also contains a set of classes that perform a -specific transformation on a type; for example, they can remove a top-level -const or volatile qualifier from a type. Each class that performs a -transformation defines a single typedef-member type that is the result of -the transformation. All of the type-traits classes are defined inside namespace boost; -for brevity, namespace-qualification is omitted in most of the code samples -given.

-

Implementation

-

There are far too many separate classes contained in the type-traits library -to give a full implementation here - see the source code in the Boost library -for the full details - however, most of the implementation is fairly repetitive -anyway, so here we will just give you a flavour for how some of the classes are -implemented. Beginning with possibly the simplest class in the library, is_void<T> -has a member value that is true only if T is void.

-
template <typename T> 
-struct is_void
-{ static const bool value = false; };
-
-template <> 
-struct is_void<void>
-{ static const bool value = true; };
-

Here we define a primary version of the template class is_void, -and provide a full-specialisation when T is void. While full specialisation of a -template class is an important technique, sometimes we need a solution that is -halfway between a fully generic solution, and a full specialisation. This is -exactly the situation for which the standards committee defined partial -template-class specialisation. As an example, consider the class -boost::is_pointer<T>: here we needed a primary version that handles all -the cases where T is not a pointer, and a partial specialisation to handle all -the cases where T is a pointer:

-
template <typename T> 
-struct is_pointer 
-{ static const bool value = false; };
-
-template <typename T> 
-struct is_pointer<T*> 
-{ static const bool value = true; };
-

The syntax for partial specialisation is somewhat arcane and could easily -occupy an article in its own right; like full specialisation, in order to write -a partial specialisation for a class, you must first declare the primary -template. The partial specialisation contains an extra <…> after the -class name that contains the partial specialisation parameters; these define the -types that will bind to that partial specialisation rather than the default -template. The rules for what can appear in a partial specialisation are somewhat -convoluted, but as a rule of thumb if you can legally write two function -overloads of the form:

-
void foo(T);
-void foo(U);
-

Then you can also write a partial specialisation of the form:

-
template <typename T>
-class c{ /*details*/ };
-
-template <typename T>
-
-class c<U>{ /*details*/ };
-

This rule is by no means foolproof, but it is reasonably simple to remember -and close enough to the actual rule to be useful for everyday use.

-

As a more complex example of partial specialisation consider the class -remove_bounds<T>. This class defines a single typedef-member type -that is the same type as T but with any top-level array bounds removed; this is -an example of a traits class that performs a transformation on a type:

-
template <typename T> 
-struct remove_bounds
-{ typedef T type; };
-
-template <typename T, std::size_t N> 
-struct remove_bounds<T[N]>
-{ typedef T type; };
-

The aim of remove_bounds is this: imagine a generic algorithm that is passed -an array type as a template parameter, remove_bounds -provides a means of determining the underlying type of the array. For example remove_bounds<int[4][5]>::type -would evaluate to the type int[5]. This example also shows that the -number of template parameters in a partial specialisation does not have to match -the number in the default template. However, the number of parameters that -appear after the class name do have to match the number and type of the -parameters in the default template.

-

Optimised copy

-

As an example of how the type traits classes can be used, consider the -standard library algorithm copy:

-
template<typename Iter1, typename Iter2>
-Iter2 copy(Iter1 first, Iter1 last, Iter2 out);
-

Obviously, there's no problem writing a generic version of copy that works -for all iterator types Iter1 and Iter2; however, there are some circumstances -when the copy operation can best be performed by a call to memcpy. -In order to implement copy in terms of memcpy -all of the following conditions need to be met:

-
    -
  • Both of the iterator types Iter1 and Iter2 must be pointers.
  • -
  • Both Iter1 and Iter2 must point to the same type - excluding const - and volatile-qualifiers.
  • -
  • The type pointed to by Iter1 must have a trivial assignment operator.
  • -
-

By trivial assignment operator we mean that the type is either a scalar -type[3] or:

-
    -
  • The type has no user defined assignment operator.
  • -
  • The type does not have any data members that are references.
  • -
  • All base classes, and all data member objects must have trivial assignment - operators.
  • -
-

If all these conditions are met then a type can be copied using memcpy -rather than using a compiler generated assignment operator. The type-traits -library provides a class has_trivial_assign, such that has_trivial_assign<T>::value -is true only if T has a trivial assignment operator. This class "just -works" for scalar types, but has to be explicitly specialised for -class/struct types that also happen to have a trivial assignment operator. In -other words if has_trivial_assign gives the wrong answer, it will give -the "safe" wrong answer - that trivial assignment is not allowable.

-

The code for an optimised version of copy that uses memcpy -where appropriate is given in listing 1. The code begins by defining a template -class copier, that takes a single Boolean template parameter, and has a -static template member function do_copy -which performs the generic version of copy (in other words -the "slow but safe version"). Following that there is a specialisation -for copier<true>: again this defines a static template member -function do_copy, but this version uses -memcpy to perform an "optimised" copy.

-

In order to complete the implementation, what we need now is a version of -copy, that calls copier<true>::do_copy if it is safe to use memcpy, -and otherwise calls copier<false>::do_copy to do a -"generic" copy. This is what the version in listing 1 does. To -understand how the code works look at the code for copy -and consider first the two typedefs v1_t and v2_t. These use std::iterator_traits<Iter1>::value_type -to determine what type the two iterators point to, and then feed the result into -another type-traits class remove_cv that removes the top-level -const-volatile-qualifiers: this will allow copy to compare the two types without -regard to const- or volatile-qualifiers. Next, copy -declares an enumerated value can_opt that will become the template -parameter to copier - declaring this here as a constant is really just a -convenience - the value could be passed directly to class copier. -The value of can_opt is computed by verifying that all of the following -are true:

-
    -
  • first that the two iterators point to the same type by using a type-traits - class is_same.
  • -
  • Then that both iterators are real pointers - using the class is_pointer - described above.
  • -
  • Finally that the pointed-to types have a trivial assignment operator using - has_trivial_assign.
  • -
-

Finally we can use the value of can_opt as the template argument to -copier - this version of copy will now adapt to whatever parameters are passed -to it, if its possible to use memcpy, -then it will do so, otherwise it will use a generic copy.

-

Was it worth it?

-

It has often been repeated in these columns that "premature optimisation -is the root of all evil" [4]. So the question must be asked: was our -optimisation premature? To put this in perspective the timings for our version -of copy compared a conventional generic copy[5] are shown in table 1.

-

Clearly the optimisation makes a difference in this case; but, to be fair, -the timings are loaded to exclude cache miss effects - without this accurate -comparison between algorithms becomes difficult. However, perhaps we can add a -couple of caveats to the premature optimisation rule:

-
    -
  • If you use the right algorithm for the job in the first place then - optimisation will not be required; in some cases, memcpy - is the right algorithm.
  • -
  • If a component is going to be reused in many places by many people then - optimisations may well be worthwhile where they would not be so for a single - case - in other words, the likelihood that the optimisation will be - absolutely necessary somewhere, sometime is that much higher. Just as - importantly the perceived value of the stock implementation will be higher: - there is no point standardising an algorithm if users reject it on the - grounds that there are better, more heavily optimised versions available.
  • -
-

Table 1: Time taken to copy 1000 elements using copy<const T*, T*> -(times in micro-seconds)

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

Version

-
-

T

-
-

Time

-
"Optimised" copychar0.99
Conventional copychar8.07
"Optimised" copyint2.52
Conventional copyint8.02
-

 

-

Pair of References

-

The optimised copy example shows how type traits may be used to perform -optimisation decisions at compile-time. Another important usage of type traits -is to allow code to compile that otherwise would not do so unless excessive -partial specialization is used. This is possible by delegating partial -specialization to the type traits classes. Our example for this form of usage is -a pair that can hold references [6].

-

First, let us examine the definition of "std::pair", omitting the -comparision operators, default constructor, and template copy constructor for -simplicity:

-
template <typename T1, typename T2> 
-struct pair 
-{
-  typedef T1 first_type;
-  typedef T2 second_type;
-
-  T1 first;
-  T2 second;
-
-  pair(const T1 & nfirst, const T2 & nsecond)
-  :first(nfirst), second(nsecond) { }
-};
-

Now, this "pair" cannot hold references as it currently stands, -because the constructor would require taking a reference to a reference, which -is currently illegal [7]. Let us consider what the constructor's parameters -would have to be in order to allow "pair" to hold non-reference types, -references, and constant references:

- - - - - - - - - - - - - - - - - -
Type of "T1"Type of parameter to initializing constructor
-
T
-
-
const T &
-
-
T &
-
-
T &
-
-
const T &
-
-
const T &
-
-

A little familiarity with the type traits classes allows us to construct a -single mapping that allows us to determine the type of parameter from the type -of the contained class. The type traits classes provide a transformation "add_reference", -which adds a reference to its type, unless it is already a reference.

- - - - - - - - - - - - - - - - - - - - - -
Type of "T1"Type of "const T1"Type of "add_reference<const - T1>::type"
-
T
-
-
const T
-
-
const T &
-
-
T &
-
-
T & [8]
-
-
T &
-
-
const T &
-
-
const T &
-
-
const T &
-
-

This allows us to build a primary template definition for "pair" -that can contain non-reference types, reference types, and constant reference -types:

-
template <typename T1, typename T2> 
-struct pair 
-{
-  typedef T1 first_type;
-  typedef T2 second_type;
-
-  T1 first;
-  T2 second;
-
-  pair(boost::add_reference<const T1>::type nfirst,
-       boost::add_reference<const T2>::type nsecond)
-  :first(nfirst), second(nsecond) { }
-};
-

Add back in the standard comparision operators, default constructor, and -template copy constructor (which are all the same), and you have a std::pair -that can hold reference types!

-

This same extension could have been done using partial template -specialization of "pair", but to specialize "pair" in this -way would require three partial specializations, plus the primary template. Type -traits allows us to define a single primary template that adjusts itself -auto-magically to any of these partial specializations, instead of a brute-force -partial specialization approach. Using type traits in this fashion allows -programmers to delegate partial specialization to the type traits classes, -resulting in code that is easier to maintain and easier to understand.

-

Conclusion

-

We hope that in this article we have been able to give you some idea of what -type-traits are all about. A more complete listing of the available classes are -in the boost documentation, along with further examples using type traits. -Templates have enabled C++ uses to take the advantage of the code reuse that -generic programming brings; hopefully this article has shown that generic -programming does not have to sink to the lowest common denominator, and that -templates can be optimal as well as generic.

-

Acknowledgements

-

The authors would like to thank Beman Dawes and Howard Hinnant for their -helpful comments when preparing this article.

-

References

-
    -
  1. Nathan C. Myers, C++ Report, June 1995.
  2. -
  3. The type traits library is based upon contributions by Steve Cleary, Beman - Dawes, Howard Hinnant and John Maddock: it can be found at www.boost.org.
  4. -
  5. A scalar type is an arithmetic type (i.e. a built-in integer or floating - point type), an enumeration type, a pointer, a pointer to member, or a - const- or volatile-qualified version of one of these types.
  6. -
  7. This quote is from Donald Knuth, ACM Computing Surveys, December 1974, pg - 268.
  8. -
  9. The test code is available as part of the boost utility library (see - algo_opt_examples.cpp), the code was compiled with gcc 2.95 with all - optimisations turned on, tests were conducted on a 400MHz Pentium II machine - running Microsoft Windows 98.
  10. -
  11. John Maddock and Howard Hinnant have submitted a "compressed_pair" - library to Boost, which uses a technique similar to the one described here - to hold references. Their pair also uses type traits to determine if any of - the types are empty, and will derive instead of contain to conserve space -- - hence the name "compressed".
  12. -
  13. This is actually an issue with the C++ Core Language Working Group (issue - #106), submitted by Bjarne Stroustrup. The tentative resolution is to allow - a "reference to a reference to T" to mean the same thing as a - "reference to T", but only in template instantiation, in a method - similar to multiple cv-qualifiers.
  14. -
  15. For those of you who are wondering why this shouldn't be const-qualified, - remember that references are always implicitly constant (for example, you - can't re-assign a reference). Remember also that "const T &" - is something completely different. For this reason, cv-qualifiers on - template type arguments that are references are ignored.
  16. -
-

Listing 1

-
namespace detail{
-
-template <bool b>
-struct copier
-{
-   template<typename I1, typename I2>
-   static I2 do_copy(I1 first, 
-                     I1 last, I2 out);
-};
-
-template <bool b>
-template<typename I1, typename I2>
-I2 copier<b>::do_copy(I1 first, 
-                      I1 last, 
-                      I2 out)
-{
-   while(first != last)
-   {
-      *out = *first;
-      ++out;
-      ++first;
-   }
-   return out;
-}
-
-template <>
-struct copier<true>
-{
-   template<typename I1, typename I2>
-   static I2* do_copy(I1* first, I1* last, I2* out)
-   {
-      memcpy(out, first, (last-first)*sizeof(I2));
-      return out+(last-first);
-   }
-};
-
-}
-
-template<typename I1, typename I2>
-inline I2 copy(I1 first, I1 last, I2 out)
-{
-   typedef typename 
-    boost::remove_cv<
-     typename std::iterator_traits<I1>
-      ::value_type>::type v1_t;
-
-   typedef typename 
-    boost::remove_cv<
-     typename std::iterator_traits<I2>
-      ::value_type>::type v2_t;
-
-   enum{ can_opt = 
-      boost::is_same<v1_t, v2_t>::value
-      && boost::is_pointer<I1>::value
-      && boost::is_pointer<I2>::value
-      && boost::
-      has_trivial_assign<v1_t>::value 
-   };
-
-   return detail::copier<can_opt>::
-      do_copy(first, last, out);
-}
-
-

© Copyright John Maddock and Steve Cleary, 2000

- - - - diff --git a/call_traits.htm b/call_traits.htm deleted file mode 100644 index 78cb60f..0000000 --- a/call_traits.htm +++ /dev/null @@ -1,754 +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<Operation::second_argument_type, Operation::result_type> 
-{ 
-protected: 
-   Operation op; 
-   Operation::first_argument_type value; 
-public: 
-   binder1st(const Operation& x, const Operation::first_argument_type& y); 
-   Operation::result_type operator()(const 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:

- -
Operation::result_type operator()(call_traits<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 algo_opt_examples.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(call_traits<T>::value_type t);
-};
-
-template <class T>
-void A<T>::foo(call_traits<T>::value_type t)
-{
-   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.egroups.com/list/boost.

- -

.

- -

 

- -

 

- - diff --git a/call_traits_test.cpp b/call_traits_test.cpp deleted file mode 100644 index 0c7155e..0000000 --- a/call_traits_test.cpp +++ /dev/null @@ -1,366 +0,0 @@ - // boost::compressed_pair test program - - // (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and - // distribute this software is granted provided this copyright notice appears - // in all copies. This software is provided "as is" without express or implied - // warranty, and with no claim as to its suitability for any purpose. - -// standalone test program for -// 03 Oct 2000: -// Enabled extra tests for VC6. - -#include -#include -#include -#include -#include -#include - -#include "type_traits_test.hpp" -// -// 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 p){} - -}; - -#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 p){} -}; -#endif - -template -contained::value_type> wrap(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 checker: -// verifies behaviour of contained example: -// -template -struct checker -{ - typedef typename boost::call_traits::param_type param_type; - void operator()(param_type); -}; - -template -void 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()); - - //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; -} - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -struct 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 contained& w, const U& u) -{ - cout << "checking contained<" << typeid(T).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 UDT -{ - int i_; - UDT() : i_(2){} - bool operator == (const UDT& v){ return v.i_ == i_; } -}; - -int main() -{ - checker c1; - UDT u; - c1(u); - checker c2; - int i = 2; - c2(i); - int* pi = &i; -#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) - checker c3; - c3(pi); - checker c4; - c4(i); - checker c5; - c5(i); -#if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - int a[2] = {1,2}; - checker c6; - c6(a); -#endif -#endif - - check_wrap(wrap(2), 2); - const char ca[4] = "abc"; - // compiler can't deduce this for some reason: - //check_wrap(wrap(ca), ca); -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - check_wrap(wrap(a), a); - check_make_pair(test::make_pair(a, a), a, a); -#endif - - // cv-qualifiers applied to reference types should have no effect - // declare these here for later use with is_reference and remove_reference: - typedef int& r_type; - typedef const r_type cr_type; - - type_test(UDT, boost::call_traits::value_type) - type_test(UDT&, boost::call_traits::reference) - type_test(const UDT&, boost::call_traits::const_reference) - type_test(const UDT&, boost::call_traits::param_type) - type_test(int, boost::call_traits::value_type) - type_test(int&, boost::call_traits::reference) - type_test(const int&, boost::call_traits::const_reference) - type_test(const int, boost::call_traits::param_type) - type_test(int*, boost::call_traits::value_type) - type_test(int*&, boost::call_traits::reference) - type_test(int*const&, boost::call_traits::const_reference) - type_test(int*const, boost::call_traits::param_type) -#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) - type_test(int&, boost::call_traits::value_type) - type_test(int&, boost::call_traits::reference) - type_test(const int&, boost::call_traits::const_reference) - type_test(int&, boost::call_traits::param_type) -#if !(defined(__GNUC__) && (__GNUC__ < 3)) - type_test(int&, boost::call_traits::value_type) - type_test(int&, boost::call_traits::reference) - type_test(const int&, boost::call_traits::const_reference) - type_test(int&, boost::call_traits::param_type) -#else - std::cout << "Your compiler cannot instantiate call_traits, skipping four tests (4 errors)" << std::endl; - failures += 4; - test_count += 4; -#endif - type_test(const int&, boost::call_traits::value_type) - type_test(const int&, boost::call_traits::reference) - type_test(const int&, boost::call_traits::const_reference) - type_test(const int&, boost::call_traits::param_type) -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - type_test(const int*, boost::call_traits::value_type) - type_test(int(&)[3], boost::call_traits::reference) - type_test(const int(&)[3], boost::call_traits::const_reference) - type_test(const int*const, boost::call_traits::param_type) - type_test(const int*, boost::call_traits::value_type) - type_test(const int(&)[3], boost::call_traits::reference) - type_test(const int(&)[3], boost::call_traits::const_reference) - type_test(const int*const, boost::call_traits::param_type) -#else - std::cout << "You're compiler does not support partial template instantiation, skipping 8 tests (8 errors)" << std::endl; - failures += 8; - test_count += 8; -#endif -#else - std::cout << "You're compiler does not support partial template instantiation, skipping 20 tests (20 errors)" << std::endl; - failures += 20; - test_count += 20; -#endif - - std::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit"; - std::cin.get(); - return failures; -} - -// -// 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); -} -#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); -} -#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) || !defined(BOOST_NO_MEMBER_TEMPLATES) -template struct call_traits_test; -template struct call_traits_test; -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template struct call_traits_test; -#endif -#endif - diff --git a/compressed_pair.htm b/compressed_pair.htm deleted file mode 100644 index d63af7f..0000000 --- a/compressed_pair.htm +++ /dev/null @@ -1,92 +0,0 @@ - - - - - - -Header <boost/compressed_pair.hpp> - - - - -

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 member 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);
-
-	first_reference       first();
-	first_const_reference first() const;
-
-	second_reference       second();
-	second_const_reference second() const;
-
-	void swap(compressed_pair& y);
-};
- -

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

- -

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

- -

Finally, compressed_pair requires compiler support for partial -specialisation of class templates - without that support -compressed_pair behaves just like std::pair.

- -
- -

Revised 08 March 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.egroups.com/list/boost.

- -

 

- - diff --git a/compressed_pair_test.cpp b/compressed_pair_test.cpp deleted file mode 100644 index 751ab9e..0000000 --- a/compressed_pair_test.cpp +++ /dev/null @@ -1,159 +0,0 @@ - // boost::compressed_pair test program - - // (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and - // distribute this software is granted provided this copyright notice appears - // in all copies. This software is provided "as is" without express or implied - // warranty, and with no claim as to its suitability for any purpose. - -// standalone test program for -// Revised 03 Oct 2000: -// Enabled tests for VC6. - -#include -#include -#include - -#include -#include "type_traits_test.hpp" - -using namespace boost; - -struct empty_POD_UDT{}; -struct empty_UDT -{ - ~empty_UDT(){}; -}; -namespace boost { -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -template <> struct is_empty -{ static const bool value = true; }; -template <> struct is_empty -{ static const bool value = true; }; -template <> struct is_POD -{ static const bool value = true; }; -#else -template <> struct is_empty -{ enum{ value = true }; }; -template <> struct is_empty -{ enum{ value = true }; }; -template <> struct is_POD -{ enum{ value = true }; }; -#endif -} - -struct non_empty1 -{ - int i; - non_empty1() : i(1){} - non_empty1(int v) : i(v){} - friend bool operator==(const non_empty1& a, const non_empty1& b) - { return a.i == b.i; } -}; - -struct non_empty2 -{ - int i; - non_empty2() : i(3){} - non_empty2(int v) : i(v){} - friend bool operator==(const non_empty2& a, const non_empty2& b) - { return a.i == b.i; } -}; - -int main() -{ - compressed_pair cp1(1, 1.3); - assert(cp1.first() == 1); - assert(cp1.second() == 1.3); - compressed_pair cp1b(2, 2.3); - assert(cp1b.first() == 2); - assert(cp1b.second() == 2.3); - swap(cp1, cp1b); - assert(cp1b.first() == 1); - assert(cp1b.second() == 1.3); - assert(cp1.first() == 2); - assert(cp1.second() == 2.3); - compressed_pair cp1c(non_empty1(9)); - assert(cp1c.second() == non_empty2()); - assert(cp1c.first() == non_empty1(9)); - compressed_pair cp1d(non_empty2(9)); - assert(cp1d.second() == non_empty2(9)); - assert(cp1d.first() == non_empty1()); - - compressed_pair cp1e(cp1); - - compressed_pair cp2(2); - assert(cp2.second() == 2); - compressed_pair cp3(1); - assert(cp3.first() ==1); - compressed_pair cp4; - compressed_pair cp5; - compressed_pair cp9(empty_UDT()); - compressed_pair cp10(1); - assert(cp10.first() == 1); -#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) || !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - int i = 0; - compressed_pair cp6(i,i); - assert(cp6.first() == i); - assert(cp6.second() == i); - assert(&cp6.first() == &i); - assert(&cp6.second() == &i); - compressed_pair cp7; - cp7.first(); - double* pd = cp7.second(); -#endif - value_test(true, (sizeof(compressed_pair) < sizeof(std::pair))) - value_test(true, (sizeof(compressed_pair) < sizeof(std::pair))) - value_test(true, (sizeof(compressed_pair) < sizeof(std::pair))) - value_test(true, (sizeof(compressed_pair) < sizeof(std::pair))) - value_test(true, (sizeof(compressed_pair >) < sizeof(std::pair >))) - - std::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit"; - std::cin.get(); - return failures; -} - -// -// instanciate some compressed pairs: -#ifdef __MWERKS__ -template class compressed_pair; -template class compressed_pair; -template class compressed_pair; -template class compressed_pair; -template class compressed_pair; -template class compressed_pair; -#else -template class boost::compressed_pair; -template class boost::compressed_pair; -template class boost::compressed_pair; -template class boost::compressed_pair; -template class boost::compressed_pair; -template class boost::compressed_pair; -#endif - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#ifndef __MWERKS__ -// -// now some for which only a few specific members can be instantiated, -// first references: -template double& compressed_pair::first(); -template int& compressed_pair::second(); -#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)) -template compressed_pair::compressed_pair(int&); -#endif -template compressed_pair::compressed_pair(call_traits::param_type,int&); -// -// and then arrays: -#ifndef __BORLANDC__ -template call_traits::reference compressed_pair::second(); -#endif -template call_traits::reference compressed_pair::first(); -#if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)) -template compressed_pair::compressed_pair(call_traits::param_type); -#endif -template compressed_pair::compressed_pair(); -#endif // __MWERKS__ -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - - - - diff --git a/include/boost/call_traits.hpp b/include/boost/call_traits.hpp deleted file mode 100644 index 345a440..0000000 --- a/include/boost/call_traits.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. -// See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp -// for full copyright notices. - -#ifndef BOOST_CALL_TRAITS_HPP -#define BOOST_CALL_TRAITS_HPP - -#ifndef BOOST_CONFIG_HPP -#include -#endif - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#include -#else -#include -#endif - -#endif // BOOST_CALL_TRAITS_HPP diff --git a/include/boost/compressed_pair.hpp b/include/boost/compressed_pair.hpp deleted file mode 100644 index c55ca2d..0000000 --- a/include/boost/compressed_pair.hpp +++ /dev/null @@ -1,23 +0,0 @@ -// (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. -// See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp -// for full copyright notices. - -#ifndef BOOST_COMPRESSED_PAIR_HPP -#define BOOST_COMPRESSED_PAIR_HPP - -#ifndef BOOST_CONFIG_HPP -#include -#endif - -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#include -#else -#include -#endif - -#endif // BOOST_COMPRESSED_PAIR_HPP diff --git a/include/boost/detail/call_traits.hpp b/include/boost/detail/call_traits.hpp deleted file mode 100644 index 304a686..0000000 --- a/include/boost/detail/call_traits.hpp +++ /dev/null @@ -1,138 +0,0 @@ -// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// call_traits: defines typedefs for function usage -// (see libs/utility/call_traits.htm) - -/* Release notes: - 23rd July 2000: - Fixed array specialization. (JM) - Added Borland specific fixes for reference types - (issue raised by Steve Cleary). -*/ - -#ifndef BOOST_DETAIL_CALL_TRAITS_HPP -#define BOOST_DETAIL_CALL_TRAITS_HPP - -#ifndef BOOST_CONFIG_HPP -#include -#endif - -#ifndef BOOST_TYPE_TRAITS_HPP -#include -#endif - -namespace boost{ - -namespace detail{ - -template -struct ct_imp -{ - typedef const T& param_type; -}; - -template -struct ct_imp -{ - typedef T const param_type; -}; - -template -struct ct_imp -{ - typedef T const param_type; -}; - -} - -template -struct call_traits -{ -public: - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - // - // C++ Builder workaround: we should be able to define a compile time - // constant and pass that as a single template parameter to ct_imp, - // however compiler bugs prevent this - instead pass three bool's to - // ct_imp and add an extra partial specialisation - // of ct_imp to handle the logic. (JM) - typedef typename detail::ct_imp::type>::value, ::boost::is_arithmetic::type>::value, sizeof(T) <= sizeof(void*)>::param_type param_type; -}; - -template -struct call_traits -{ - typedef T& value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T& param_type; // hh removed const -}; - -#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x551) -// these are illegal specialisations; cv-qualifies applied to -// references have no effect according to [8.3.2p1], -// C++ Builder requires them though as it treats cv-qualified -// references as distinct types... -template -struct call_traits -{ - typedef T& value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T& param_type; // hh removed const -}; -template -struct call_traits -{ - typedef T& value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T& param_type; // hh removed const -}; -template -struct call_traits -{ - typedef T& value_type; - typedef T& reference; - typedef const T& const_reference; - typedef T& param_type; // hh removed const -}; -#endif - -template -struct call_traits -{ -private: - typedef T array_type[N]; -public: - // degrades array to pointer: - typedef const T* value_type; - typedef array_type& reference; - typedef const array_type& const_reference; - typedef const T* const param_type; -}; - -template -struct call_traits -{ -private: - typedef const T array_type[N]; -public: - // degrades array to pointer: - typedef const T* value_type; - typedef array_type& reference; - typedef const array_type& const_reference; - typedef const T* const param_type; -}; - -} - -#endif // BOOST_DETAIL_CALL_TRAITS_HPP diff --git a/include/boost/detail/compressed_pair.hpp b/include/boost/detail/compressed_pair.hpp deleted file mode 100644 index c2b9bef..0000000 --- a/include/boost/detail/compressed_pair.hpp +++ /dev/null @@ -1,424 +0,0 @@ -// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// compressed_pair: pair that "compresses" empty members -// (see libs/utility/compressed_pair.htm) -// -// JM changes 25 Jan 2000: -// Removed default arguments from compressed_pair_switch to get -// C++ Builder 4 to accept them -// rewriten swap to get gcc and C++ builder to compile. -// added partial specialisations for case T1 == T2 to avoid duplicate constructor defs. - -#ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP -#define BOOST_DETAIL_COMPRESSED_PAIR_HPP - -#include -#ifndef BOOST_TYPE_TRAITS_HPP -#include -#endif -#ifndef BOOST_CALL_TRAITS_HPP -#include -#endif - -namespace boost -{ - -// compressed_pair - -namespace details -{ - // JM altered 26 Jan 2000: - template - struct compressed_pair_switch; - - template - struct compressed_pair_switch - {static const int value = 0;}; - - template - struct compressed_pair_switch - {static const int value = 3;}; - - template - struct compressed_pair_switch - {static const int value = 1;}; - - template - struct compressed_pair_switch - {static const int value = 2;}; - - template - struct compressed_pair_switch - {static const int value = 4;}; - - template - struct compressed_pair_switch - {static const int value = 5;}; - - template class compressed_pair_imp; - -#ifdef __GNUC__ - // workaround for GCC (JM): - using std::swap; -#endif - // - // can't call unqualified swap from within classname::swap - // as Koenig lookup rules will find only the classname::swap - // member function not the global declaration, so use cp_swap - // as a forwarding function (JM): - template - inline void cp_swap(T& t1, T& t2) - { -#ifndef __GNUC__ - using std::swap; -#endif - swap(t1, t2); - } - - // 0 derive from neither - - template - class compressed_pair_imp - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair_imp() {} - - compressed_pair_imp(first_param_type x, second_param_type y) - : first_(x), second_(y) {} - - explicit compressed_pair_imp(first_param_type x) - : first_(x) {} - - explicit compressed_pair_imp(second_param_type y) - : second_(y) {} - - first_reference first() {return first_;} - first_const_reference first() const {return first_;} - - second_reference second() {return second_;} - second_const_reference second() const {return second_;} - - void swap(compressed_pair_imp& y) - { - cp_swap(first_, y.first_); - cp_swap(second_, y.second_); - } - private: - first_type first_; - second_type second_; - }; - - // 1 derive from T1 - - template - class compressed_pair_imp - : private T1 - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair_imp() {} - - compressed_pair_imp(first_param_type x, second_param_type y) - : first_type(x), second_(y) {} - - explicit compressed_pair_imp(first_param_type x) - : first_type(x) {} - - explicit compressed_pair_imp(second_param_type y) - : second_(y) {} - - first_reference first() {return *this;} - first_const_reference first() const {return *this;} - - second_reference second() {return second_;} - second_const_reference second() const {return second_;} - - void swap(compressed_pair_imp& y) - { - // no need to swap empty base class: - cp_swap(second_, y.second_); - } - private: - second_type second_; - }; - - // 2 derive from T2 - - template - class compressed_pair_imp - : private T2 - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair_imp() {} - - compressed_pair_imp(first_param_type x, second_param_type y) - : second_type(y), first_(x) {} - - explicit compressed_pair_imp(first_param_type x) - : first_(x) {} - - explicit compressed_pair_imp(second_param_type y) - : second_type(y) {} - - first_reference first() {return first_;} - first_const_reference first() const {return first_;} - - second_reference second() {return *this;} - second_const_reference second() const {return *this;} - - void swap(compressed_pair_imp& y) - { - // no need to swap empty base class: - cp_swap(first_, y.first_); - } - - private: - first_type first_; - }; - - // 3 derive from T1 and T2 - - template - class compressed_pair_imp - : private T1, - private T2 - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair_imp() {} - - compressed_pair_imp(first_param_type x, second_param_type y) - : first_type(x), second_type(y) {} - - explicit compressed_pair_imp(first_param_type x) - : first_type(x) {} - - explicit compressed_pair_imp(second_param_type y) - : second_type(y) {} - - first_reference first() {return *this;} - first_const_reference first() const {return *this;} - - second_reference second() {return *this;} - second_const_reference second() const {return *this;} - // - // no need to swap empty bases: - void swap(compressed_pair_imp&) {} - }; - - // JM - // 4 T1 == T2, T1 and T2 both empty - // Note does not actually store an instance of T2 at all - - // but reuses T1 base class for both first() and second(). - template - class compressed_pair_imp - : private T1 - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair_imp() {} - - compressed_pair_imp(first_param_type x, second_param_type) - : first_type(x) {} - - explicit compressed_pair_imp(first_param_type x) - : first_type(x) {} - - first_reference first() {return *this;} - first_const_reference first() const {return *this;} - - second_reference second() {return *this;} - second_const_reference second() const {return *this;} - - void swap(compressed_pair_imp&) {} - private: - }; - - // 5 T1 == T2 and are not empty: //JM - - template - class compressed_pair_imp - { - public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair_imp() {} - - compressed_pair_imp(first_param_type x, second_param_type y) - : first_(x), second_(y) {} - - explicit compressed_pair_imp(first_param_type x) - : first_(x), second_(x) {} - - first_reference first() {return first_;} - first_const_reference first() const {return first_;} - - second_reference second() {return second_;} - second_const_reference second() const {return second_;} - - void swap(compressed_pair_imp& y) - { - cp_swap(first_, y.first_); - cp_swap(second_, y.second_); - } - private: - first_type first_; - second_type second_; - }; - -} // details - -template -class compressed_pair - : private ::boost::details::compressed_pair_imp::type, typename remove_cv::type>::value, - ::boost::is_empty::value, - ::boost::is_empty::value>::value> -{ -private: - typedef details::compressed_pair_imp::type, typename remove_cv::type>::value, - ::boost::is_empty::value, - ::boost::is_empty::value>::value> base; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair() : base() {} - compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} - explicit compressed_pair(first_param_type x) : base(x) {} - explicit compressed_pair(second_param_type y) : base(y) {} - - first_reference first() {return base::first();} - first_const_reference first() const {return base::first();} - - second_reference second() {return base::second();} - second_const_reference second() const {return base::second();} - - void swap(compressed_pair& y) { base::swap(y); } -}; - -// JM -// Partial specialisation for case where T1 == T2: -// -template -class compressed_pair - : private details::compressed_pair_imp::type, typename remove_cv::type>::value, - ::boost::is_empty::value, - ::boost::is_empty::value>::value> -{ -private: - typedef details::compressed_pair_imp::type, typename remove_cv::type>::value, - ::boost::is_empty::value, - ::boost::is_empty::value>::value> base; -public: - typedef T first_type; - typedef T second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair() : base() {} - compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} - explicit compressed_pair(first_param_type x) : base(x) {} - - first_reference first() {return base::first();} - first_const_reference first() const {return base::first();} - - second_reference second() {return base::second();} - second_const_reference second() const {return base::second();} - - void swap(compressed_pair& y) { base::swap(y); } -}; - -template -inline -void -swap(compressed_pair& x, compressed_pair& y) -{ - x.swap(y); -} - -} // boost - -#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP - - diff --git a/include/boost/detail/ob_call_traits.hpp b/include/boost/detail/ob_call_traits.hpp deleted file mode 100644 index a031f17..0000000 --- a/include/boost/detail/ob_call_traits.hpp +++ /dev/null @@ -1,125 +0,0 @@ -// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. -// -// Crippled version for crippled compilers: -// see libs/utility/call_traits.htm -// - -/* Release notes: - 01st October 2000: - Fixed call_traits on VC6, using "poor man's partial specialisation", - using ideas taken from "Generative programming" by Krzysztof Czarnecki - & Ulrich Eisenecker. -*/ - -#ifndef BOOST_OB_CALL_TRAITS_HPP -#define BOOST_OB_CALL_TRAITS_HPP - -#ifndef BOOST_CONFIG_HPP -#include -#endif - -#ifndef BOOST_TYPE_TRAITS_HPP -#include -#endif - -namespace boost{ - -#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) -// -// use member templates to emulate -// partial specialisation: -// -namespace detail{ - -template -struct standard_call_traits -{ - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef const T& param_type; -}; -template -struct simple_call_traits -{ - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef const T param_type; -}; -template -struct reference_call_traits -{ - typedef T value_type; - typedef T reference; - typedef T const_reference; - typedef T param_type; -}; -template -struct call_traits_chooser -{ - template - struct rebind - { - typedef standard_call_traits type; - }; -}; -template <> -struct call_traits_chooser -{ - template - struct rebind - { - typedef simple_call_traits type; - }; -}; -template <> -struct call_traits_chooser -{ - template - struct rebind - { - typedef reference_call_traits type; - }; -}; -} // namespace detail -template -struct call_traits -{ -private: - typedef detail::call_traits_chooser<(is_pointer::value || is_arithmetic::value) && sizeof(T) <= sizeof(void*), is_reference::value> chooser; - typedef typename chooser::template rebind bound_type; - typedef typename bound_type::type call_traits_type; -public: - typedef typename call_traits_type::value_type value_type; - typedef typename call_traits_type::reference reference; - typedef typename call_traits_type::const_reference const_reference; - typedef typename call_traits_type::param_type param_type; -}; - -#else -// -// sorry call_traits is completely non-functional -// blame your broken compiler: -// - -template -struct call_traits -{ - typedef T value_type; - typedef T& reference; - typedef const T& const_reference; - typedef const T& param_type; -}; - -#endif // member templates - -} - -#endif // BOOST_OB_CALL_TRAITS_HPP diff --git a/include/boost/detail/ob_compressed_pair.hpp b/include/boost/detail/ob_compressed_pair.hpp deleted file mode 100644 index 7f02a04..0000000 --- a/include/boost/detail/ob_compressed_pair.hpp +++ /dev/null @@ -1,474 +0,0 @@ -// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. -// see libs/utility/compressed_pair.hpp -// -/* Release notes: - 20 Jan 2001: - Fixed obvious bugs (David Abrahams) - 07 Oct 2000: - Added better single argument constructor support. - 03 Oct 2000: - Added VC6 support (JM). - 23rd July 2000: - Additional comments added. (JM) - Jan 2000: - Original version: this version crippled for use with crippled compilers - - John Maddock Jan 2000. -*/ - - -#ifndef BOOST_OB_COMPRESSED_PAIR_HPP -#define BOOST_OB_COMPRESSED_PAIR_HPP - -#include -#ifndef BOOST_TYPE_TRAITS_HPP -#include -#endif -#ifndef BOOST_CALL_TRAITS_HPP -#include -#endif - -namespace boost -{ -#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) -// -// use member templates to emulate -// partial specialisation. Note that due to -// problems with overload resolution with VC6 -// each of the compressed_pair versions that follow -// have one template single-argument constructor -// in place of two specific constructors: -// - -template -class compressed_pair; - -namespace detail{ - -template -struct best_conversion_traits -{ - typedef char one; - typedef char (&two)[2]; - static A a; - static one test(T1); - static two test(T2); - - enum { value = sizeof(test(a)) }; -}; - -template -struct init_one; - -template <> -struct init_one<1> -{ - template - static void init(const A& a, T1* p1, T2*) - { - *p1 = a; - } -}; - -template <> -struct init_one<2> -{ - template - static void init(const A& a, T1*, T2* p2) - { - *p2 = a; - } -}; - - -// T1 != T2, both non-empty -template -class compressed_pair_0 -{ -private: - T1 _first; - T2 _second; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair_0() : _first(), _second() {} - compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {} - template - explicit compressed_pair_0(const A& val) - { - init_one::value>::init(val, &_first, &_second); - } - compressed_pair_0(const ::boost::compressed_pair& x) - : _first(x.first()), _second(x.second()) {} - - first_reference first() { return _first; } - first_const_reference first() const { return _first; } - - second_reference second() { return _second; } - second_const_reference second() const { return _second; } - - void swap(compressed_pair_0& y) - { - using std::swap; - swap(_first, y._first); - swap(_second, y._second); - } -}; - -// T1 != T2, T2 empty -template -class compressed_pair_1 : T2 -{ -private: - T1 _first; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair_1() : T2(), _first() {} - compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {} - template - explicit compressed_pair_1(const A& val) - { - init_one::value>::init(val, &_first, static_cast(this)); - } - compressed_pair_1(const ::boost::compressed_pair& x) - : T2(x.second()), _first(x.first()) {} - - first_reference first() { return _first; } - first_const_reference first() const { return _first; } - - second_reference second() { return *this; } - second_const_reference second() const { return *this; } - - void swap(compressed_pair_1& y) - { - // no need to swap empty base class: - using std::swap; - swap(_first, y._first); - } -}; - -// T1 != T2, T1 empty -template -class compressed_pair_2 : T1 -{ -private: - T2 _second; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair_2() : T1(), _second() {} - compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {} - template - explicit compressed_pair_2(const A& val) - { - init_one::value>::init(val, static_cast(this), &_second); - } - compressed_pair_2(const ::boost::compressed_pair& x) - : T1(x.first()), _second(x.second()) {} - - first_reference first() { return *this; } - first_const_reference first() const { return *this; } - - second_reference second() { return _second; } - second_const_reference second() const { return _second; } - - void swap(compressed_pair_2& y) - { - // no need to swap empty base class: - using std::swap; - swap(_second, y._second); - } -}; - -// T1 != T2, both empty -template -class compressed_pair_3 : T1, T2 -{ -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair_3() : T1(), T2() {} - compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {} - template - explicit compressed_pair_3(const A& val) - { - init_one::value>::init(val, static_cast(this), static_cast(this)); - } - compressed_pair_3(const ::boost::compressed_pair& x) - : T1(x.first()), T2(x.second()) {} - - first_reference first() { return *this; } - first_const_reference first() const { return *this; } - - second_reference second() { return *this; } - second_const_reference second() const { return *this; } - - void swap(compressed_pair_3& y) - { - // no need to swap empty base classes: - } -}; - -// T1 == T2, and empty -template -class compressed_pair_4 : T1 -{ -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair_4() : T1() {} - compressed_pair_4(first_param_type x, second_param_type) : T1(x) {} - // only one single argument constructor since T1 == T2 - explicit compressed_pair_4(first_param_type x) : T1(x) {} - compressed_pair_4(const ::boost::compressed_pair& x) - : T1(x.first()){} - - first_reference first() { return *this; } - first_const_reference first() const { return *this; } - - second_reference second() { return *this; } - second_const_reference second() const { return *this; } - - void swap(compressed_pair_4& y) - { - // no need to swap empty base classes: - } -}; - -// T1 == T2, not empty -template -class compressed_pair_5 -{ -private: - T1 _first; - T2 _second; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair_5() : _first(), _second() {} - compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {} - // only one single argument constructor since T1 == T2 - explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {} - compressed_pair_5(const ::boost::compressed_pair& c) - : _first(c.first()), _second(c.second()) {} - - first_reference first() { return _first; } - first_const_reference first() const { return _first; } - - second_reference second() { return _second; } - second_const_reference second() const { return _second; } - - void swap(compressed_pair_5& y) - { - using std::swap; - swap(_first, y._first); - swap(_second, y._second); - } -}; - -template -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_0 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_1 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_2 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_3 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_4 type; - }; -}; - -template <> -struct compressed_pair_chooser -{ - template - struct rebind - { - typedef compressed_pair_5 type; - }; -}; - -template -struct compressed_pair_traits -{ -private: - typedef compressed_pair_chooser::value, is_empty::value, is_same::value> chooser; - typedef typename chooser::template rebind bound_type; -public: - typedef typename bound_type::type type; -}; - -} // namespace detail - -template -class compressed_pair : public detail::compressed_pair_traits::type -{ -private: - typedef typename detail::compressed_pair_traits::type base_type; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair() : base_type() {} - compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {} - template - explicit compressed_pair(const A& x) : base_type(x){} - - first_reference first() { return base_type::first(); } - first_const_reference first() const { return base_type::first(); } - - second_reference second() { return base_type::second(); } - second_const_reference second() const { return base_type::second(); } -}; - -template -inline void swap(compressed_pair& x, compressed_pair& y) -{ - x.swap(y); -} - -#else -// no partial specialisation, no member templates: - -template -class compressed_pair -{ -private: - T1 _first; - T2 _second; -public: - typedef T1 first_type; - typedef T2 second_type; - typedef typename call_traits::param_type first_param_type; - typedef typename call_traits::param_type second_param_type; - typedef typename call_traits::reference first_reference; - typedef typename call_traits::reference second_reference; - typedef typename call_traits::const_reference first_const_reference; - typedef typename call_traits::const_reference second_const_reference; - - compressed_pair() : _first(), _second() {} - compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {} - explicit compressed_pair(first_param_type x) : _first(x), _second() {} - // can't define this in case T1 == T2: - // explicit compressed_pair(second_param_type y) : _first(), _second(y) {} - - first_reference first() { return _first; } - first_const_reference first() const { return _first; } - - second_reference second() { return _second; } - second_const_reference second() const { return _second; } - - void swap(compressed_pair& y) - { - using std::swap; - swap(_first, y._first); - swap(_second, y._second); - } -}; - -template -inline void swap(compressed_pair& x, compressed_pair& y) -{ - x.swap(y); -} - -#endif - -} // boost - -#endif // BOOST_OB_COMPRESSED_PAIR_HPP - - - diff --git a/include/boost/operators.hpp b/include/boost/operators.hpp deleted file mode 100644 index 482a25a..0000000 --- a/include/boost/operators.hpp +++ /dev/null @@ -1,563 +0,0 @@ -// Boost operators.hpp header file ----------------------------------------// - -// (C) Copyright David Abrahams 1999. Permission to copy, use, -// modify, sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 04 Jul 00 Fixed NO_OPERATORS_IN_NAMESPACE bugs, major cleanup and -// refactoring of compiler workarounds, additional documentation -// (Alexy Gurtovoy and Mark Rodgers with some help and prompting from -// Dave Abrahams) -// 28 Jun 00 General cleanup and integration of bugfixes from Mark Rodgers and -// Jeremy Siek (Dave Abrahams) -// 20 Jun 00 Changes to accommodate Borland C++Builder 4 and Borland C++ 5.5 -// (Mark Rodgers) -// 20 Jun 00 Minor fixes to the prior revision (Aleksey Gurtovoy) -// 10 Jun 00 Support for the base class chaining technique was added -// (Aleksey Gurtovoy). See documentation and the comments below -// for the details. -// 12 Dec 99 Initial version with iterator operators (Jeremy Siek) -// 18 Nov 99 Change name "divideable" to "dividable", remove unnecessary -// specializations of dividable, subtractable, modable (Ed Brey) -// 17 Nov 99 Add comments (Beman Dawes) -// Remove unnecessary specialization of operators<> (Ed Brey) -// 15 Nov 99 Fix less_than_comparable second operand type for first two -// operators.(Beman Dawes) -// 12 Nov 99 Add operators templates (Ed Brey) -// 11 Nov 99 Add single template parameter version for compilers without -// partial specialization (Beman Dawes) -// 10 Nov 99 Initial version - -// 10 Jun 00: -// An additional optional template parameter was added to most of -// operator templates to support the base class chaining technique (see -// documentation for the details). Unfortunately, a straightforward -// implementation of this change would have broken compatibility with the -// previous version of the library by making it impossible to use the same -// template name (e.g. 'addable') for both the 1- and 2-argument versions of -// an operator template. This implementation solves the backward-compatibility -// issue at the cost of some simplicity. -// -// One of the complications is an existence of special auxiliary class template -// 'is_chained_base<>' (see 'detail' namespace below), which is used -// to determine whether its template parameter is a library's operator template -// or not. You have to specialize 'is_chained_base<>' for each new -// operator template you add to the library. -// -// However, most of the non-trivial implementation details are hidden behind -// several local macros defined below, and as soon as you understand them, -// you understand the whole library implementation. - -#ifndef BOOST_OPERATORS_HPP -#define BOOST_OPERATORS_HPP - -#include -#include - -#if defined(__sgi) && !defined(__GNUC__) -#pragma set woff 1234 -#endif - -#if defined(BOOST_MSVC) -# pragma warning( disable : 4284 ) // complaint about return type of -#endif // operator-> not begin a UDT - -namespace boost { -namespace detail { - -class empty_base {}; - -} // namespace detail -} // namespace boost - -// In this section we supply the xxxx1 and xxxx2 forms of the operator -// templates, which are explicitly targeted at the 1-type-argument and -// 2-type-argument operator forms, respectively. Some compilers get confused -// when inline friend functions are overloaded in namespaces other than the -// global namespace. When BOOST_NO_OPERATORS_IN_NAMESPACE is defined, all of -// these templates must go in the global namespace. - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE -namespace boost -{ -#endif - -// Basic operator classes (contributed by Dave Abrahams) ------------------// - -// Note that friend functions defined in a class are implicitly inline. -// See the C++ std, 11.4 [class.friend] paragraph 5 - -template -struct less_than_comparable2 : B -{ - friend bool operator<=(const T& x, const U& y) { return !(x > y); } - friend bool operator>=(const T& x, const U& y) { return !(x < y); } - friend bool operator>(const U& x, const T& y) { return y < x; } - friend bool operator<(const U& x, const T& y) { return y > x; } - friend bool operator<=(const U& x, const T& y) { return !(y < x); } - friend bool operator>=(const U& x, const T& y) { return !(y > x); } -}; - -template -struct less_than_comparable1 : B -{ - friend bool operator>(const T& x, const T& y) { return y < x; } - friend bool operator<=(const T& x, const T& y) { return !(y < x); } - friend bool operator>=(const T& x, const T& y) { return !(x < y); } -}; - -template -struct equality_comparable2 : B -{ - friend bool operator==(const U& y, const T& x) { return x == y; } - friend bool operator!=(const U& y, const T& x) { return !(x == y); } - friend bool operator!=(const T& y, const U& x) { return !(y == x); } -}; - -template -struct equality_comparable1 : B -{ - friend bool operator!=(const T& x, const T& y) { return !(x == y); } -}; - -template -struct multipliable2 : B -{ - friend T operator*(T x, const U& y) { return x *= y; } - friend T operator*(const U& y, T x) { return x *= y; } -}; - -template -struct multipliable1 : B -{ - friend T operator*(T x, const T& y) { return x *= y; } -}; - -template -struct addable2 : B -{ - friend T operator+(T x, const U& y) { return x += y; } - friend T operator+(const U& y, T x) { return x += y; } -}; - -template -struct addable1 : B -{ - friend T operator+(T x, const T& y) { return x += y; } -}; - -template -struct subtractable2 : B -{ - friend T operator-(T x, const U& y) { return x -= y; } -}; - -template -struct subtractable1 : B -{ - friend T operator-(T x, const T& y) { return x -= y; } -}; - -template -struct dividable2 : B -{ - friend T operator/(T x, const U& y) { return x /= y; } -}; - -template -struct dividable1 : B -{ - friend T operator/(T x, const T& y) { return x /= y; } -}; - -template -struct modable2 : B -{ - friend T operator%(T x, const U& y) { return x %= y; } -}; - -template -struct modable1 : B -{ - friend T operator%(T x, const T& y) { return x %= y; } -}; - -template -struct xorable2 : B -{ - friend T operator^(T x, const U& y) { return x ^= y; } - friend T operator^(const U& y, T x) { return x ^= y; } -}; - -template -struct xorable1 : B -{ - friend T operator^(T x, const T& y) { return x ^= y; } -}; - -template -struct andable2 : B -{ - friend T operator&(T x, const U& y) { return x &= y; } - friend T operator&(const U& y, T x) { return x &= y; } -}; - -template -struct andable1 : B -{ - friend T operator&(T x, const T& y) { return x &= y; } -}; - -template -struct orable2 : B -{ - friend T operator|(T x, const U& y) { return x |= y; } - friend T operator|(const U& y, T x) { return x |= y; } -}; - -template -struct orable1 : B -{ - friend T operator|(T x, const T& y) { return x |= y; } -}; - -// incrementable and decrementable contributed by Jeremy Siek - -template -struct incrementable : B -{ - friend T operator++(T& x, int) - { - incrementable_type tmp(x); - ++x; - return tmp; - } -private: // The use of this typedef works around a Borland bug - typedef T incrementable_type; -}; - -template -struct decrementable : B -{ - friend T operator--(T& x, int) - { - decrementable_type tmp(x); - --x; - return tmp; - } -private: // The use of this typedef works around a Borland bug - typedef T decrementable_type; -}; - -// Iterator operator classes (contributed by Jeremy Siek) ------------------// - -template -struct dereferenceable : B -{ - P operator->() const - { - return &*static_cast(*this); - } -}; - -template -struct indexable : B -{ - R operator[](I n) const - { - return *(static_cast(*this) + n); - } -}; - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE -} // namespace boost -#endif // BOOST_NO_OPERATORS_IN_NAMESPACE - - -// BOOST_IMPORT_TEMPLATE1/BOOST_IMPORT_TEMPLATE2 - -// -// When BOOST_NO_OPERATORS_IN_NAMESPACE is defined we need a way to import an -// operator template into the boost namespace. BOOST_IMPORT_TEMPLATE1 is used -// for one-argument forms of operator templates; BOOST_IMPORT_TEMPLATE2 for -// two-argument forms. Note that these macros expect to be invoked from within -// boost. - -#if defined(BOOST_NO_OPERATORS_IN_NAMESPACE) - -# if defined(BOOST_NO_USING_TEMPLATE) - - // Because a Borland C++ 5.5 bug prevents a using declaration from working, - // we are forced to use inheritance for that compiler. -# define BOOST_IMPORT_TEMPLATE2(template_name) \ - template \ - struct template_name : ::template_name {}; - -# define BOOST_IMPORT_TEMPLATE1(template_name) \ - template \ - struct template_name : ::template_name {}; - -# else - - // Otherwise, bring the names in with a using-declaration to avoid - // stressing the compiler -# define BOOST_IMPORT_TEMPLATE2(template_name) using ::template_name; -# define BOOST_IMPORT_TEMPLATE1(template_name) using ::template_name; - -# endif // BOOST_NO_USING_TEMPLATE - -#else // !BOOST_NO_OPERATORS_IN_NAMESPACE - - // The template is already in boost so we have nothing to do. -# define BOOST_IMPORT_TEMPLATE2(template_name) -# define BOOST_IMPORT_TEMPLATE1(template_name) - -#endif // BOOST_NO_OPERATORS_IN_NAMESPACE - -// -// Here's where we put it all together, defining the xxxx forms of the templates -// in namespace boost. We also define specializations of is_chained_base<> for -// the xxxx, xxxx1, and xxxx2 templates, importing them into boost:: as -// neccessary. -// -#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - -// is_chained_base<> - a traits class used to distinguish whether an operator -// template argument is being used for base class chaining, or is specifying a -// 2nd argument type. - -namespace boost { -// A type parameter is used instead of a plain bool because Borland's compiler -// didn't cope well with the more obvious non-type template parameter. -namespace detail { - struct true_t {}; - struct false_t {}; -} // namespace detail - -// Unspecialized version assumes that most types are not being used for base -// class chaining. We specialize for the operator templates defined in this -// library. -template struct is_chained_base { - typedef ::boost::detail::false_t value; -}; - -} // namespace boost - -// Import a 2-type-argument operator template into boost (if neccessary) and -// provide a specialization of 'is_chained_base<>' for it. -# define BOOST_OPERATOR_TEMPLATE2(template_name2) \ - BOOST_IMPORT_TEMPLATE2(template_name2) \ - template \ - struct is_chained_base< ::boost::template_name2 > { \ - typedef ::boost::detail::true_t value; \ - }; - -// Import a 1-type-argument operator template into boost (if neccessary) and -// provide a specialization of 'is_chained_base<>' for it. -# define BOOST_OPERATOR_TEMPLATE1(template_name1) \ - BOOST_IMPORT_TEMPLATE1(template_name1) \ - template \ - struct is_chained_base< ::boost::template_name1 > { \ - typedef ::boost::detail::true_t value; \ - }; - -// BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it -// can be used for specifying both 1-argument and 2-argument forms. Requires the -// existence of two previously defined class templates named '1' -// and '2' which must implement the corresponding 1- and 2- -// argument forms. -// -// The template type parameter O == is_chained_base::value is used to -// distinguish whether the 2nd argument to is being used for -// base class chaining from another boost operator template or is describing a -// 2nd operand type. O == true_t only when U is actually an another operator -// template from the library. Partial specialization is used to select an -// implementation in terms of either '1' or '2'. -// - -# define BOOST_OPERATOR_TEMPLATE(template_name) \ -template ::value \ - > \ -struct template_name : template_name##2 {}; \ - \ -template \ -struct template_name \ - : template_name##1 {}; \ - \ -template \ -struct template_name \ - : template_name##1 {}; \ - \ -template \ -struct is_chained_base< ::boost::template_name > { \ - typedef ::boost::detail::true_t value; \ -}; \ - \ -BOOST_OPERATOR_TEMPLATE2(template_name##2) \ -BOOST_OPERATOR_TEMPLATE1(template_name##1) - - -#else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -# define BOOST_OPERATOR_TEMPLATE2(template_name2) \ - BOOST_IMPORT_TEMPLATE2(template_name2) -# define BOOST_OPERATOR_TEMPLATE1(template_name1) \ - BOOST_IMPORT_TEMPLATE1(template_name1) - - // In this case we can only assume that template_name<> is equivalent to the - // more commonly needed template_name1<> form. -# define BOOST_OPERATOR_TEMPLATE(template_name) \ - template \ - struct template_name : template_name##1 {}; - -#endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - -namespace boost { - -BOOST_OPERATOR_TEMPLATE(less_than_comparable) -BOOST_OPERATOR_TEMPLATE(equality_comparable) -BOOST_OPERATOR_TEMPLATE(multipliable) -BOOST_OPERATOR_TEMPLATE(addable) -BOOST_OPERATOR_TEMPLATE(subtractable) -BOOST_OPERATOR_TEMPLATE(dividable) -BOOST_OPERATOR_TEMPLATE(modable) -BOOST_OPERATOR_TEMPLATE(xorable) -BOOST_OPERATOR_TEMPLATE(andable) -BOOST_OPERATOR_TEMPLATE(orable) - -BOOST_OPERATOR_TEMPLATE1(incrementable) -BOOST_OPERATOR_TEMPLATE1(decrementable) -BOOST_OPERATOR_TEMPLATE2(dereferenceable) - -// indexable doesn't follow the patterns above (it has 4 template arguments), so -// we just write out the compiler hacks explicitly. -#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE -# ifdef BOOST_NO_USING_TEMPLATE - template - struct indexable : ::indexable {}; -# else - using ::indexable; -# endif -#endif - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -struct is_chained_base< ::boost::indexable > { - typedef ::boost::detail::true_t operator_template_type; -}; -#endif - -#undef BOOST_OPERATOR_TEMPLATE -#undef BOOST_OPERATOR_TEMPLATE2 -#undef BOOST_OPERATOR_TEMPLATE1 -#undef BOOST_IMPORT_TEMPLATE1 -#undef BOOST_IMPORT_TEMPLATE2 - -// The following 'operators' classes can only be used portably if the derived class -// declares ALL of the required member operators. -template -struct operators2 - : less_than_comparable2 > > > > > > > > > {}; - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -struct operators : operators2 {}; - -template struct operators -#else -template struct operators -#endif - : less_than_comparable > > > > > > > > > > > {}; - -// Iterator helper classes (contributed by Jeremy Siek) -------------------// -template -struct forward_iterator_helper - : equality_comparable > > > {}; - -template -struct bidirectional_iterator_helper - : equality_comparable > > > > {}; - -template -struct random_access_iterator_helper - : equality_comparable > > > > > > > > -{ -#ifndef __BORLANDC__ - friend D requires_difference_operator(const T& x, const T& y) { - return x - y; - } -#endif -}; // random_access_iterator_helper - -} // namespace boost - -#if defined(__sgi) && !defined(__GNUC__) -#pragma reset woff 1234 -#endif - -#endif // BOOST_OPERATORS_HPP diff --git a/include/boost/utility.hpp b/include/boost/utility.hpp deleted file mode 100644 index 82a7d13..0000000 --- a/include/boost/utility.hpp +++ /dev/null @@ -1,96 +0,0 @@ -// boost utility.hpp header file -------------------------------------------// - -// (C) Copyright boost.org 1999. Permission to copy, use, modify, sell -// and distribute this software is granted provided this copyright -// notice appears in all copies. This software is provided "as is" without -// express or implied warranty, and with no claim as to its suitability for -// any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Classes appear in alphabetical order - -// Revision History -// 26 Jan 00 protected noncopyable destructor added (Miki Jovanovic) -// 10 Dec 99 next() and prior() templates added (Dave Abrahams) -// 30 Aug 99 moved cast templates to cast.hpp (Beman Dawes) -// 3 Aug 99 cast templates added -// 20 Jul 99 name changed to utility.hpp -// 9 Jun 99 protected noncopyable default ctor -// 2 Jun 99 Initial Version. Class noncopyable only contents (Dave Abrahams) - -#ifndef BOOST_UTILITY_HPP -#define BOOST_UTILITY_HPP - -#include -#include // for size_t -#include // for std::pair - -namespace boost -{ - -// next() and prior() template functions -----------------------------------// - - // Helper functions for classes like bidirectional iterators not supporting - // operator+ and operator-. - // - // Usage: - // const std::list::iterator p = get_some_iterator(); - // const std::list::iterator prev = boost::prior(p); - - // Contributed by Dave Abrahams - - template - T next(T x) { return ++x; } - - template - T prior(T x) { return --x; } - - -// class noncopyable -------------------------------------------------------// - - // Private copy constructor and copy assignment ensure classes derived from - // class noncopyable cannot be copied. - - // Contributed by Dave Abrahams - - class noncopyable - { - protected: - noncopyable(){} - ~noncopyable(){} - private: // emphasize the following members are private - noncopyable( const noncopyable& ); - const noncopyable& operator=( const noncopyable& ); - }; // noncopyable - -// class tied -------------------------------------------------------// - - // A helper for conveniently assigning the two values from a pair - // into separate variables. The idea for this comes from Jaakko J„rvi's - // Binder/Lambda Library. - - // Constributed by Jeremy Siek - - template - class tied { - public: - inline tied(A& a, B& b) : _a(a), _b(b) { } - template - inline tied& operator=(const std::pair& p) { - _a = p.first; - _b = p.second; - return *this; - } - protected: - A& _a; - B& _b; - }; - - template - inline tied tie(A& a, B& b) { return tied(a, b); } - -} // namespace boost - -#endif // BOOST_UTILITY_HPP - diff --git a/iterator_adaptor_examples.cpp b/iterator_adaptor_examples.cpp deleted file mode 100644 index c7baa08..0000000 --- a/iterator_adaptor_examples.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - - -#include -#include -#include -#include -#include - -int -main(int, char*[]) -{ - // This is a simple example of using the transform_iterators class to - // generate iterators that multiply the value returned by dereferencing - // the iterator. In this case we are multiplying by 2. - // Would be cooler to use lambda library in this example. - - int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; - - typedef std::binder1st< std::multiplies > Function; - typedef boost::transform_iterator - >::type doubling_iterator; - - doubling_iterator i(x, std::bind1st(std::multiplies(), 2)), - i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies(), 2)); - - std::cout << "multiplying the array by 2:" << std::endl; - while (i != i_end) - std::cout << *i++ << " "; - std::cout << std::endl; - - // Here is an example of counting from 0 to 5 using the integer_range class. - - boost::integer_range r(0,5); - - std::cout << "counting to from 0 to 4:" << std::endl; - std::copy(r.begin(), r.end(), std::ostream_iterator(std::cout, " ")); - std::cout << std::endl; - - return 0; -} - - diff --git a/iterator_adaptor_test.cpp b/iterator_adaptor_test.cpp deleted file mode 100644 index a739985..0000000 --- a/iterator_adaptor_test.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// Demonstrate and test boost/operators.hpp on std::iterators -------------// - -// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 13 Jun 00 Added const version of the iterator tests (Jeremy Siek) -// 12 Dec 99 Initial version with iterator operators (Jeremy Siek) - -#include -#include - -#include -#include -#include -#include -#include - -struct my_iterator_tag : public std::random_access_iterator_tag { }; - - -using boost::dummyT; - -struct my_iter_traits { - typedef dummyT value_type; - typedef dummyT* pointer; - typedef dummyT& reference; - typedef my_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; -}; - -struct my_const_iter_traits { - typedef dummyT value_type; - typedef const dummyT* pointer; - typedef const dummyT& reference; - typedef my_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; -}; - -typedef boost::iterator_adaptors - My; - -struct mult_functor { - typedef int result_type; - typedef int argument_type; - // Functors used with transform_iterator must be - // DefaultConstructible, as the transform_iterator must be - // DefaultConstructible to satisfy the requirements for - // TrivialIterator. - mult_functor() { } - mult_functor(int aa) : a(aa) { } - int operator()(int b) const { return a * b; } - int a; -}; - -template -struct select1st_ - : public std::unary_function -{ - const typename Pair::first_type& operator()(const Pair& x) const { - return x.first; - } - typename Pair::first_type& operator()(Pair& x) const { - return x.first; - } -}; - -struct one_or_four { - bool operator()(dummyT x) const { - return x.foo() == 1 || x.foo() == 4; - } -}; - -int -main() -{ - dummyT array[] = { dummyT(0), dummyT(1), dummyT(2), - dummyT(3), dummyT(4), dummyT(5) }; - const int N = sizeof(array)/sizeof(dummyT); - - // sanity check, if this doesn't pass the test is buggy - boost::random_access_iterator_test(array,N,array); - - // Test the iterator_adaptors - { - My::iterator i = array; - boost::random_access_iterator_test(i, N, array); - - My::const_iterator j = array; - boost::random_access_iterator_test(j, N, array); - boost::const_nonconst_iterator_test(i, ++j); - } - // Test transform_iterator - { - int x[N], y[N]; - for (int k = 0; k < N; ++k) - x[k] = k; - std::copy(x, x + N, y); - - for (int k2 = 0; k2 < N; ++k2) - x[k2] = x[k2] * 2; - - boost::transform_iterator >::type - i(y, mult_functor(2)); - boost::random_access_iterator_test(i, N, x); - } - // Test indirect_iterators - { - dummyT* ptr[N]; - for (int k = 0; k < N; ++k) - ptr[k] = array + k; - typedef boost::indirect_iterators, - boost::iterator, - boost::iterator - > Indirect; - Indirect::iterator i = ptr; - boost::random_access_iterator_test(i, N, array); - - Indirect::const_iterator j = ptr; - boost::random_access_iterator_test(j, N, array); - - boost::const_nonconst_iterator_test(i, ++j); - } - // Test projection_iterators - { - typedef std::pair Pair; - Pair pair_array[N]; - for (int k = 0; k < N; ++k) - pair_array[k].first = array[k]; - - typedef boost::projection_iterators, - Pair*, const Pair*, - boost::iterator, - boost::iterator - > Projection; - - Projection::iterator i = pair_array; - boost::random_access_iterator_test(i, N, array); - - Projection::const_iterator j = pair_array; - boost::random_access_iterator_test(j, N, array); - - boost::const_nonconst_iterator_test(i, ++j); - } - // Test reverse_iterators - { - dummyT reversed[N]; - std::copy(array, array + N, reversed); - std::reverse(reversed, reversed + N); - - typedef boost::reverse_iterators, - boost::iterator - > Reverse; - Reverse::iterator i = reversed + N; - boost::random_access_iterator_test(i, N, array); - - Reverse::const_iterator j = reversed + N; - boost::random_access_iterator_test(j, N, array); - - boost::const_nonconst_iterator_test(i, ++j); - } - - // Test integer_range's iterators - { - int int_array[] = { 0, 1, 2, 3, 4, 5 }; - boost::integer_range r(0, 5); - boost::random_access_iterator_test(r.begin(), r.size(), int_array); - } - - // Test filter iterator - { - typedef boost::filter_iterator >::type FilterIter; - FilterIter i(array); - boost::forward_iterator_test(i, 1, 4); - } - std::cout << "test successful " << std::endl; - - return 0; -} diff --git a/iterator_adaptors.htm b/iterator_adaptors.htm deleted file mode 100644 index 7bfa3cd..0000000 --- a/iterator_adaptors.htm +++ /dev/null @@ -1,819 +0,0 @@ - - - - - - -Header boost/iterator_adaptors.hpp Documentation - - - - -c++boost.gif (8819 bytes) - -

Header -boost/iterator_adaptors.hpp -and -boost/integer_range.hpp

- -

The file boost/iterator_adaptors.hpp -includes the main iterator_adaptors class and several other classes -for constructing commonly used iterator adaptors.

- - - -

The file boost/integer_range.hpp includes a class that - uses iterator adaptors to create an iterator that increments over a - range of integers. The file also includes a "container" type - that creates a container-interface for the range of integers. -

- - - - -

Dave -Abrahams started the library, coming up with the idea to use -policy classes and how to handle the const/non-const iterator -interactions. He also contributed the indirect_iterators and -reverse_iterators classes.
- -Jeremy Siek -contributed transform_iterator, integer_range, -and this documentation.
- -John Potter -contributed indirect_iterator and projection_iterator -and made some simplifications to iterator_adaptor. - -

The Iterator Adaptors Class

- -Implementing standard conforming iterators is a non-trivial task. -There are some fine-points such as iterator/const_iterator -interactions and there are the myriad of operators that should be -implemented but are easily forgotten such as -operator->(). The purpose of the -iterator_adaptors class is to make it easier to implement an -iterator class, and even easier to extend and adapt existing iterator -types. The iterator_adaptors class itself is not an adaptor -class but a type generator. It generates a pair of adaptor classes, -one class for the mutable iterator and one class for the const -iterator. The definition of the iterator_adaptors class is as -follows: - -

- -
-
-template <class Iterator,
-          class ConstIterator,
-          class Traits = std::iterator_traits<Iterator>,
-          class ConstTraits = std::iterator_traits<ConstIterator>,
-          class Policies = default_iterator_policies>
-struct iterator_adaptors
-{
-  typedef ... iterator;
-  typedef ... const_iterator;
-};
-
- -

The Iterator and ConstIterator template parameters -are the iterator types that you want to adapt. The Traits and -ConstTraits must be iterator traits classes. The traits -parameters default to the specialization of the -std::iterator_traits class for the adapted iterators. If you -want the traits for your new iterator adaptor (value_type, -iterator_category, etc.) to be the same as the adapted -iterator then use the default, otherwise create your own traits -classes and pass them in [1]. - - -

The Policies class that you pass in will become the heart of -the iterator adaptor, supplying the core iterator operations that will determine how your new adaptor -class will behave. The core iterator operations are: -

    -
  • dereference - returns an element of the iterator's reference type -
  • equal - tests the iterator for equality -
  • increment - increments the iterator -
  • decrement - decrements bidirectional and random-access iterators -
  • less - imposes a strict weak ordering relation on random-access iterators -
  • distance - measures the distance between random-access iterators -
  • advance - adds an integer offset to random-access iterators -
-The Policies class must implement three, four, or -seven of the core iterator operations depending on whether you wish the -new iterator adaptor class to be a - -ForwardIterator, - -BidirectionalIterator, or -RandomAccessIterator. The -iterator_category type of the traits class you pass in -must match the category of iterator that you want to create. The default -policy class, default_iterator_policies, implements all 7 of -the core operations in the usual way. If you wish to create an -iterator adaptor that only changes a few of the iterator's behaviors, -then you can have your new policy class inherit from -default_iterator_policies to avoid retyping the usual -behaviours. You should also look at default_iterator_policies -as the "boiler-plate" for your own policy classes. The -following is definition of the default_iterator_policies -class: - - -

- -
-
-struct default_iterator_policies
-{
-  // required for a ForwardIterator
-  template <class Reference, class Iterator>
-  Reference dereference(type<Reference>, const Iterator& x) const
-    { return *x; }
-
-  template <class Iterator>
-  static void increment(Iterator& x)
-    { ++x; }
-
-  template <class Iterator1, class Iterator2>
-  bool equal(Iterator1& x, Iterator2& y) const
-    { return x == y; }
-
-  // required for a BidirectionalIterator
-  template <class Iterator>
-  static void decrement(Iterator& x)
-    { --x; }
-
-  // required for a RandomAccessIterator
-  template <class Iterator, class DifferenceType>
-  static void advance(Iterator& x, DifferenceType n)
-    { x += n; }
-
-  template <class Difference, class Iterator1, class Iterator2>
-  Difference distance(type<Difference>, Iterator1& x, Iterator2& y) const
-    { return y - x; }
-
-  template <class Iterator1, class Iterator2>
-  bool less(Iterator1& x, Iterator2& y) const
-    { return x < y; }
-};
-
- -

-The generated iterator adaptor types will have the following -constructors. - -

- -
-
-iterator(const Iterator& i, const Policies& p = Policies())
-
-const_iterator(const ConstIterator& i, const Policies& p = Policies())
-
- -

The Iterator Adaptor Class

- -This is the class used inside of the iterator_adaptors type -generator. Use this class directly (instead of using -iterator_adaptors) when you are interested in creating only -one of the iterator types (either const or non-const) or when there is -no difference between the const and non-const versions of the iterator -type (often this is because there is only a const (read-only) version -of the iterator, as is the case for std::set's iterators). - -

- -
-
-template <class Iterator,
-          class Policies = default_iterator_policies,
-          class Traits = std::iterator_traits<Iterator> >
-struct iterator_adaptor;
-
- - -

-Next we will look at some iterator adaptors that are examples of how -to use the iterator adaptors class, and that are useful iterator -adaptors in their own right. - -

The Transform Iterator Class

- -It is often useful to automatically apply some function to the value -returned by dereferencing (operator*()) an iterator. The -transform_iterators class makes it easy to create an iterator -adaptor that does just that. - -First let us consider what the Policies class for the transform -iterator should look like. We are only changing one of the iterator -behaviours, so we will inherit from -default_iterator_policies. In addition, we will need a -function object to apply, so we will have a template parameter and a -data member for the function object. The function will take one -argument (the dereferenced value) and we will need to know the -result_type of the function, so -AdaptableUnaryFunction is the corrent concept to choose for the -function object type. Now for the heart of our iterator adaptor, we -implement the dereference method, applying the function -object to *i. The type<Reference> class is -there to tell you what the reference type of the iterator is, which is -handy when writing generic iterator adaptors such as this one [2]. - - -

- -
-
-  template <class AdaptableUnaryFunction>
-  struct transform_iterator_policies : public default_iterator_policies
-  {
-    transform_iterator_policies() { }
-    transform_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
-
-    template <class Reference, class Iterator>
-    Reference dereference(type<Reference>, const Iterator& i) const
-      { return m_f(*i); }
-
-    AdaptableUnaryFunction m_f;
-  };
-
- -Next we need to create the traits class for our new iterator. In some -situations you may need to create a separate traits class for the -const and non-const iterator types, but here a single traits class -will do. The value_type and reference type of our -transform iterator will be the result_type of the function -object. The difference_type and iterator_category -will be the same as the adapted iterator. - -

- -
-
-  template <class AdaptableUnaryFunction, class IteratorTraits>
-  struct transform_iterator_traits {
-    typedef typename AdaptableUnaryFunction::result_type value_type;
-    typedef value_type reference;
-    typedef value_type* pointer;
-    typedef typename IteratorTraits::difference_type difference_type;
-    typedef typename IteratorTraits::iterator_category iterator_category;
-  };
-
- -The final step is to use the iterator_adaptor class to -construct our transform iterator. We will use the single iterator -adaptor version because we will not need to create both a mutable and -const version of the transform iterator. The transform iterator is -inherently a read-only iterator. The nicest way to package up our new -transform iterator is to create a type generator similar to -iterator_adaptor. The first template parameter will be the -type of the function object. The second parameter will be the adapted -iterator type. The third parameter is the trait class for -the adapted iterator. Inside the transform_iterators class -we use the transform_iterator_traits class defined above to -create the traits class for the new transform iterator. We then use -the iterator_adaptor class to extract the generated -iterator adaptor type. - -

- -
-
-template <class AdaptableUnaryFunction,
-          class Iterator,
-          class Traits = std::iterator_traits<Iterator>
-         >
-struct transform_iterator
-{
-  typedef transform_iterator_traits<AdaptableUnaryFunction,Traits>
-    TransTraits;
-  typedef iterator_adaptor<Iterator, TransTraits,
-    transform_iterator_policies<AdaptableUnaryFunction> >::type type;
-};
-
- -

-The following is a simple example of how to use the -transform_iterators class to iterate through a range of -numbers, multiplying each of them by 2 when they are dereferenced. - -

- -
-
-#include <functional>
-#include <iostream>
-#include <boost/iterator_adaptors.hpp>
-
-int
-main(int, char*[])
-{
-  int x[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
-
-  typedef std::binder1st< std::multiplies<int> > Function;
-  typedef boost::transform_iterator<Function, int*, 
-    boost::iterator<std::random_access_iterator_tag, int>
-  >::type doubling_iterator;
-
-  doubling_iterator i(x, std::bind1st(std::multiplies<int>(), 2)),
-    i_end(x + sizeof(x)/sizeof(int), std::bind1st(std::multiplies<int>(), 2));
-
-  std::cout << "multiplying the array by 2:" << std::endl;
-  while (i != i_end)
-    std::cout << *i++ << " ";
-  std::cout << std::endl;
-
-  return 0;
-}
-
- - -

The Indirect Iterator Adaptors

- -It is not all that uncommon to create data structures that consist of -pointers to pointers. For such a structure it might be nice to have an -iterator that applies a double-dereference inside the -operator*(). The implementation of this is similar to the -transform_iterators[3]. When talking about a -data structure of pointers to pointers (or more generally, iterators -to iterators), we call the first level iterators the outer -iterators and the second level iterators the inner -iterators. For example, if the outer iterator type is T** -then the inner iterator type is T*. - -To implement the indirect adaptors, we first create a policies class -which does a double-dereference in the dereference() method. - -

- -
-
-struct indirect_iterator_policies : public default_iterator_policies
-{
-    template <class Reference, class Iterator>
-    Reference dereference(type<Reference>, const Iterator& x) const
-        { return **x; }
-};
-
- -We then create a traits class, including a template parameter for both -the inner and outer iterators and traits classes. The -difference_type and iterator_category come from the -outer iterator, while the value_type, pointer, and -reference types come from the inner iterator. - -

- -
-
-template <class OuterIterator, class InnerIterator,
-          class OuterTraits = std::iterator_traits<OuterIterator>,
-          class InnerTraits = std::iterator_traits<InnerIterator>
-         >
-struct indirect_traits
-{
-    typedef typename OuterTraits::difference_type difference_type;
-    typedef typename InnerTraits::value_type value_type;
-    typedef typename InnerTraits::pointer pointer;
-    typedef typename InnerTraits::reference reference;
-    typedef typename OuterTraits::iterator_category iterator_category;
-};
-
- -Lastly we wrap this up in two type generators: -indirect_iterator for creating a single indirect iterator -type, and indirect_iterators for creating an const/non-const -pair of indirect iterator types. We use the iterator_adaptor -and iterator_adaptors classes here to do most of the work. - -

- -
-
-template <class OuterIterator, class InnerIterator,
-          class OuterTraits = std::iterator_traits<OuterIterator>,
-          class InnerTraits = std::iterator_traits<InnerIterator>
-         >
-struct indirect_iterator
-{
-    typedef iterator_adaptor<OuterIterator,
-        indirect_iterator_policies,
-        indirect_traits<OuterIterator, InnerIterator,
-                        OuterTraits, InnerTraits>
-    > type;
-};
-
-template <class OuterIterator,      // Mutable or Immutable, does not matter
-          class InnerIterator,      // Mutable
-          class ConstInnerIterator, // Immutable
-          class OuterTraits = std::iterator_traits<OuterIterator>,
-          class InnerTraits = std::iterator_traits<InnerIterator>,
-          class ConstInnerTraits = std::iterator_traits<ConstInnerIterator>
-         >
-struct indirect_iterators
-{
-    typedef iterator_adaptors<OuterIterator, OuterIterator,
-        indirect_traits<OuterIterator, InnerIterator,
-                        OuterTraits, InnerTraits>,
-        indirect_traits<OuterIterator, ConstInnerIterator,
-                        OuterTraits, ConstInnerTraits>,
-        indirect_iterator_policies
-        > Adaptors;
-    typedef typename Adaptors::iterator iterator;
-    typedef typename Adaptors::const_iterator const_iterator;
-};
-
- - -

The Projection Iterator Adaptors

- -The projection iterator adaptor is very similar to the transform -iterator, except for a subtle difference in the return type: the -tranform iterator returns the result of the unary function by value, -whereas the projection iterator returns the result by reference. -Therefore, these two adaptors cater to different kinds of unary -functions. Transform iterator caters to functions that create new -objects, whereas projection iterator caters to a function that somehow -obtains a reference to an object that already exists. An example of a -unary function that is suitable for use with the projection adaptor is -select1st_: - -

- -
-
-template <class Pair>
-struct select1st_ 
-  : public std::unary_function<Pair, typename Pair::first_type>
-{
-  const typename Pair::first_type& operator()(const Pair& x) const {
-    return x.first;
-  }
-  typename Pair::first_type& operator()(Pair& x) const {
-    return x.first;
-  }
-};
-
- -The implementation of projection iterator is as follows. First, the -policies class is the same as the transform iterator's policies class. - -

- -
-
-template <class AdaptableUnaryFunction>
-struct projection_iterator_policies : public default_iterator_policies
-{
-    projection_iterator_policies() { }
-    projection_iterator_policies(const AdaptableUnaryFunction& f) : m_f(f) { }
-
-    template <class Reference, class Iterator>
-    Reference dereference (type<Reference>, Iterator const& iter) const {
-        return m_f(*iter);
-    }
-
-    AdaptableUnaryFunction m_f;    
-};
-
- -Next we have two traits classes. We use value_type& for the -reference type of the mutable projection iterator, and const -value_type& for the immutable projection iterator. - -

- -
-
-template <class AdaptableUnaryFunction, class Traits>
-struct projection_iterator_traits {
-    typedef typename AdaptableUnaryFunction::result_type value_type;
-    typedef value_type& reference;
-    typedef value_type* pointer;
-    typedef typename Traits::difference_type difference_type;
-    typedef typename Traits::iterator_category iterator_category;
-};
-
-template <class AdaptableUnaryFunction, class Traits>
-struct const_projection_iterator_traits {
-    typedef typename AdaptableUnaryFunction::result_type value_type;
-    typedef value_type const& reference;
-    typedef value_type const* pointer;
-    typedef typename Traits::difference_type difference_type;
-    typedef typename Traits::iterator_category iterator_category;
-};
-
- -And to finish up, we create three generator classes that -use iterator_adaptor to create the projection iterator -types. The class projection_iterator creates a mutable -projection iterator type. The class const_projection_iterator -creates an immutable projection iterator type, and -projection_iterators creates both mutable and immutable -projection iterator types. - -

- -
-
-template <class AdaptableUnaryFunction, class Iterator,
-          class Traits = std::iterator_traits<Iterator>
-         >
-struct projection_iterator {
-    typedef projection_iterator_traits<AdaptableUnaryFunction, Traits>
-            Projection_Traits;
-    typedef iterator_adaptor<Iterator,
-            projection_iterator_policies<AdaptableUnaryFunction>,
-            Projection_Traits> type;
-};
-
-template <class AdaptableUnaryFunction, class Iterator,
-          class Traits = std::iterator_traits<Iterator>
-         >
-struct const_projection_iterator {
-    typedef const_projection_iterator_traits<AdaptableUnaryFunction,
-            Traits> Projection_Traits;
-    typedef iterator_adaptor<Iterator,
-            projection_iterator_policies<AdaptableUnaryFunction>,
-            Projection_Traits> type;
-};
-
-template <class AdaptableUnaryFunction, class Iterator, class ConstIterator,
-          class Traits = std::iterator_traits<Iterator>,
-          class ConstTraits = std::iterator_traits<ConstIterator>
-         >
-struct projection_iterators {
-    typedef projection_iterator_traits<AdaptableUnaryFunction, Traits>
-            Projection_Traits;
-    typedef const_projection_iterator_traits<AdaptableUnaryFunction,
-            ConstTraits> Const_Projection_Traits;
-    typedef iterator_adaptors<Iterator, ConstIterator,
-            Projection_Traits, Const_Projection_Traits,
-            projection_iterator_policies<AdaptableUnaryFunction> > Adaptors;
-    typedef typename Adaptors::iterator iterator;
-    typedef typename Adaptors::const_iterator const_iterator;
-};
-
- - -

The Reverse Iterators Class

- -

-Yes, there is already a reverse_iterator adaptor class -defined in the C++ Standard, but using the iterator_adaptors -class we can re-implement this classic adaptor in a more succinct and -elegant fashion. Also, this makes for a good example of using -iterator_adaptors that is in familiar territory. - -

-The first step is to create the Policies class. As in the -std::reverse_iterator class, we need to flip all the -operations of the iterator. Increment will become decrement, advancing -by n will become retreating by n, etc. - -

- -
-
-struct reverse_iterator_policies
-{
-  template <class Reference, class Iterator>
-  Reference dereference(type<Reference>, const Iterator& x) const
-    { return *boost::prior(x); }
-    // this is equivalent to { Iterator tmp = x; return *--tmp; }
-    
-  template <class Iterator>
-  void increment(Iterator& x) const
-    { --x; }
-    
-  template <class Iterator>
-  void decrement(Iterator& x) const
-    { ++x; }
-    
-  template <class Iterator, class DifferenceType>
-  void advance(Iterator& x, DifferenceType n) const
-    { x -= n; }
-    
-  template <class Difference, class Iterator1, class Iterator2>
-  Difference distance(type<Difference>, Iterator1& x, Iterator2& y) const
-    { return x - y; }
-    
-  template <class Iterator1, class Iterator2>
-  bool equal(Iterator1& x, Iterator2& y) const
-    { return x == y; }
-    
-  template <class Iterator1, class Iterator2>
-  bool less(Iterator1& x, Iterator2& y) const
-    { return y < x; }
-};
-
- -Since the traits of the reverse iterator adaptor will be the same as -the adapted iterator's traits, we do not need to create new traits -classes as was the case for transform_iterator. We can skip to -the final stage of creating a type generator class for our reverse -iterators using the iterator_adaptor class. - -

- -
-
-template <class Iterator, class ConstIterator,
-          class Traits = std::iterator_traits<Iterator>, 
-          class ConstTraits = std::iterator_traits<ConstIterator>
-         >
-struct reverse_iterators
-{
-  typedef iterator_adaptors<Iterator,ConstIterator,Traits,ConstTraits,
-    reverse_iterator_policies> Adaptor;
-  typedef typename Adaptor::iterator iterator;
-  typedef typename Adaptor::const_iterator const_iterator;
-};
-
- -A typical use of the reverse_iterators class is in -user-defined container types. You can use the -reverse_iterators class to generate the reverse iterators for -your container. - -

- -
-
-class my_container {
-  ...
-  typedef ... iterator;
-  typedef ... const_iterator;
-
-  typedef reverse_iterators<iterator, const_iterator> RevIters;
-  typedef typename RevIters::iterator reverse_iterator;
-  typedef typename RevIters::const_iterator const_reverse_iterator;
-  ...
-};
-
- - -

The Integer Range Class

- -The iterator_adaptors class can not only be used for adapting -iterators, but it can also be used to take a non-iterator type and use -it to build an iterator. An especially simple example of this is -turning an integer type into an iterator, a counting iterator. The -builtin integer types of C++ are almost iterators. They have -operator++(), operator--(), etc. The one operator -they are lacking is the operator*(), which we will want to -simply return the current value of the integer. The following few -lines of code implement the policy and traits class for the counting -iterator. - -

- -
-
-template <class IntegerType>
-struct counting_iterator_policies : public default_iterator_policies
-{
-  IntegerType dereference(type<IntegerType>, const IntegerType& i) const
-    { return i; }
-};
-template <class IntegerType>
-struct counting_iterator_traits {
-  typedef IntegerType value_type;
-  typedef IntegerType reference;
-  typedef value_type* pointer;
-  typedef std::ptrdiff_t difference_type;
-  typedef std::random_access_iterator_tag iterator_category;
-};
-
- -Typically we will want to count the integers in some range, so a nice -interface would be to have a fake container that represents the range -of integers. The following is the definition of such a class called -integer_range. - -

- -
-
-template <class IntegerType>
-struct integer_range {
-  typedef typename iterator_adaptor<IntegerType, 
-                           counting_iterator_traits<IntegerType>,
-                           counting_iterator_policies >::type iterator;
-  typedef iterator const_iterator;
-  typedef IntegerType value_type;
-  typedef std::ptrdiff_t difference_type;
-  typedef IntegerType reference;
-  typedef IntegerType* pointer;
-  typedef IntegerType size_type;
-
-  integer_range(IntegerType start, IntegerType finish)
-    : m_start(start), m_finish(finish) { }
-
-  iterator begin() const { return iterator(m_start); }
-  iterator end() const { return iterator(m_finish); }
-  size_type size() const { return m_finish - m_start; }
-  bool empty() const { return m_finish == m_start; }
-  void swap(integer_range& x) {
-    std::swap(m_start, x.m_start);
-    std::swap(m_finish, x.m_finish);
-  }
-protected:
-  IntegerType m_start, m_finish;
-};
-
- -

-The following is an example of how to use the -integer_range class to count from 0 to 4. - -

- -
-
-boost::integer_range<int> r(0,5);
-
-cout << "counting to from 0 to 4:" << endl;
-std::copy(r.begin(), r.end(), ostream_iterator<int>(cout, " "));
-cout << endl;
-
- -

Challenge

- -

-There is an unlimited number of ways the the -iterator_adaptors class can be used to create iterators. One -interesting exercise would be to re-implement the iterators of -std::list and std::slist using -iterator_adaptors, where the adapted Iterator types -would be node pointers. - - -

Notes

- -

-[1] -If your compiler does not support partial specialization and hence -does not have a working std::iterator_traits class, you will -not be able to use the defaults and will need to supply your own -Traits and ConstTraits classes. - -

-[2] -The reference type could also be obtained from -std::iterator_traits, but that is not portable on compilers -that do not support partial specialization. - -

-[3] -It would have been more elegant to implement indirect_iterators -using transform_iterators, but for subtle reasons that would require -the use of boost::remove_cv which is not portable. - -

Implementation Notes

- -The code is somewhat complicated because there are three iterator -adaptor class: forward_iterator_adaptor, -bidirectional_iterator_adaptor, and -random_access_iterator_adaptor. The alternative would be to -just have one iterator adaptor equivalent to the -random_access_iterator_adaptor. The reason for going with -the three adaptors is that according to 14.5.3p5 in the C++ Standard, -friend functions defined inside a template class body are instantiated -when the template class is instantiated. This means that if we only -used the one iterator adaptor, then if the adapted iterator did not -meet all of the requirements for a - -RandomAccessIterator then a compiler error should occur. Many -current compilers in fact do not instantiate the friend functions -unless used, so we could get away with the one iterator adaptor in -most cases. However, out of respect for the standard this implementation -uses the three adaptors. - - - -
-

Revised 27 Nov 2000

-

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

- - - - diff --git a/iterator_traits_test.cpp b/iterator_traits_test.cpp deleted file mode 100644 index e5631a8..0000000 --- a/iterator_traits_test.cpp +++ /dev/null @@ -1,141 +0,0 @@ -// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 21 Jan 2001 Quick fix to my_iterator, which wasn't returning a -// reference type from operator* (David Abrahams) -// 19 Jan 2001 Initial version with iterator operators (David Abrahams) - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct my_iterator - : public boost::forward_iterator_helper -{ - my_iterator(const char* p) : m_p(p) {} - - bool operator==(const my_iterator& rhs) const - { return this->m_p == rhs.m_p; } - - my_iterator& operator++() { ++this->m_p; return *this; } - const char& operator*() { return *m_p; } - private: - const char* m_p; -}; - -// Test difference_type and iterator_category - -// istream_iterator (forward_iterator_tag, ptrdiff_t) -BOOST_STATIC_ASSERT(( - boost::is_same< - boost::detail::iterator_traits >::iterator_category, - std::input_iterator_tag - >::value)); - -BOOST_STATIC_ASSERT(( - boost::is_same< - boost::detail::iterator_traits >::difference_type, - std::ptrdiff_t - >::value)); - -// ostream_iterator (output_iterator_tag, void) -BOOST_STATIC_ASSERT(( - boost::is_same< - boost::detail::iterator_traits >::iterator_category, - std::output_iterator_tag - >::value)); - -BOOST_STATIC_ASSERT(( - boost::is_same< - boost::detail::iterator_traits >::difference_type, - void - >::value)); - -// list::iterator (bidirectional_iterator_tag, ptrdiff_t) -BOOST_STATIC_ASSERT(( - boost::is_same< - boost::detail::iterator_traits::iterator>::iterator_category, - std::bidirectional_iterator_tag - >::value)); - -#ifdef __KCC - typedef long std_list_diff_type; -#else - typedef std::ptrdiff_t std_list_diff_type; -#endif - -BOOST_STATIC_ASSERT(( - boost::is_same< - boost::detail::iterator_traits::iterator>::difference_type, - std_list_diff_type - >::value)); - -// vector::iterator (random_access_iterator_tag, ptrdiff_t) -BOOST_STATIC_ASSERT(( - boost::is_same< - boost::detail::iterator_traits::iterator>::iterator_category, - std::random_access_iterator_tag - >::value)); - -BOOST_STATIC_ASSERT(( - boost::is_same< - boost::detail::iterator_traits::iterator>::difference_type, - std::ptrdiff_t - >::value)); - -// int* (random_access_iterator_tag, ptrdiff_t) -BOOST_STATIC_ASSERT(( - boost::is_same< - boost::detail::iterator_traits::iterator_category, - std::random_access_iterator_tag - >::value)); - -BOOST_STATIC_ASSERT(( - boost::is_same< - boost::detail::iterator_traits::difference_type, - std::ptrdiff_t - >::value)); - -// my_iterator (forward_iterator_tag, long) -BOOST_STATIC_ASSERT(( - boost::is_same< - boost::detail::iterator_traits::iterator_category, - std::forward_iterator_tag - >::value)); - -BOOST_STATIC_ASSERT(( - boost::is_same< - boost::detail::iterator_traits::difference_type, - long - >::value)); - -int main() -{ - char chars[100]; - int ints[100]; - - for (std::ptrdiff_t length = 3; length < 100; length += length / 3) - { - std::list l(length); - assert(boost::detail::distance(l.begin(), l.end()) == length); - - std::vector v(length); - assert(boost::detail::distance(v.begin(), v.end()) == length); - - assert(boost::detail::distance(&ints[0], ints + length) == length); - assert(boost::detail::distance(my_iterator(chars), my_iterator(chars + length)) == length); - } - return 0; -} diff --git a/iterators_test.cpp b/iterators_test.cpp deleted file mode 100644 index e264aff..0000000 --- a/iterators_test.cpp +++ /dev/null @@ -1,169 +0,0 @@ -// Demonstrate and test boost/operators.hpp on std::iterators --------------// - -// (C) Copyright Jeremy Siek 1999. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 12 Dec 99 Initial version with iterator operators (Jeremy Siek) - -#include -#include -using namespace std; - -#include -using namespace boost; - - -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: - test_iter(T* i) : _i(i) { } - test_iter(const self& x) : _i(x._i) { } - self& operator=(const self& x) { _i = x._i; return *this; } - Reference operator*() const { return *_i; } - 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: - T* _i; -}; - - -int -main() -{ - string array[] = { "apple", "orange", "pear", "peach", "grape", "plum" }; - { - test_iter i = array, - ie = array + sizeof(array)/sizeof(string); - - // Tests for all of the operators added by random_access_iterator_helper - - // test i++ - while (i != ie) - cout << *i++ << " "; - cout << endl; - i = array; - - // test i-- - while (ie != i) { - ie--; - cout << *ie << " "; - } - cout << endl; - ie = array + sizeof(array)/sizeof(string); - - // test i->m - while (i != ie) { - cout << i->size() << " "; - ++i; - } - cout << endl; - i = array; - - // test i + n - while (i < ie) { - cout << *i << " "; - i = i + 2; - } - cout << endl; - i = array; - - // test n + i - while (i < ie) { - cout << *i << " "; - i = ptrdiff_t(2) + i; - } - cout << endl; - i = array; - - // test i - n - while (ie > i) { - ie = ie - 2; - cout << *ie << " "; - } - cout << endl; - ie = array + sizeof(array)/sizeof(string); - - // test i[n] - for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j) - cout << i[j] << " "; - cout << endl; - } - { - test_iter i = array, - ie = array + sizeof(array)/sizeof(string); - - // Tests for all of the operators added by random_access_iterator_helper - - // test i++ - while (i != ie) - cout << *i++ << " "; - cout << endl; - i = array; - - // test i-- - while (ie != i) { - ie--; - cout << *ie << " "; - } - cout << endl; - ie = array + sizeof(array)/sizeof(string); - - // test i->m - while (i != ie) { - cout << i->size() << " "; - ++i; - } - cout << endl; - i = array; - - // test i + n - while (i < ie) { - cout << *i << " "; - i = i + 2; - } - cout << endl; - i = array; - - // test n + i - while (i < ie) { - cout << *i << " "; - i = ptrdiff_t(2) + i; - } - cout << endl; - i = array; - - // test i - n - while (ie > i) { - ie = ie - 2; - cout << *ie << " "; - } - cout << endl; - ie = array + sizeof(array)/sizeof(string); - - // test i[n] - for (std::size_t j = 0; j < sizeof(array)/sizeof(string); ++j) - cout << i[j] << " "; - cout << endl; - } - return 0; -} diff --git a/noncopyable_test.cpp b/noncopyable_test.cpp deleted file mode 100644 index e5103fb..0000000 --- a/noncopyable_test.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// boost class noncopyable test program ------------------------------------// - -// (C) Copyright boost.org 1999. Permission to copy, use, modify, sell -// and distribute this software is granted provided this copyright -// notice appears in all copies. This software is provided "as is" without -// express or implied warranty, and with no claim as to its suitability for -// any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 9 Jun 99 Add unnamed namespace -// 2 Jun 99 Initial Version - -#include -#include - -// This program demonstrates compiler errors resulting from trying to copy -// construct or copy assign a class object derived from class noncopyable. - -namespace -{ - class DontTreadOnMe : boost::noncopyable - { - public: - DontTreadOnMe() { std::cout << "defanged!" << std::endl; } - }; // DontTreadOnMe - -} // unnamed namespace - -int main() -{ - DontTreadOnMe object1; - DontTreadOnMe object2(object1); - object1 = object2; - return 0; -} // main - \ No newline at end of file diff --git a/numeric_traits_test.cpp b/numeric_traits_test.cpp deleted file mode 100644 index 0bc0ca5..0000000 --- a/numeric_traits_test.cpp +++ /dev/null @@ -1,385 +0,0 @@ -// (C) Copyright David Abrahams 2001. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 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 - -// A macro for declaring class compile-time constants. -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -# define DECLARE_CLASS_CONST(type, init) static const type init -#else -# define DECLARE_CLASS_CONST(type, init) enum { init } -#endif - -// ================================================================================= -// template class complement_traits -- -// -// 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 -{ - DECLARE_CLASS_CONST(Number, max = complement::template traits::max); - DECLARE_CLASS_CONST(Number, min = complement::template traits::min); -}; - -template -struct complement -{ - template - struct traits - { - private: - // indirection through complement_traits_aux neccessary to keep MSVC happy - typedef complement_traits_aux prev; - public: - DECLARE_CLASS_CONST(Number, max = - Number(Number(prev::max) << CHAR_BIT) - + Number(UCHAR_MAX)); - - DECLARE_CLASS_CONST(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 - { - DECLARE_CLASS_CONST(Number, min = 0); - DECLARE_CLASS_CONST(Number, max = UCHAR_MAX); - }; -}; - -template <> struct complement_base -{ - template - struct values - { - DECLARE_CLASS_CONST(Number, min = SCHAR_MIN); - DECLARE_CLASS_CONST(Number, max = SCHAR_MAX); - }; -}; - -// Base specialization of complement, puts an end to the recursion. -template <> -struct complement<1> -{ - template - struct traits - { - DECLARE_CLASS_CONST(bool, is_signed = boost::detail::is_signed::value); - DECLARE_CLASS_CONST(Number, min = - complement_base::template values::min); - DECLARE_CLASS_CONST(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 -{ - DECLARE_CLASS_CONST(Number, max = (complement_traits_aux::max)); - DECLARE_CLASS_CONST(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) // No intmax streaming built-in - -// On this platform, __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) // No intmax streaming built-in - -// On this platform, stream them as long/unsigned long if they fit. -// Otherwise, write a string. -template <> struct promote { - std::string static from(const boost::uintmax_t x) { - if (x > ULONG_MAX) - return std::string("large unsigned value"); - else - return boost::lexical_cast((unsigned long)x); - } -}; -template <> struct promote { - std::string static from(const boost::intmax_t x) { - if (x > boost::intmax_t(ULONG_MAX)) - return std::string("large positive signed value"); - else if (x >= 0) - return boost::lexical_cast((unsigned long)x); - - if (x < boost::intmax_t(LONG_MIN)) - return std::string("large negative signed value"); - else - return boost::lexical_cast((long)x); - } -}; -#endif - -// This is the function which converts types to the form I want to stream them in. -template -typename stream_as::t2 stream_number(T x) -{ - return promote::from(x); -} -// ================================================================================= - -// -// Tests for built-in signed and unsigned types -// - -// Tag types for selecting tests -struct unsigned_tag {}; -struct signed_tag {}; - -// Tests for unsigned numbers. The extra default Number parameter works around -// an MSVC bug. -template -void test_aux(unsigned_tag, Number* = 0) -{ - typedef typename boost::detail::numeric_traits::difference_type difference_type; - BOOST_STATIC_ASSERT(!boost::detail::is_signed::value); - BOOST_STATIC_ASSERT( - (sizeof(Number) < sizeof(boost::intmax_t)) - | (boost::is_same::value)); - - // Force casting to Number here to work around the fact that it's an enum on MSVC - BOOST_STATIC_ASSERT(Number(complement_traits::max) > Number(0)); - BOOST_STATIC_ASSERT(Number(complement_traits::min) == Number(0)); - - const Number max = complement_traits::max; - const Number min = complement_traits::min; - - const Number test_max = (sizeof(Number) < sizeof(boost::intmax_t)) - ? max - : max / 2 - 1; - - std::cout << std::hex << "(unsigned) min = " << stream_number(min) << ", max = " - << stream_number(max) << "..." << std::flush; - std::cout << "difference_type = " << typeid(difference_type).name() << "..." - << std::flush; - - difference_type d1 = boost::detail::numeric_distance(Number(0), test_max); - difference_type d2 = boost::detail::numeric_distance(test_max, Number(0)); - - std::cout << "0->" << stream_number(test_max) << "==" << std::dec << stream_number(d1) << "; " - << std::hex << stream_number(test_max) << "->0==" << std::dec << stream_number(d2) << "..." << std::flush; - - assert(d1 == difference_type(test_max)); - assert(d2 == -difference_type(test_max)); -} - -// Tests for signed numbers. The extra default Number parameter works around an -// MSVC bug. -struct out_of_range_tag {}; -struct in_range_tag {}; - -// This test morsel gets executed for numbers whose difference will always be -// representable in intmax_t -template -void signed_test(in_range_tag, Number* = 0) -{ - BOOST_STATIC_ASSERT(boost::detail::is_signed::value); - typedef typename boost::detail::numeric_traits::difference_type difference_type; - const Number max = complement_traits::max; - const Number min = complement_traits::min; - - difference_type d1 = boost::detail::numeric_distance(min, max); - difference_type d2 = boost::detail::numeric_distance(max, min); - - std::cout << stream_number(min) << "->" << stream_number(max) << "=="; - std::cout << std::dec << stream_number(d1) << "; "; - std::cout << std::hex << stream_number(max) << "->" << stream_number(min) - << "==" << std::dec << stream_number(d2) << "..." << std::flush; - assert(d1 == difference_type(max) - difference_type(min)); - assert(d2 == difference_type(min) - difference_type(max)); -} - -// This test morsel gets executed for numbers whose difference may exceed the -// capacity of intmax_t. -template -void signed_test(out_of_range_tag, Number* = 0) -{ - BOOST_STATIC_ASSERT(boost::detail::is_signed::value); - typedef typename boost::detail::numeric_traits::difference_type difference_type; - const Number max = complement_traits::max; - const Number min = complement_traits::min; - - difference_type min_distance = complement_traits::min; - difference_type max_distance = complement_traits::max; - - const Number n1 = Number(min + max_distance); - const Number n2 = Number(max + min_distance); - difference_type d1 = boost::detail::numeric_distance(min, n1); - difference_type d2 = boost::detail::numeric_distance(max, n2); - - std::cout << stream_number(min) << "->" << stream_number(n1) << "=="; - std::cout << std::dec << stream_number(d1) << "; "; - std::cout << std::hex << stream_number(max) << "->" << stream_number(n2) - << "==" << std::dec << stream_number(d2) << "..." << std::flush; - assert(d1 == max_distance); - assert(d2 == min_distance); -} - -template -void test_aux(signed_tag, Number* = 0) -{ - typedef typename boost::detail::numeric_traits::difference_type difference_type; - BOOST_STATIC_ASSERT(boost::detail::is_signed::value); - BOOST_STATIC_ASSERT( - (sizeof(Number) < sizeof(boost::intmax_t)) - | (boost::is_same::value)); - - // Force casting to Number here to work around the fact that it's an enum on MSVC - BOOST_STATIC_ASSERT(Number(complement_traits::max) > Number(0)); - BOOST_STATIC_ASSERT(Number(complement_traits::min) < Number(0)); - - const Number max = complement_traits::max; - const Number min = complement_traits::min; - - std::cout << std::hex << "min = " << stream_number(min) << ", max = " - << stream_number(max) << "..." << std::flush; - std::cout << "difference_type = " << typeid(difference_type).name() << "..." - << std::flush; - - typedef typename boost::detail::if_true< - (sizeof(Number) < sizeof(boost::intmax_t))> - ::template then< - in_range_tag, - out_of_range_tag - >::type - range_tag; - signed_test(range_tag()); -} - - -// Test for all numbers. The extra default Number parameter works around an MSVC -// bug. -template -void test(Number* = 0) -{ - std::cout << "testing " << typeid(Number).name() << ":\n" -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - << "is_signed: " << (std::numeric_limits::is_signed ? "true\n" : "false\n") - << "is_bounded: " << (std::numeric_limits::is_bounded ? "true\n" : "false\n") - << "digits: " << std::numeric_limits::digits << "\n" -#endif - << "..." << std::flush; - typedef typename boost::detail::numeric_traits::difference_type difference_type; - BOOST_STATIC_ASSERT(boost::detail::is_signed::value); - - typedef typename boost::detail::if_true< - boost::detail::is_signed::value - >::template then::type signedness; - - test_aux(signedness()); - std::cout << "passed" << std::endl; -} - -int main() -{ - test(); - test(); - test(); - test(); - test(); - test(); - test(); - test(); - test(); - test(); -#if defined(ULLONG_MAX) || defined(ULONG_LONG_MAX) - test(); - test(); -#elif defined(BOOST_MSVC) - // The problem of not having compile-time static class constants other than - // enums prevents this from working, since values get truncated. - // test(); - // test(); -#endif - return 0; -} diff --git a/operators.htm b/operators.htm deleted file mode 100644 index f97498c..0000000 --- a/operators.htm +++ /dev/null @@ -1,597 +0,0 @@ - - - - - - -Header boost/operators.hpp Documentation - - - - -

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

-

Header boost/operators.hpp supplies -(in namespace boost) several sets of templates:

- -

These templates define many global operators in terms of a minimal number of -fundamental operators.

-

Arithmetic Operators

-

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 +.  Two-argument -forms of the templates are also provided to allow interaction with other -types.

-

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.
-Aleksey Gurtovoy -contributed the code to support base class chaining -while remaining backward-compatible with old versions of the library.
-Beman Dawes -contributed test_operators.cpp.

-

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.

- -

Two-Argument Template Forms

-
-

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<> -and equality_comparable<> -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.

-

Arithmetic operators table

-

The requirements for the types used to instantiate operator templates are -specified in terms of expressions which must be valid and by the return type of -the expression. In the following table t and t1 are -values of type T, and u is a value of type U. -Every template in the library other than operators<> -and operators2<> has an additional -optional template parameter B which is not shown in the table, but -is explained below

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
templatetemplate will supplyRequirements
operators<T>All the other <T> templates in this table.All the <T> requirements in this table.
operators<T,U>
- operators2<T,U>
All the other <T,U> templates in this table, plus incrementable<T> - and decrementable<T>.All the <T,U> requirements in this table*, - plus incrementable<T> and decrementable<T>.
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
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. Return convertible to bool
- t>u. Return convertible to bool
equality_comparable<T>
- equality_comparable1<T>
bool operator!=(const T&, const T&)t==t1. Return convertible to bool
equality_comparable<T,U>
- equality_comparable2<T,U>
friend bool operator==(const U&, const T&)
- friend bool operator!=(const U&, const T&)
- friend bool operator!=( const T&, const U&)
t==u. Return convertible to bool
addable<T>
- addable1<T>
T operator+(T, const T&)t+=t1. Return convertible to T
addable<T,U>
- addable2<T,U>
T operator+(T, const U&)
- T operator+(const U&, T )
t+=u. Return convertible to T
subtractable<T>
- subtractable1<T>
T operator-(T, const T&)t-=t1. Return convertible to T
subtractable<T,U>
- subtractable2<T,U>
T operator-(T, const U&)t-=u. Return convertible to T
multipliable<T>
- multipliable1<T>
T operator*(T, const T&)t*=t1. Return convertible to T
multipliable<T,U>
- multipliable2<T,U>
T operator*(T, const U&)
- T operator*(const U&, T )
t*=u. Return convertible to T
dividable<T>
- dividable1<T>
T operator/(T, const T&)t/=t1. Return convertible to T
dividable<T,U>
- dividable2<T,U>
T operator/(T, const U&)t/=u. Return convertible to T
modable<T>
- modable1<T>
T operator%(T, const T&)t%=t1. Return convertible to T
modable<T,U>
- modable2<T,U>
T operator%(T, const U&)t%=u. Return convertible to T
orable<T>
- orable1<T>
T operator|(T, const T&)t|=t1. Return convertible to T
orable<T,U>
- orable2<T,U>
T operator|(T, const U&)
- T operator|(const U&, T )
t|=u. Return convertible to T
andable<T>
- andable1<T>
T operator&(T, const T&)t&=t1. Return convertible to T
andable<T,U>
- andable2<T,U>
T operator&(T, const U&)
- T operator&(const U&, T)
t&=u. Return convertible to T
xorable<T>
- xorable1<T>
T operator^(T, const T&)t^=t1. Return convertible to T
xorable<T,U>
- xorable2<T,U>
T operator^(T, const U&)
- T operator^(const U&, T )
t^=u. Return convertible to T
incrementable<T>
- incrementable1<T>
T operator++(T& x, int)T temp(x); ++x; return temp;
- Return convertible to T
decrementable<T>
- decrementable1<T>
T operator--(T& x, int)T temp(x); --x; return temp;
- Return convertible to T
-
-Portability Note: many compilers (e.g. MSVC6.3, -GCC 2.95.2) will not enforce the requirements in this table unless the -operations which depend on them are actually used. This is not -standard-conforming behavior. If you are trying to write portable code it is -important not to rely on this bug. In particular, 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 in the table. Even if -this works with your compiler today, it may not work tomorrow. -

Base Class Chaining and Object Size

-

Every template listed in the table except operators<> -and operators2<> has an additional -optional template parameter B.  If supplied, B -must be a class type; the resulting class will be publicly derived from B. This -can be used to avoid the object size bloat commonly associated with multiple -empty base classes (see the note for users of older -versions below for more details). To provide support for several groups of -operators, use the additional parameter to chain operator templates into a -single-base class hierarchy, as in the following example.

-

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.

-

Borland users: even single-inheritance seems to cause an increase in -object size in some cases. If you are not defining a 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 class less_than_comparable<myclass>;
-    template class equality_comparable<myclass>;
-    template class incrementable<myclass>;
-    template class decrementable<myclass>;
-    template class addable<myclass,long>;
-    template class subtractable<myclass,long>;
-
-
-

Usage example

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

-

The test program has been compiled and run successfully with: 

-
    -
  • GCC 2.95.2 -
  • GCC 2.95.2 / STLport 4.0b8. -
  • Metrowerks Codewarrior 5.3 -
  • KAI C++ 3.3 -
  • Microsoft Visual C++ 6.0 SP3. -
  • Microsoft Visual C++ 6.0 SP3 / STLport 4.0b8.
  • -
-

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[]). -

Notation

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Tis the user-defined type for which the operations are - being supplied.
Vis the type which the resulting dereferenceable - type "points to", or the value_type of the custom - iterator.
Dis the type used to index the resulting indexable - type or the difference_type of the custom iterator.
Pis a type which can be dereferenced to access V, - or the pointer type of the custom iterator.
Ris the type returned by indexing the indexable - type or the reference type of the custom iterator.
iis short for static_cast<const T&>(*this), - where this is a pointer to the helper class.
- Another words, i should be an object of the custom iterator - type.
x,x1,x2are objects of type T.
nis an object of type D.
-

The requirements for the types used to instantiate the dereference operators -and iterator helpers are specified in terms of expressions which must be valid -and their return type. 

-

Dereference operators

-

The dereference operator templates in this table all accept an optional -template parameter (not shown) to be used for base class -chaining. - - - - - - - - - - - - - - - - - - -
templatetemplate will supplyRequirements
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.
-

Iterator helpers

-

There are three separate iterator helper classes, each for a different -category of iterator. Here is a summary of the core set of operators that the -custom iterator must define, and the extra operators that are created by the -helper classes. For convenience, the helper classes also fill in all of the -typedef's required of iterators by the C++ standard (iterator_category, -value_type, etc.).

- - - - - - - - - - - - - - - - - - - - - - - -
templatetemplate will supplyRequirements
forward_iterator_helper
- <T,V,D,P,R>
bool operator!=(const T& x1, const T& x2)
- T operator++(T& x, int)
- V* operator->() const
-
x1==x2. Return convertible to bool
- T temp(x); ++x; return temp;
- (&*i.). Return convertible to V*.
bidirectional_iterator_helper
- <T,V,D,P,R>
Same as above, plus
- T operator--(T& x, int)
Same as above, plus
- T temp(x); --x; return temp;
random_access_iterator_helper
- <T,V,D,P,R>
Same as above, plus
- T operator+(T x, const D&)
- T operator+(const D& n, T x)
- T operator-(T x, const D& n)
- R operator[](D n) const
- bool operator>(const T& x1, const T& x2) 
- bool operator<=(const T& x1, const T& x2)
- bool operator>=(const T& x1, const T& x2)
Same as above, plus
- x+=n. Return convertible to T
- x-=n. Return convertible to T
- x1<x2. Return convertible to bool
- And to satisfy RandomAccessIterator:
- x1-x2. Return convertible to D
-

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:
-  test_iter(T* i) : _i(i) { }
-  test_iter(const self& x) : _i(x._i) { }
-  self& operator=(const self& x) { _i = x._i; return *this; }
-  Reference operator*() const { return *_i; }
-  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:
-  T* _i;
-};
-
-

It has been compiled and run successfully with:

-
    -
  • GCC 2.95.2 -
  • Metrowerks Codewarrior 5.2 -
  • Microsoft Visual C++ 6.0 SP3
  • -
-

Jeremy Siek -contributed the iterator operators and helpers.  He also contributed iterators_test.cpp

-
-

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], -par. 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 27 Sep 2000

-

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

- - - - diff --git a/operators_test.cpp b/operators_test.cpp deleted file mode 100644 index a194521..0000000 --- a/operators_test.cpp +++ /dev/null @@ -1,481 +0,0 @@ -// Demonstrate and test boost/operators.hpp -------------------------------// - -// (C) Copyright Beman Dawes 1999. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// See http://www.boost.org for most recent version including documentation. - -// Revision History -// 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 - -#include -#include -#include -#include - - -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; } - 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; } - - // The use of operators<> here tended to obscure interactions with certain - // compiler bugs - template - class Wrapped1 : boost::operators > - { - 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++() { ++_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> - { - 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++() { ++_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; } - - private: - T _value; - }; - template - T true_value(Wrapped2 x) { return x.value(); } - - // MyInt uses only the single template-argument form of all_operators<> - typedef Wrapped1 MyInt; - - typedef Wrapped2 MyLong; - - template - void sanity_check(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - assert(true_value(y1) == true_value(y2)); - assert(true_value(x1) == true_value(x2)); - } - - template - void test_less_than_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - assert((x1 < y1) == (x2 < y2)); - assert((x1 <= y1) == (x2 <= y2)); - assert((x1 >= y1) == (x2 >= y2)); - assert((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) - { - assert((x1 == y1) == (x2 == y2)); - assert((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) - { - assert((x1 * y1).value() == (x2 * y2)); - } - - template - void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check(x1, y1, x2, y2); - test_multipliable_aux(x1, y1, x2, y2); - test_multipliable_aux(y1, x1, y2, x2); - } - - template - void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - assert((x1 + y1).value() == (x2 + y2)); - } - - template - void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check(x1, y1, x2, y2); - test_addable_aux(x1, y1, x2, y2); - test_addable_aux(y1, x1, y2, x2); - } - - template - void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check(x1, y1, x2, y2); - assert((x1 - y1).value() == x2 - y2); - } - - template - void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check(x1, y1, x2, y2); - if (y2 != 0) - assert((x1 / y1).value() == x2 / y2); - } - - template - void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check(x1, y1, x2, y2); - if (y2 != 0) - assert((x1 / y1).value() == x2 / y2); - } - - template - void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - assert((x1 ^ y1).value() == (x2 ^ y2)); - } - - template - void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check(x1, y1, x2, y2); - test_xorable_aux(x1, y1, x2, y2); - test_xorable_aux(y1, x1, y2, x2); - } - - template - void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - assert((x1 & y1).value() == (x2 & y2)); - } - - template - void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check(x1, y1, x2, y2); - test_andable_aux(x1, y1, x2, y2); - test_andable_aux(y1, x1, y2, x2); - } - - template - void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - assert((x1 | y1).value() == (x2 | y2)); - } - - template - void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2) - { - sanity_check(x1, y1, x2, y2); - test_orable_aux(x1, y1, x2, y2); - test_orable_aux(y1, x1, y2, x2); - } - - template - void test_incrementable(X1 x1, X2 x2) - { - sanity_check(x1, x1, x2, x2); - assert(x1++.value() == x2++); - assert(x1.value() == x2); - } - - template - void test_decrementable(X1 x1, X2 x2) - { - sanity_check(x1, x1, x2, x2); - assert(x1--.value() == x2--); - assert(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_incrementable(x1, x2); - test_decrementable(x1, x2); - } - - template - struct tester - { - void operator()(boost::min_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); - } - }; - - // added as a regression test. We had a bug which this uncovered. - struct Point - : boost::addable > - { - Point( int h, int v ) : h(h), v(v) {} - Point() :h(0), v(0) {} - const Point& operator+=( const Point& rhs ) { h += rhs.h; v += rhs.v; return *this; } - const Point& operator-=( const Point& rhs ) { h -= rhs.h; v -= rhs.v; return *this; } - - int h; - int v; - }; -} // unnamed namespace - - -// workaround for MSVC bug; for some reasons the compiler doesn't instantiate -// inherited operator templates at the moment it must, so the following -// explicit instantiations force it to do that. - -#if defined(BOOST_MSVC) && (_MSC_VER <= 1200) -template Wrapped1; -template Wrapped1; -template Wrapped1; -template Wrapped1; - -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -template Wrapped2; -#endif - -#ifdef NDEBUG -#error This program is pointless when NDEBUG disables assert()! -#endif - -int main() -{ - // Regression test. - Point x; - x = x + Point(3, 4); - x = x - Point(3, 4); - - for (int n = 0; n < 10000; ++n) - { - boost::min_rand r; - tester()(r); - tester()(r); - tester()(r); - tester()(r); - tester()(r); - - tester()(r); - tester()(r); - tester()(r); - tester()(r); - tester()(r); - } - - MyInt i1(1); - MyInt i2(2); - MyInt i; - - assert( i1.value() == 1 ); - assert( i2.value() == 2 ); - assert( i.value() == 0 ); - - i = i2; - assert( i.value() == 2 ); - assert( i2 == i ); - assert( i1 != i2 ); - assert( i1 < i2 ); - assert( i1 <= i2 ); - assert( i <= i2 ); - assert( i2 > i1 ); - assert( i2 >= i1 ); - assert( i2 >= i ); - - i = i1 + i2; assert( i.value() == 3 ); - i = i + i2; assert( i.value() == 5 ); - i = i - i1; assert( i.value() == 4 ); - i = i * i2; assert( i.value() == 8 ); - i = i / i2; assert( i.value() == 4 ); - i = i % (i - i1); assert( i.value() == 1 ); - i = i2 + i2; assert( i.value() == 4 ); - i = i1 | i2 | i; assert( i.value() == 7 ); - i = i & i2; assert( i.value() == 2 ); - i = i + i1; assert( i.value() == 3 ); - i = i ^ i1; assert( i.value() == 2 ); - i = (i+i1)*(i2|i1); assert( i.value() == 9 ); - - MyLong j1(1); - MyLong j2(2); - MyLong j; - - assert( j1.value() == 1 ); - assert( j2.value() == 2 ); - assert( j.value() == 0 ); - - j = j2; - assert( j.value() == 2 ); - - assert( j2 == j ); - assert( 2 == j ); - assert( j2 == 2 ); - assert( j == j2 ); - assert( j1 != j2 ); - assert( j1 != 2 ); - assert( 1 != j2 ); - assert( j1 < j2 ); - assert( 1 < j2 ); - assert( j1 < 2 ); - assert( j1 <= j2 ); - assert( 1 <= j2 ); - assert( j1 <= j ); - assert( j <= j2 ); - assert( 2 <= j2 ); - assert( j <= 2 ); - assert( j2 > j1 ); - assert( 2 > j1 ); - assert( j2 > 1 ); - assert( j2 >= j1 ); - assert( 2 >= j1 ); - assert( j2 >= 1 ); - assert( j2 >= j ); - assert( 2 >= j ); - assert( j2 >= 2 ); - - assert( (j1 + 2) == 3 ); - assert( (1 + j2) == 3 ); - j = j1 + j2; assert( j.value() == 3 ); - - assert( (j + 2) == 5 ); - assert( (3 + j2) == 5 ); - j = j + j2; assert( j.value() == 5 ); - - assert( (j - 1) == 4 ); - j = j - j1; assert( j.value() == 4 ); - - assert( (j * 2) == 8 ); - assert( (4 * j2) == 8 ); - j = j * j2; assert( j.value() == 8 ); - - assert( (j / 2) == 4 ); - j = j / j2; assert( j.value() == 4 ); - - assert( (j % 3) == 1 ); - j = j % (j - j1); assert( j.value() == 1 ); - - j = j2 + j2; assert( j.value() == 4 ); - - assert( (1 | j2 | j) == 7 ); - assert( (j1 | 2 | j) == 7 ); - assert( (j1 | j2 | 4) == 7 ); - j = j1 | j2 | j; assert( j.value() == 7 ); - - assert( (7 & j2) == 2 ); - assert( (j & 2) == 2 ); - j = j & j2; assert( j.value() == 2 ); - - j = j | j1; assert( j.value() == 3 ); - - assert( (3 ^ j1) == 2 ); - assert( (j ^ 1) == 2 ); - j = j ^ j1; assert( j.value() == 2 ); - - j = (j+j1)*(j2|j1); assert( j.value() == 9 ); - - std::cout << "0 errors detected\n"; - return 0; -} diff --git a/tie.html b/tie.html deleted file mode 100644 index 8023b61..0000000 --- a/tie.html +++ /dev/null @@ -1,137 +0,0 @@ - - - -Boost Tie - -C++ Boost - -
- -

-tie -

- -

-

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

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

- -

Where Defined

- -

-boost/utility.hpp - -

- -

Example

- -

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

-

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

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

-

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

Header -<boost/type_traits.hpp>

- -

The contents of <boost/type_traits.hpp> are declared in -namespace boost.

- -

The file <boost/type_traits.hpp> -contains various template classes that describe the fundamental -properties of a type; each class represents a single type -property or a single type transformation. This documentation is -divided up into the following sections:

- -
Fundamental type operations
-Fundamental type properties
-   Miscellaneous
-   cv-Qualifiers
-   Fundamental Types
-   Compound Types
-   Object/Scalar Types
-Compiler Support Information
-Example Code
- -

Fundamental type operations

- -

Usage: "class_name<T>::type" performs -indicated transformation on type T.

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

Expression.

-

Description.

-

Compiler.

-
remove_volatile<T>::typeCreates a type the same as T - but with any top level volatile qualifier removed. For - example "volatile int" would become "int".

P

-
remove_const<T>::typeCreates a type the same as T - but with any top level const qualifier removed. For - example "const int" would become "int".

P

-
remove_cv<T>::typeCreates a type the same as T - but with any top level cv-qualifiers removed. For example - "const int" would become "int", and - "volatile double" would become "double".

P

-
remove_reference<T>::typeIf T is a reference type - then removes the reference, otherwise leaves T unchanged. - For example "int&" becomes "int" - but "int*" remains unchanged.

P

-
add_reference<T>::typeIf T is a reference type - then leaves T unchanged, otherwise converts T to a - reference type. For example "int&" remains - unchanged, but "double" becomes "double&".

P

-
remove_bounds<T>::typeIf T is an array type then - removes the top level array qualifier from T, otherwise - leaves T unchanged. For example "int[2][3]" - becomes "int[3]".

P

-
- -

 

- -

Fundamental type properties

- -

Usage: "class_name<T>::value" is true if -indicated property is true, false otherwise. (Note that class_name<T>::value -is always defined as a compile time constant).

- -

Miscellaneous

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

Expression

-

Description

-

Compiler

-
is_same<T,U>::value
-

True if T and U are the - same type.

-
 
is_convertible<T,U>::value
-

True if type T is - convertible to type U.

-
 
alignment_of<T>::value
-

An integral value - representing the minimum alignment requirements of type T - (strictly speaking defines a multiple of the type's - alignment requirement; for all compilers tested so far - however it does return the actual alignment).

-
 
- -

 

- -

cv-Qualifiers

- -

The following classes determine what cv-qualifiers are present -on a type (see 3.93).

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

Expression.

-

Description.

-

Compiler.

-
is_const<T>::valueTrue if type T is top-level - const qualified. 
is_volatile<T>::valueTrue if type T is top-level - volatile qualified. 
- -

 

- -

Fundamental Types

- -

The following will only ever be true for cv-unqualified types; -these are closely based on the section 3.9 of the C++ Standard.

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

Expression.

-

Description.

-

Compiler.

-
is_void<T>::valueTrue only if T is void. 
is_standard_unsigned_integral<T>::valueTrue only if T is one of the - standard unsigned integral types (3.9.1 p3) - unsigned - char, unsigned short, unsigned int, and unsigned long. 
is_standard_signed_integral<T>::valueTrue only if T is one of the - standard signed integral types (3.9.1 p2) - signed char, - short, int, and long. 
is_standard_integral<T>::valueTrue if T is a standard - integral type(3.9.1 p7) - T is either char, wchar_t, bool - or either is_standard_signed_integral<T>::value or - is_standard_integral<T>::value is true. 
is_standard_float<T>::valueTrue if T is one of the - standard floating point types(3.9.1 p8) - float, double - or long double. 
is_standard_arithmetic<T>::valueTrue if T is a standard - arithmetic type(3.9.1 p8) - implies is_standard_integral - or is_standard_float is true. 
is_standard_fundamental<T>::valueTrue if T is a standard - arithmetic type or if T is void. 
is_extension_unsigned_integral<T>::valueTrue for compiler specific - unsigned integral types. 
is_extension_signed_integral<T>>:valueTrue for compiler specific - signed integral types. 
is_extension_integral<T>::valueTrue if either is_extension_unsigned_integral<T>::value - or is_extension_signed_integral<T>::value is true. 
is_extension_float<T>::valueTrue for compiler specific - floating point types. 
is_extension_arithmetic<T>::valueTrue if either is_extension_integral<T>::value - or is_extension_float<T>::value are true. 
 is_extension_fundamental<T>::valueTrue if either is_extension_arithmetic<T>::value - or is_void<T>::value are true. 
 is_unsigned_integral<T>::valueTrue if either is_standard_unsigned_integral<T>::value - or is_extention_unsigned_integral<T>::value are - true. 
is_signed_integral<T>::valueTrue if either is_standard_signed_integral<T>::value - or is_extention_signed_integral<T>>::value are - true. 
is_integral<T>::valueTrue if either is_standard_integral<T>::value - or is_extention_integral<T>::value are true. 
is_float<T>::valueTrue if either is_standard_float<T>::value - or is_extention_float<T>::value are true. 
is_arithmetic<T>::valueTrue if either is_integral<T>::value - or is_float<T>::value are true. 
is_fundamental<T>::valueTrue if either is_arithmetic<T>::value - or is_void<T>::value are true. 
- -

 

- -

Compound Types

- -

The following will only ever be true for cv-unqualified types, -as defined by the Standard. 

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

Expression

-

Description

-

Compiler

-
is_array<T>::valueTrue if T is an array type.

P

-
is_pointer<T>::valueTrue if T is a regular - pointer type - including function pointers - but - excluding pointers to member functions (3.9.2 p1 and 8.3.1). 
is_member_pointer<T>::valueTrue if T is a pointer to a - non-static class member (3.9.2 p1 and 8.3.1). 
is_reference<T>::valueTrue if T is a reference - type (3.9.2 p1 and 8.3.2). 
is_class<T>::valueTrue if T is a class or - struct type.

PD

-
is_union<T>::valueTrue if T is a union type.

C

-
is_enum<T>::valueTrue if T is an enumerator - type.

C

-
is_compound<T>::valueTrue if T is any of the - above compound types.

PD

-
- -

 

- -

Object/Scalar Types

- -

The following ignore any top level cv-qualifiers: if class_name<T>::value -is true then class_name<cv-qualified-T>::value -will also be true.

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

Expression

-

Description

-

Compiler

-
is_object<T>::valueTrue if T is not a reference - type, or a (possibly cv-qualified) void type.

P

-
is_standard_scalar<T>::valueTrue if T is a standard - arithmetic type, an enumerated type, a pointer or a - member pointer.

PD

-
is_extension_scalar<T>::valueTrue if T is an extentions - arithmetic type, an enumerated type, a pointer or a - member pointer.

PD

-
is_scalar<T>::valueTrue if T is an arithmetic - type, an enumerated type, a pointer or a member pointer.

PD

-
is_POD<T>::valueTrue if T is a "Plain - Old Data" type (see 3.9 p2&p3). Note that - although this requires compiler support to be correct in - all cases, if T is a scalar or an array of scalars then - we can correctly define T as a POD.

PC

-
is_empty<T>::valueTrue if T is an empty struct - or class. If the compiler implements the "zero sized - empty base classes" optimisation, then is_empty will - correctly guess whether T is empty. Relies upon is_class - to determine whether T is a class type. Screens out enum - types by using is_convertible<T,int>, this means - that empty classes that overload operator int(), will not - be classified as empty.

PCD

-
has_trivial_constructor<T>::valueTrue if T has a trivial - default constructor - that is T() is equivalent to memset.

PC

-
has_trivial_copy<T>::valueTrue if T has a trivial copy - constructor - that is T(const T&) is equivalent to - memcpy.

PC

-
has_trivial_assign<T>::valueTrue if T has a trivial - assignment operator - that is if T::operator=(const T&) - is equivalent to memcpy.

PC

-
has_trivial_destructor<T>::valueTrue if T has a trivial - destructor - that is if T::~T() has no effect.

PC

-
- -

 

- -

Compiler Support Information

- -

The legends used in the tables above have the following -meanings:

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

P

-
Denotes that the class - requires support for partial specialisation of class - templates to work correctly.

C

-
Denotes that direct compiler - support for that traits class is required.

D

-
Denotes that the traits - class is dependent upon a class that requires direct - compiler support.
- -

 

- -

For those classes that are marked with a D or C, if compiler -support is not provided, this type trait may return "false" -when the correct value is actually "true". The single -exception to this rule is "is_class", which attempts to -guess whether or not T is really a class, and may return "true" -when the correct value is actually "false". This can -happen if: T is a union, T is an enum, or T is a compiler-supplied -scalar type that is not specialised for in these type traits.

- -

If there is no compiler support, to ensure that these -traits always return the correct values, specialise 'is_enum' -for each user-defined enumeration type, 'is_union' for each user-defined -union type, 'is_empty' for each user-defined empty composite type, -and 'is_POD' for each user-defined POD type. The 'has_*' traits -should also be specialized if the user-defined type has those -traits and is not a POD.

- -

The following rules are automatically enforced:

- -

is_enum implies is_POD

- -

is_POD implies has_*

- -

This means, for example, if you have an empty POD-struct, just -specialize is_empty and is_POD, which will cause all the has_* to -also return true.

- -

Example code

- -

Type-traits comes with two sample programs: type_traits_test.cpp tests the -type traits classes - mostly this is a test of your compiler's -support for the concepts used in the type traits implementation, -while algo_opt_examples.cpp -uses the type traits classes to "optimise" some -familiar standard library algorithms.

- -

There are four algorithm examples in algo_opt_examples.cpp:

- - - - - - - - - - - - - - - - - - -
opt::copy
-
If the copy operation can be - performed using memcpy then does so, otherwise uses a - regular element by element copy (c.f. std::copy).
opt::fill
-
If the fill operation can be - performed by memset, then does so, otherwise uses a - regular element by element assign. Also uses call_traits - to optimise how the parameters can be passed (c.f. - std::fill).
opt::destroy_array
-
If the type in the array has - a trivial destructor then does nothing, otherwise calls - destructors for all elements in the array - this - algorithm is the reverse of std::uninitialized_copy / std::uninitialized_fill.
opt::iter_swap
-
Determines whether the - iterator is a proxy-iterator: if it is then does a "slow - and safe" swap, otherwise calls std::swap on the - assumption that std::swap may be specialised for the - iterated type.
- -

 

- -
- -

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.egroups.com/list/boost.

- - diff --git a/type_traits_test.cpp b/type_traits_test.cpp deleted file mode 100644 index bcd1946..0000000 --- a/type_traits_test.cpp +++ /dev/null @@ -1,659 +0,0 @@ -// (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. -// Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// standalone test program for - -/* Release notes: - 20 Jan 2001: - Suppress an expected warning for MSVC - Added a test to prove that we can use void with is_same<> - Removed "press any key to exit" as it interferes with testing in large - batches. - (David Abahams) - 31st July 2000: - Added extra tests for is_empty, is_convertible, alignment_of. - 23rd July 2000: - Removed all call_traits tests to call_traits_test.cpp - Removed all compressed_pair tests to compressed_pair_tests.cpp - Improved tests macros - Tidied up specialistions of type_types classes for test cases. -*/ - -#include -#include - -#include -#include -#include "type_traits_test.hpp" - -using namespace boost; - -// Since there is no compiler support, we should specialize: -// is_enum for all enumerations (is_enum implies is_POD) -// is_union for all unions -// is_empty for all empty composites -// is_POD for all PODs (except enums) (is_POD implies has_*) -// has_* for any UDT that has that trait and is not POD - -enum enum_UDT{ one, two, three }; -struct UDT -{ - UDT(); - ~UDT(); - UDT(const UDT&); - UDT& operator=(const UDT&); - int i; - - void f1(); - int f2(); - int f3(int); - int f4(int, float); -}; - -struct POD_UDT { int x; }; -struct empty_UDT{ ~empty_UDT(){}; }; -struct empty_POD_UDT{}; -union union_UDT -{ - int x; - double y; - ~union_UDT(); -}; -union POD_union_UDT -{ - int x; - double y; -}; -union empty_union_UDT -{ - ~empty_union_UDT(); -}; -union empty_POD_union_UDT{}; -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -namespace boost { -template <> struct is_enum -{ static const bool value = true; }; -template <> struct is_POD -{ static const bool value = true; }; -// this type is not POD, so we have to specialize the has_* individually -template <> struct has_trivial_constructor -{ static const bool value = true; }; -template <> struct has_trivial_copy -{ static const bool value = true; }; -template <> struct has_trivial_assign -{ static const bool value = true; }; -template <> struct is_POD -{ static const bool value = true; }; -template <> struct is_union -{ static const bool value = true; }; -template <> struct is_union -{ static const bool value = true; }; -template <> struct is_POD -{ static const bool value = true; }; -template <> struct is_union -{ static const bool value = true; }; -// this type is not POD, so we have to specialize the has_* individually -template <> struct has_trivial_constructor -{ static const bool value = true; }; -template <> struct has_trivial_copy -{ static const bool value = true; }; -template <> struct has_trivial_assign -{ static const bool value = true; }; -template <> struct is_union -{ static const bool value = true; }; -template <> struct is_POD -{ static const bool value = true; }; -} -#else -namespace boost { -template <> struct is_enum -{ enum{ value = true }; }; -template <> struct is_POD -{ enum{ value = true }; }; -// this type is not POD, so we have to specialize the has_* individually -template <> struct has_trivial_constructor -{ enum{ value = true }; }; -template <> struct has_trivial_copy -{ enum{ value = true }; }; -template <> struct has_trivial_assign -{ enum{ value = true }; }; -template <> struct is_POD -{ enum{ value = true }; }; -template <> struct is_union -{ enum{ value = true }; }; -template <> struct is_union -{ enum{ value = true }; }; -template <> struct is_POD -{ enum{ value = true }; }; -template <> struct is_union -{ enum{ value = true }; }; -// this type is not POD, so we have to specialize the has_* individually -template <> struct has_trivial_constructor -{ enum{ value = true }; }; -template <> struct has_trivial_copy -{ enum{ value = true }; }; -template <> struct has_trivial_assign -{ enum{ value = true }; }; -template <> struct is_union -{ enum{ value = true }; }; -template <> struct is_POD -{ enum{ value = true }; }; -} -#endif - -class Base { }; - -class Deriverd : public Base { }; - -class NonDerived { }; - -enum enum1 -{ - one_,two_ -}; - -enum enum2 -{ - three_,four_ -}; - -struct VB -{ - virtual ~VB(){}; -}; - -struct VD : VB -{ - ~VD(){}; -}; -// -// struct non_pointer: -// used to verify that is_pointer does not return -// true for class types that implement operator void*() -// -struct non_pointer -{ - operator void*(){return this;} -}; -// -// struct non_empty: -// used to verify that is_empty does not emit -// spurious warnings or errors. -// -struct non_empty : boost::noncopyable -{ - int i; -}; - -// Steve: All comments that I (Steve Cleary) have added below are prefixed with -// "Steve:" The failures that BCB4 has on the tests are due to Borland's -// not considering cv-qual's as a part of the type -- they are considered -// compiler hints only. These failures should be fixed before long. - -int main() -{ - std::cout << "Checking type operations..." << std::endl << std::endl; - - // 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; -#ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable:4181) // qualifier applied to reference type ignored -#endif - typedef const r_type cr_type; -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif - - type_test(int, remove_reference::type) - type_test(const int, remove_reference::type) - type_test(int, remove_reference::type) - type_test(const int, remove_reference::type) - type_test(volatile int, remove_reference::type) - type_test(int, remove_reference::type) - - type_test(int, remove_const::type) - // Steve: fails on BCB4 - type_test(volatile int, remove_const::type) - // Steve: fails on BCB4 - type_test(volatile int, remove_const::type) - type_test(int, remove_const::type) - type_test(int*, remove_const::type) - type_test(int, remove_volatile::type) - // Steve: fails on BCB4 - type_test(const int, remove_volatile::type) - // Steve: fails on BCB4 - type_test(const int, remove_volatile::type) - type_test(int, remove_volatile::type) - type_test(int*, remove_volatile::type) - type_test(int, remove_cv::type) - type_test(int, remove_cv::type) - type_test(int, remove_cv::type) - type_test(int, remove_cv::type) - type_test(int*, remove_cv::type) - type_test(int*, remove_cv::type) - type_test(int*, remove_cv::type) - type_test(const int *, remove_cv::type) - type_test(int, remove_bounds::type) - type_test(int*, remove_bounds::type) - type_test(int, remove_bounds::type) - type_test(int[3], remove_bounds::type) - - std::cout << std::endl << "Checking type properties..." << std::endl << std::endl; - - value_test(true, (is_same::value)) - value_test(false, (is_same::value)) - value_test(false, (is_same::value)) - value_test(true, (is_same::value)) - value_test(false, (is_same::value)) - value_test(false, (is_same::value)) - value_test(false, (is_same::value)) - value_test(false, (is_same::value)) - value_test(false, (is_same::value)) - value_test(false, (is_same::value)) - value_test(false, (is_same::value)) - - value_test(false, is_const::value) - value_test(true, is_const::value) - value_test(false, is_const::value) - value_test(true, is_const::value) - - value_test(false, is_volatile::value) - value_test(false, is_volatile::value) - value_test(true, is_volatile::value) - value_test(true, is_volatile::value) - - value_test(true, is_void::value) - // Steve: fails on BCB4 - // JM: but looks as though it should according to [3.9.3p1]? - //value_test(false, is_void::value) - value_test(false, is_void::value) - - value_test(false, is_standard_unsigned_integral::value) - value_test(false, is_standard_unsigned_integral::value) - value_test(false, is_standard_unsigned_integral::value) - value_test(false, is_standard_unsigned_integral::value) - value_test(false, is_standard_unsigned_integral::value) - value_test(true, is_standard_unsigned_integral::value) - value_test(false, is_standard_unsigned_integral::value) - value_test(false, is_standard_unsigned_integral::value) - value_test(true, is_standard_unsigned_integral::value) - value_test(false, is_standard_unsigned_integral::value) - value_test(true, is_standard_unsigned_integral::value) - value_test(false, is_standard_unsigned_integral::value) - value_test(true, is_standard_unsigned_integral::value) - value_test(false, is_standard_unsigned_integral::value) - value_test(false, is_standard_unsigned_integral::value) - value_test(false, is_standard_unsigned_integral::value) - #ifdef ULLONG_MAX - value_test(false, is_standard_unsigned_integral::value) - value_test(false, is_standard_unsigned_integral::value) - #endif - #if defined(__BORLANDC__) || defined(_MSC_VER) - value_test(false, is_standard_unsigned_integral<__int64>::value) - value_test(false, is_standard_unsigned_integral::value) - #endif - - value_test(false, is_standard_signed_integral::value) - value_test(false, is_standard_signed_integral::value) - value_test(false, is_standard_signed_integral::value) - value_test(false, is_standard_signed_integral::value) - value_test(true, is_standard_signed_integral::value) - value_test(false, is_standard_signed_integral::value) - value_test(false, is_standard_signed_integral::value) - value_test(true, is_standard_signed_integral::value) - value_test(false, is_standard_signed_integral::value) - value_test(true, is_standard_signed_integral::value) - value_test(false, is_standard_signed_integral::value) - value_test(true, is_standard_signed_integral::value) - value_test(false, is_standard_signed_integral::value) - value_test(false, is_standard_signed_integral::value) - value_test(false, is_standard_signed_integral::value) - value_test(false, is_standard_signed_integral::value) - #ifdef ULLONG_MAX - value_test(false, is_standard_signed_integral::value) - value_test(false, is_standard_signed_integral::value) - #endif - #if defined(__BORLANDC__) || defined(_MSC_VER) - value_test(false, is_standard_signed_integral<__int64>::value) - value_test(false, is_standard_signed_integral::value) - #endif - - value_test(false, is_standard_arithmetic::value) - value_test(false, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - value_test(true, is_standard_arithmetic::value) - #ifdef ULLONG_MAX - value_test(false, is_standard_arithmetic::value) - value_test(false, is_standard_arithmetic::value) - #endif - #if defined(__BORLANDC__) || defined(_MSC_VER) - value_test(false, is_standard_arithmetic<__int64>::value) - value_test(false, is_standard_arithmetic::value) - #endif - - value_test(false, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - value_test(true, is_standard_fundamental::value) - #ifdef ULLONG_MAX - value_test(false, is_standard_fundamental::value) - value_test(false, is_standard_fundamental::value) - #endif - #if defined(__BORLANDC__) || defined(_MSC_VER) - value_test(false, is_standard_fundamental<__int64>::value) - value_test(false, is_standard_fundamental::value) - #endif - - value_test(false, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - #ifdef ULLONG_MAX - value_test(true, is_arithmetic::value) - value_test(true, is_arithmetic::value) - #endif - #if defined(__BORLANDC__) || defined(_MSC_VER) - value_test(true, is_arithmetic<__int64>::value) - value_test(true, is_arithmetic::value) - #endif - - value_test(false, is_array::value) - value_test(false, is_array::value) - value_test(false, is_array::value) - value_test(false, is_array::value) - value_test(true, is_array::value) - value_test(true, is_array::value) - value_test(true, is_array::value) - value_test(true, is_array::value) - value_test(true, is_array::value) - value_test(false, is_array::value) - - typedef void(*f1)(); - typedef int(*f2)(int); - typedef int(*f3)(int, bool); - typedef void (UDT::*mf1)(); - typedef int (UDT::*mf2)(); - typedef int (UDT::*mf3)(int); - typedef int (UDT::*mf4)(int, float); - - value_test(false, is_const::value) - value_test(false, is_reference::value) - value_test(false, is_array::value) - value_test(false, is_pointer::value) - value_test(false, is_pointer::value) - value_test(true, is_pointer::value) - value_test(true, is_pointer::value) - value_test(true, is_pointer::value) - value_test(true, is_pointer::value) - // Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1 - value_test(false, is_pointer::value) - // Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1 - value_test(false, is_pointer::value) - // Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1 - value_test(false, is_pointer::value) - // JM 02 Oct 2000: - value_test(false, is_pointer::value) - value_test(false, is_pointer::value) - value_test(false, is_pointer::value) - value_test(false, is_pointer::value) - value_test(false, is_pointer::value) - - value_test(true, is_pointer::value) - value_test(true, is_pointer::value) - value_test(true, is_pointer::value) - // Steve: was 'true', should be 'false', via 3.9.2p3 - value_test(false, is_pointer::value) - // Steve: was 'true', should be 'false', via 3.9.2p3 - value_test(false, is_pointer::value) - // Steve: was 'true', should be 'false', via 3.9.2p3 - value_test(false, is_pointer::value) - // Steve: was 'true', should be 'false', via 3.9.2p3 - value_test(false, is_pointer::value) - - value_test(false, is_reference::value) - value_test(true, is_reference::value) - value_test(true, is_reference::value) - value_test(true, is_reference::value) - value_test(true, is_reference::value) - value_test(true, is_reference::value) - value_test(true, is_reference::value) - - value_test(false, is_class::value) - value_test(false, is_class::value) - value_test(false, is_class::value) - value_test(false, is_class::value) - value_test(false, is_class::value) - value_test(false, is_class::value) - value_test(false, is_class::value) - value_test(false, is_class::value) - value_test(false, is_class::value) - value_test(false, is_class::value) - value_test(true, is_class::value) - value_test(true, is_class::value) - value_test(true, is_class::value) - value_test(true, is_class::value) - value_test(true, is_class::value) - value_test(false, is_class::value) - value_test(false, is_class::value) - value_test(false, is_class::value) - - value_test(true, is_object::value) - value_test(true, is_object::value) - value_test(false, is_object::value) - value_test(false, is_object::value) - value_test(true, is_standard_scalar::value) - value_test(true, is_extension_scalar::value) - - value_test(false, is_enum::value) - value_test(true, is_enum::value) - - value_test(false, is_member_pointer::value) - value_test(false, is_member_pointer::value) - value_test(false, is_member_pointer::value) - value_test(true, is_member_pointer::value) - value_test(true, is_member_pointer::value) - value_test(true, is_member_pointer::value) - value_test(true, is_member_pointer::value) - - value_test(false, is_empty::value) - value_test(false, is_empty::value) - value_test(false, is_empty::value) -#if defined(__MWERKS__) || defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - // apparent compiler bug causes this to fail to compile: - value_fail(false, is_empty::value) -#else - value_test(false, is_empty::value) -#endif -#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - value_fail(false, is_empty::value) -#else - value_test(false, is_empty::value) -#endif - value_test(false, is_empty::value) - value_test(false, is_empty::value) - value_test(true, is_empty::value) - value_test(true, is_empty::value) -#if defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - value_fail(true, is_empty::value) -#else - value_test(true, is_empty::value) -#endif - value_test(false, is_empty::value) - value_test(true, is_empty::value) - value_test(false, is_empty::value) - - value_test(true, has_trivial_constructor::value) - value_test(true, has_trivial_constructor::value) - value_test(true, has_trivial_constructor::value) - value_test(true, has_trivial_constructor::value) - value_test(true, has_trivial_constructor::value) - value_test(true, has_trivial_constructor::value) - value_test(true, has_trivial_constructor::value) - value_test(true, has_trivial_constructor::value) - value_test(true, has_trivial_constructor::value) - value_test(true, has_trivial_constructor::value) - value_test(false, has_trivial_constructor::value) - value_test(true, has_trivial_constructor::value) - value_test(true, has_trivial_constructor::value) - - value_test(true, has_trivial_copy::value) - value_test(true, has_trivial_copy::value) - value_test(true, has_trivial_copy::value) - value_test(true, has_trivial_copy::value) - // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10 - value_test(true, has_trivial_copy::value) - value_test(true, has_trivial_copy::value) - value_test(true, has_trivial_copy::value) - value_test(true, has_trivial_copy::value) - value_test(true, has_trivial_copy::value) - value_test(true, has_trivial_copy::value) - value_test(false, has_trivial_copy::value) - value_test(true, has_trivial_copy::value) - value_test(true, has_trivial_copy::value) - - value_test(true, has_trivial_assign::value) - value_test(true, has_trivial_assign::value) - value_test(true, has_trivial_assign::value) - value_test(true, has_trivial_assign::value) - // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10 - value_test(true, has_trivial_assign::value) - value_test(true, has_trivial_assign::value) - value_test(true, has_trivial_assign::value) - value_test(true, has_trivial_assign::value) - value_test(true, has_trivial_assign::value) - value_test(true, has_trivial_assign::value) - value_test(false, has_trivial_assign::value) - value_test(true, has_trivial_assign::value) - value_test(true, has_trivial_assign::value) - - value_test(true, has_trivial_destructor::value) - value_test(true, has_trivial_destructor::value) - value_test(true, has_trivial_destructor::value) - value_test(true, has_trivial_destructor::value) - value_test(true, has_trivial_destructor::value) - value_test(true, has_trivial_destructor::value) - value_test(true, has_trivial_destructor::value) - value_test(true, has_trivial_destructor::value) - value_test(true, has_trivial_destructor::value) - value_test(true, has_trivial_destructor::value) - value_test(false, has_trivial_destructor::value) - value_test(false, has_trivial_destructor::value) - value_test(true, has_trivial_destructor::value) - - value_test(true, is_POD::value) - value_test(true, is_POD::value) - // Steve: was 'true', should be 'false', via 3.9p10 - value_test(false, is_POD::value) - value_test(true, is_POD::value) - value_test(true, is_POD::value) - // Steve: was 'false', should be 'true', via 3.9p10 - value_test(true, is_POD::value) - // Steve: was 'true', should be 'false', via 3.9p10 - value_test(false, is_POD::value) - value_test(true, is_POD::value) - value_test(true, is_POD::value) - value_test(true, is_POD::value) - value_test(true, is_POD::value) - value_test(true, is_POD::value) - value_test(false, is_POD::value) - value_test(false, is_POD::value) - value_test(true, is_POD::value) - - value_test(true, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(false, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(false, (boost::is_convertible::value)); - value_test(false, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); -#if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) - value_test(false, (boost::is_convertible::value)); - value_test(false, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); -#endif - value_test(true, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(false, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(false, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(false, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(false, (boost::is_convertible::value)); - - value_test(false, (boost::is_convertible::value)); - value_test(false, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(false, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(true, (boost::is_convertible::value)); - value_test(false, (boost::is_convertible::value)); - - align_test(int); - align_test(char); - align_test(double); - align_test(int[4]); - align_test(int(*)(int)); -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION - align_test(char&); - align_test(char (&)(int)); - align_test(char(&)[4]); -#endif - align_test(int*); - //align_test(const int); - align_test(VB); - align_test(VD); - - std::cout << std::endl << test_count << " tests completed (" << failures << " failures)"; - return failures; -} - - - - diff --git a/type_traits_test.hpp b/type_traits_test.hpp deleted file mode 100644 index e86b83e..0000000 --- a/type_traits_test.hpp +++ /dev/null @@ -1,114 +0,0 @@ -// boost::compressed_pair test program - -// (C) Copyright John Maddock 2000. Permission to copy, use, modify, sell and -// distribute this software is granted provided this copyright notice appears -// in all copies. This software is provided "as is" without express or implied -// warranty, and with no claim as to its suitability for any purpose. - -// common test code for type_traits_test.cpp/call_traits_test.cpp/compressed_pair_test.cpp - - -#ifndef BOOST_TYPE_TRAITS_TEST_HPP -#define BOOST_TYPE_TRAITS_TEST_HPP - -// Variable declarations must come before test_align due to two-phase lookup -unsigned failures = 0; -unsigned test_count = 0; - -// -// this one is here just to suppress warnings: -// -template -bool do_compare(T i, T j) -{ - return i == j; -} - -// -// this one is to verify that a constant is indeed a -// constant-integral-expression: -// -template -struct ct_checker -{ -}; - -#define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2(X,Y) -#define BOOST_DO_JOIN2(X, Y) X##Y -#define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y ) - -#ifdef BOOST_MSVC -#define value_test(v, x) ++test_count;\ - {typedef ct_checker<(x)> this_is_a_compile_time_check_;}\ - if(!do_compare((int)v,(int)x)){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;} -#else -#define value_test(v, x) ++test_count;\ - typedef ct_checker<(x)> BOOST_JOIN(this_is_a_compile_time_check_, __LINE__);\ - if(!do_compare((int)v,(int)x)){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;} -#endif -#define value_fail(v, x) ++test_count; ++failures; std::cout << "checking value of " << #x << "...failed" << std::endl; - -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -#define type_test(v, x) ++test_count;\ - if(do_compare(boost::is_same::value, false)){\ - ++failures; \ - std::cout << "checking type of " << #x << "...failed" << std::endl; \ - std::cout << " expected type was " << #v << std::endl; \ - std::cout << " " << typeid(boost::is_same).name() << "::value is false" << std::endl; } -#else -#define type_test(v, x) ++test_count;\ - if(typeid(v) != typeid(x)){\ - ++failures; \ - std::cout << "checking type of " << #x << "...failed" << std::endl; \ - std::cout << " expected type was " << #v << std::endl; \ - std::cout << " " << "typeid(" #v ") != typeid(" #x ")" << std::endl; } -#endif - -template -struct test_align -{ - struct padded - { - char c; - T t; - }; - static void do_it() - { - padded p; - unsigned a = reinterpret_cast(&(p.t)) - reinterpret_cast(&p); - value_test(a, boost::alignment_of::value); - } -}; -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -template -struct test_align -{ - static void do_it() - { - // - // we can't do the usual test because we can't take the address - // of a reference, so check that the result is the same as for a - // pointer type instead: - value_test(boost::alignment_of::value, boost::alignment_of::value); - } -}; -#endif - -#define align_test(T) test_align::do_it() - -// -// define tests here - -// -// turn off some warnings: -#ifdef __BORLANDC__ -#pragma option -w-8004 -#endif - -#ifdef BOOST_MSVC -#pragma warning (disable: 4018) -#endif - - -#endif // BOOST_TYPE_TRAITS_TEST_HPP - diff --git a/utility.htm b/utility.htm deleted file mode 100644 index e0f090f..0000000 --- a/utility.htm +++ /dev/null @@ -1,104 +0,0 @@ - - - - -Header boost/utility.hpp Documentation - - - - -

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

- -

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

- -

Contents

- - -

Function templates next() and prior()

- -

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

- -

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

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

Usage is simple:

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

Contributed by Dave Abrahams.

- -

Class noncopyable

- -

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

- -

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

- -

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

- -

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

- -

Contributed by Dave Abrahams.

- -

Example

-
-
// inside one of your own headers ...
-#include <boost/utility.hpp>
-
-class ResourceLadenFileSystem : 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."

-
-

Revised  28 September, 2000 -

-

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

- -