forked from boostorg/utility
		
	Compare commits
	
		
			6 Commits
		
	
	
		
			svn-branch
			...
			svn-branch
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 50817f6339 | ||
|  | 2bd78704cc | ||
|  | cf7f110c89 | ||
|  | e8deb965a1 | ||
|  | 8454835ac4 | ||
|  | 13f6d43e5e | 
							
								
								
									
										423
									
								
								algo_opt_examples.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										423
									
								
								algo_opt_examples.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,423 @@ | ||||
|  | ||||
| /* | ||||
|  * | ||||
|  * 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 <iostream> | ||||
| #include <typeinfo> | ||||
| #include <algorithm> | ||||
| #include <iterator> | ||||
| #include <vector> | ||||
| #include <memory> | ||||
|  | ||||
| #include <boost/timer.hpp> | ||||
| #include <boost/type_traits.hpp> | ||||
| #include <boost/call_traits.hpp> | ||||
|  | ||||
| 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_arry: | ||||
| // The reverse of std::unitialized_copy, takes a block of | ||||
| // unitialized memory and calls destructors on all objects therein. | ||||
| // | ||||
|  | ||||
| namespace detail{ | ||||
|  | ||||
| template <bool> | ||||
| struct array_destroyer | ||||
| { | ||||
|    template <class T> | ||||
|    static void destroy_array(T* i, T* j){ do_destroy_array(i, j); } | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct array_destroyer<true> | ||||
| { | ||||
|    template <class T> | ||||
|    static void destroy_array(T*, T*){} | ||||
| }; | ||||
|  | ||||
| template <class T> | ||||
| void do_destroy_array(T* first, T* last) | ||||
| { | ||||
|    while(first != last) | ||||
|    { | ||||
|       first->~T(); | ||||
|       ++first; | ||||
|    } | ||||
| } | ||||
|  | ||||
| }; // namespace detail | ||||
|  | ||||
| template <class T> | ||||
| inline void destroy_array(T* p1, T* p2) | ||||
| { | ||||
|    detail::array_destroyer<boost::has_trivial_destructor<T>::value>::destroy_array(p1, p2); | ||||
| } | ||||
|  | ||||
| // | ||||
| // unoptimised versions of destroy_array: | ||||
| // | ||||
| template <class T> | ||||
| void destroy_array1(T* first, T* last) | ||||
| { | ||||
|    while(first != last) | ||||
|    { | ||||
|       first->~T(); | ||||
|       ++first; | ||||
|    } | ||||
| } | ||||
| template <class T> | ||||
| 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 <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); | ||||
| } | ||||
|  | ||||
| // | ||||
| // fill | ||||
| // same as std::fill, uses memset where appropriate, along with call_traits | ||||
| // to "optimise" parameter passing. | ||||
| // | ||||
| 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); | ||||
|  }; | ||||
|  | ||||
| template <bool b> | ||||
| template <typename I, typename T> | ||||
| void filler<b>::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); | ||||
| } | ||||
|  | ||||
| // | ||||
| // iter_swap: | ||||
| // tests whether iterator is a proxying iterator or not, and | ||||
| // uses optimal form accordingly: | ||||
| // | ||||
| namespace detail{ | ||||
|  | ||||
| template <bool b> | ||||
| struct swapper | ||||
| { | ||||
|    template <typename I> | ||||
|    static void do_swap(I one, I two) | ||||
|    { | ||||
|       typedef typename std::iterator_traits<I>::value_type v_t; | ||||
|       v_t v = *one; | ||||
|       *one = *two; | ||||
|       *two = v; | ||||
|    } | ||||
| }; | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
| using std::swap; | ||||
| #endif | ||||
|  | ||||
| template <> | ||||
| struct swapper<true> | ||||
| { | ||||
|    template <typename I> | ||||
|    static void do_swap(I one, I two) | ||||
|    { | ||||
|       using std::swap; | ||||
|       swap(*one, *two); | ||||
|    } | ||||
| }; | ||||
|  | ||||
| } | ||||
|  | ||||
| template <typename I1, typename I2> | ||||
| inline void iter_swap(I1 one, I2 two) | ||||
| { | ||||
|    typedef typename std::iterator_traits<I1>::reference r1_t; | ||||
|    typedef typename std::iterator_traits<I2>::reference r2_t; | ||||
|    enum{ can_opt = boost::is_reference<r1_t>::value && boost::is_reference<r2_t>::value && boost::is_same<r1_t, r2_t>::value }; | ||||
|    detail::swapper<can_opt>::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<int>: " << 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<int>(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<int>(unoptimised#2): " << result << endl << endl; | ||||
|  | ||||
|    cout << "testing fill(char)...\n" | ||||
|    "[Some standard library versions may already perform this optimisation.]" << endl; | ||||
|    /*cache load*/ opt::fill<char*, char>(c_array, c_array + array_size, (char)3); | ||||
|    t.restart(); | ||||
|    for(i = 0; i < iter_count; ++i) | ||||
|    { | ||||
|       opt::fill<char*, char>(c_array, c_array + array_size, (char)3); | ||||
|    } | ||||
|    result = t.elapsed(); | ||||
|    cout << "opt::fill<char*, char>: " << 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<char*, char>: " << 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<int*, int>(i_array, i_array + array_size, 3); | ||||
|    t.restart(); | ||||
|    for(i = 0; i < iter_count; ++i) | ||||
|    { | ||||
|       opt::fill<int*, int>(i_array, i_array + array_size, 3); | ||||
|    } | ||||
|    result = t.elapsed(); | ||||
|    cout << "opt::fill<int*, int>: " << 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<int*, int>: " << result << endl << endl; | ||||
|  | ||||
|    cout << "testing copy...\n" | ||||
|    "[Some standard library versions may already perform this optimisation.]" << endl; | ||||
|    /*cache load*/ opt::copy<const int*, int*>(ci_array, ci_array + array_size, i_array); | ||||
|    t.restart(); | ||||
|    for(i = 0; i < iter_count; ++i) | ||||
|    { | ||||
|       opt::copy<const int*, int*>(ci_array, ci_array + array_size, i_array); | ||||
|    } | ||||
|    result = t.elapsed(); | ||||
|    cout << "opt::copy<const int*, int*>: " << result << endl; | ||||
|    /*cache load*/ std::copy<const int*, int*>(ci_array, ci_array + array_size, i_array); | ||||
|    t.restart(); | ||||
|    for(i = 0; i < iter_count; ++i) | ||||
|    { | ||||
|       std::copy<const int*, int*>(ci_array, ci_array + array_size, i_array); | ||||
|    } | ||||
|    result = t.elapsed(); | ||||
|    cout << "std::copy<const int*, int*>: " << result << endl; | ||||
|    /*cache load*/ opt::detail::copier<false>::template do_copy<const int*, int*>(ci_array, ci_array + array_size, i_array); | ||||
|    t.restart(); | ||||
|    for(i = 0; i < iter_count; ++i) | ||||
|    { | ||||
|       opt::detail::copier<false>::template do_copy<const int*, int*>(ci_array, ci_array + array_size, i_array); | ||||
|    } | ||||
|    result = t.elapsed(); | ||||
|    cout << "standard \"unoptimised\" copy: " << result << endl << endl; | ||||
|  | ||||
|    /*cache load*/ opt::copy<const char*, char*>(cc_array, cc_array + array_size, c_array); | ||||
|    t.restart(); | ||||
|    for(i = 0; i < iter_count; ++i) | ||||
|    { | ||||
|       opt::copy<const char*, char*>(cc_array, cc_array + array_size, c_array); | ||||
|    } | ||||
|    result = t.elapsed(); | ||||
|    cout << "opt::copy<const char*, char*>: " << result << endl; | ||||
|    /*cache load*/ std::copy<const char*, char*>(cc_array, cc_array + array_size, c_array); | ||||
|    t.restart(); | ||||
|    for(i = 0; i < iter_count; ++i) | ||||
|    { | ||||
|       std::copy<const char*, char*>(cc_array, cc_array + array_size, c_array); | ||||
|    } | ||||
|    result = t.elapsed(); | ||||
|    cout << "std::copy<const char*, char*>: " << result << endl; | ||||
|    /*cache load*/ opt::detail::copier<false>::template do_copy<const char*, char*>(cc_array, cc_array + array_size, c_array); | ||||
|    t.restart(); | ||||
|    for(i = 0; i < iter_count; ++i) | ||||
|    { | ||||
|       opt::detail::copier<false>::template do_copy<const char*, char*>(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<int> v1; | ||||
|    v1.push_back(0); | ||||
|    v1.push_back(1); | ||||
|    std::vector<bool> 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(); | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										368
									
								
								call_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										368
									
								
								call_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,368 @@ | ||||
|  | ||||
| #include <cassert> | ||||
| #include <iostream> | ||||
| #include <iomanip> | ||||
| #include <algorithm> | ||||
| #include <typeinfo> | ||||
| #include <boost/call_traits.hpp> | ||||
|  | ||||
| #ifdef __BORLANDC__ | ||||
| // turn off some warnings, the way we do the tests will generate a *lot* of these | ||||
| // this is a result of the tests not call_traits itself.... | ||||
| #pragma option -w-8004 -w-ccc -w-rch -w-eff -w-aus | ||||
| #endif | ||||
|  | ||||
| // | ||||
| // 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 <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()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 <class T, std::size_t N> | ||||
| struct contained<T[N]> | ||||
| { | ||||
|    typedef typename boost::call_traits<T[N]>::param_type       param_type; | ||||
|    typedef typename boost::call_traits<T[N]>::reference        reference; | ||||
|    typedef typename boost::call_traits<T[N]>::const_reference  const_reference; | ||||
|    typedef T                                                   value_type[N]; | ||||
|    typedef typename boost::call_traits<T[N]>::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 <class T> | ||||
| contained<typename boost::call_traits<T>::value_type> wrap(const T& t) | ||||
| { | ||||
|    typedef typename boost::call_traits<T>::value_type ct; | ||||
|    return contained<ct>(t); | ||||
| } | ||||
|  | ||||
| namespace test{ | ||||
|  | ||||
| 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); | ||||
| } | ||||
|  | ||||
| } // namespace test | ||||
|  | ||||
| using namespace std; | ||||
|  | ||||
| // | ||||
| // struct checker: | ||||
| // verifies behaviour of contained example: | ||||
| // | ||||
| template <class T> | ||||
| struct checker | ||||
| { | ||||
|    typedef typename boost::call_traits<T>::param_type param_type; | ||||
|    void operator()(param_type); | ||||
| }; | ||||
|  | ||||
| template <class T> | ||||
| void checker<T>::operator()(param_type p) | ||||
| { | ||||
|    T t(p); | ||||
|    contained<T> 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<T>::v_).name() << endl; | ||||
|    cout << "typeof contained<" << typeid(T).name() << ">::value() is:      " << typeid(&contained<T>::value).name() << endl; | ||||
|    cout << "typeof contained<" << typeid(T).name() << ">::get() is:        " << typeid(&contained<T>::get).name() << endl; | ||||
|    cout << "typeof contained<" << typeid(T).name() << ">::const_get() is:  " << typeid(&contained<T>::const_get).name() << endl; | ||||
|    cout << "typeof contained<" << typeid(T).name() << ">::call() is:       " << typeid(&contained<T>::call).name() << endl; | ||||
|    cout << endl; | ||||
| } | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template <class T, std::size_t N> | ||||
| struct checker<T[N]> | ||||
| { | ||||
|    typedef typename boost::call_traits<T[N]>::param_type param_type; | ||||
|    void operator()(param_type t) | ||||
|    { | ||||
|       contained<T[N]> 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<T[N]>::v_).name() << endl; | ||||
|       cout << "typeof contained<" << typeid(T[N]).name() << ">::value is:      " << typeid(&contained<T[N]>::value).name() << endl; | ||||
|       cout << "typeof contained<" << typeid(T[N]).name() << ">::get is:        " << typeid(&contained<T[N]>::get).name() << endl; | ||||
|       cout << "typeof contained<" << typeid(T[N]).name() << ">::const_get is:  " << typeid(&contained<T[N]>::const_get).name() << endl; | ||||
|       cout << "typeof contained<" << typeid(T[N]).name() << ">::call is:       " << typeid(&contained<T[N]>::call).name() << endl; | ||||
|       cout << endl; | ||||
|    } | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| // | ||||
| // check_wrap: | ||||
| template <class T, class U> | ||||
| void check_wrap(const contained<T>& w, const U& u) | ||||
| { | ||||
|    cout << "checking contained<" << typeid(T).name() << ">..." << endl; | ||||
|    assert(w.value() == u); | ||||
| } | ||||
|  | ||||
| // | ||||
| // check_make_pair: | ||||
| // verifies behaviour of "make_pair": | ||||
| // | ||||
| template <class T, class U, class V> | ||||
| 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_; } | ||||
| }; | ||||
|  | ||||
| // | ||||
| // define tests here | ||||
| unsigned failures = 0; | ||||
| unsigned test_count = 0; | ||||
|  | ||||
| #define value_test(v, x) ++test_count;\ | ||||
|                          if(v != x){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;} | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| #define type_test(v, x)  ++test_count;\ | ||||
|                            if(boost::is_same<v, x>::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<v, x>).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 | ||||
|  | ||||
| int main() | ||||
| { | ||||
|    checker<UDT> c1; | ||||
|    UDT u; | ||||
|    c1(u); | ||||
|    checker<int> c2; | ||||
|    int i = 2; | ||||
|    c2(i); | ||||
|    int* pi = &i; | ||||
|    checker<int*> c3; | ||||
|    c3(pi); | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|    checker<int&> c4; | ||||
|    c4(i); | ||||
|    checker<const int&> c5; | ||||
|    c5(i); | ||||
|  | ||||
|    int a[2] = {1,2}; | ||||
|    checker<int[2]> c6; | ||||
|    c6(a); | ||||
| #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<UDT>::value_type) | ||||
|    type_test(UDT&, boost::call_traits<UDT>::reference) | ||||
|    type_test(const UDT&, boost::call_traits<UDT>::const_reference) | ||||
|    type_test(const UDT&, boost::call_traits<UDT>::param_type) | ||||
|    type_test(int, boost::call_traits<int>::value_type) | ||||
|    type_test(int&, boost::call_traits<int>::reference) | ||||
|    type_test(const int&, boost::call_traits<int>::const_reference) | ||||
|    type_test(const int, boost::call_traits<int>::param_type) | ||||
|    type_test(int*, boost::call_traits<int*>::value_type) | ||||
|    type_test(int*&, boost::call_traits<int*>::reference) | ||||
|    type_test(int*const&, boost::call_traits<int*>::const_reference) | ||||
|    type_test(int*const, boost::call_traits<int*>::param_type) | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|    type_test(int&, boost::call_traits<int&>::value_type) | ||||
|    type_test(int&, boost::call_traits<int&>::reference) | ||||
|    type_test(const int&, boost::call_traits<int&>::const_reference) | ||||
|    type_test(int&, boost::call_traits<int&>::param_type) | ||||
| #if !(defined(__GNUC__) && (__GNUC__ < 3)) | ||||
|    type_test(int&, boost::call_traits<cr_type>::value_type) | ||||
|    type_test(int&, boost::call_traits<cr_type>::reference) | ||||
|    type_test(const int&, boost::call_traits<cr_type>::const_reference) | ||||
|    type_test(int&, boost::call_traits<cr_type>::param_type) | ||||
| #else | ||||
|    std::cout << "GNU C++ cannot instantiate call_traits<cr_type>, skipping four tests (4 errors)" << std::endl; | ||||
|    failures += 4; | ||||
|    test_count += 4; | ||||
| #endif | ||||
|    type_test(const int&, boost::call_traits<const int&>::value_type) | ||||
|    type_test(const int&, boost::call_traits<const int&>::reference) | ||||
|    type_test(const int&, boost::call_traits<const int&>::const_reference) | ||||
|    type_test(const int&, boost::call_traits<const int&>::param_type) | ||||
|    type_test(const int*, boost::call_traits<int[3]>::value_type) | ||||
|    type_test(int(&)[3], boost::call_traits<int[3]>::reference) | ||||
|    type_test(const int(&)[3], boost::call_traits<int[3]>::const_reference) | ||||
|    type_test(const int*const, boost::call_traits<int[3]>::param_type) | ||||
|    type_test(const int*, boost::call_traits<const int[3]>::value_type) | ||||
|    type_test(const int(&)[3], boost::call_traits<const int[3]>::reference) | ||||
|    type_test(const int(&)[3], boost::call_traits<const int[3]>::const_reference) | ||||
|    type_test(const int*const, boost::call_traits<const int[3]>::param_type) | ||||
| #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 <typename T, bool isarray = false> | ||||
| struct call_traits_test | ||||
| { | ||||
|    static void assert_construct(boost::call_traits<T>::param_type val); | ||||
| }; | ||||
|  | ||||
| template <typename T, bool isarray> | ||||
| void call_traits_test<T, isarray>::assert_construct(boost::call_traits<T>::param_type val) | ||||
| { | ||||
|    // | ||||
|    // this is to check that the call_traits assertions are valid: | ||||
|    T t(val); | ||||
|    boost::call_traits<T>::value_type v(t); | ||||
|    boost::call_traits<T>::reference r(t); | ||||
|    boost::call_traits<T>::const_reference cr(t); | ||||
|    boost::call_traits<T>::param_type p(t); | ||||
|    boost::call_traits<T>::value_type v2(v); | ||||
|    boost::call_traits<T>::value_type v3(r); | ||||
|    boost::call_traits<T>::value_type v4(p); | ||||
|    boost::call_traits<T>::reference r2(v); | ||||
|    boost::call_traits<T>::reference r3(r); | ||||
|    boost::call_traits<T>::const_reference cr2(v); | ||||
|    boost::call_traits<T>::const_reference cr3(r); | ||||
|    boost::call_traits<T>::const_reference cr4(cr); | ||||
|    boost::call_traits<T>::const_reference cr5(p); | ||||
|    boost::call_traits<T>::param_type p2(v); | ||||
|    boost::call_traits<T>::param_type p3(r); | ||||
|    boost::call_traits<T>::param_type p4(p); | ||||
| } | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template <typename T> | ||||
| struct call_traits_test<T, true> | ||||
| { | ||||
|    static void assert_construct(boost::call_traits<T>::param_type val); | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| void call_traits_test<T, true>::assert_construct(boost::call_traits<T>::param_type val) | ||||
| { | ||||
|    // | ||||
|    // this is to check that the call_traits assertions are valid: | ||||
|    T t; | ||||
|    boost::call_traits<T>::value_type v(t); | ||||
|    boost::call_traits<T>::value_type v5(val); | ||||
|    boost::call_traits<T>::reference r = t; | ||||
|    boost::call_traits<T>::const_reference cr = t; | ||||
|    boost::call_traits<T>::reference r2 = r; | ||||
|    #ifndef __BORLANDC__ | ||||
|    // C++ Builder buglet: | ||||
|    boost::call_traits<T>::const_reference cr2 = r; | ||||
|    #endif | ||||
|    boost::call_traits<T>::param_type p(t); | ||||
|    boost::call_traits<T>::value_type v2(v); | ||||
|    boost::call_traits<T>::const_reference cr3 = cr; | ||||
|    boost::call_traits<T>::value_type v3(r); | ||||
|    boost::call_traits<T>::value_type v4(p); | ||||
|    boost::call_traits<T>::param_type p2(v); | ||||
|    boost::call_traits<T>::param_type p3(r); | ||||
|    boost::call_traits<T>::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<int>; | ||||
| template struct call_traits_test<const int>; | ||||
| template struct call_traits_test<int*>; | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template struct call_traits_test<int&>; | ||||
| template struct call_traits_test<const int&>; | ||||
| template struct call_traits_test<int[2], true>; | ||||
| #endif | ||||
|  | ||||
|  | ||||
							
								
								
									
										149
									
								
								cast_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								cast_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| //  boost utility cast 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 | ||||
| //   28 Jun 00  implicit_cast removed (Beman Dawes) | ||||
| //   30 Aug 99  value_cast replaced by numeric_cast | ||||
| //    3 Aug 99  Initial Version | ||||
|  | ||||
| #include <iostream> | ||||
| #include <climits> | ||||
| #include <limits> | ||||
| #include <boost/cast.hpp> | ||||
|  | ||||
| #  if SCHAR_MAX == LONG_MAX | ||||
| #      error "This test program doesn't work if SCHAR_MAX == LONG_MAX" | ||||
| #  endif  | ||||
|  | ||||
| using namespace boost; | ||||
| using std::cout; | ||||
|  | ||||
| namespace | ||||
| { | ||||
|     struct Base | ||||
|     {  | ||||
|         virtual char kind() { return 'B'; } | ||||
|     }; | ||||
|      | ||||
|     struct Base2 | ||||
|     {  | ||||
|         virtual char kind2() { return '2'; } | ||||
|     }; | ||||
|      | ||||
|     struct Derived : public Base, Base2 | ||||
|     { | ||||
|         virtual char kind() { return 'D'; } | ||||
|     };  | ||||
| }    | ||||
|  | ||||
|  | ||||
| int main( int argc, char * argv[] ) | ||||
| { | ||||
|     cout << "Usage: test_casts [n], where n omitted or is:\n" | ||||
|             "  1 = execute #1 assert failure (#ifndef NDEBUG)\n" | ||||
|             "  2 = execute #2 assert failure (#ifndef NDEBUG)\n" | ||||
|             "Example: test_casts 2\n\n"; | ||||
|  | ||||
| #   ifdef NDEBUG | ||||
|         cout << "NDEBUG is defined\n"; | ||||
| #   else | ||||
|         cout << "NDEBUG is not defined\n"; | ||||
| #   endif | ||||
|  | ||||
|     cout << "\nBeginning tests...\n";         | ||||
|  | ||||
| //  test polymorphic_cast  ---------------------------------------------------// | ||||
|      | ||||
|     //  tests which should succeed | ||||
|     Base *    base = new Derived; | ||||
|     Base2 *   base2 = 0; | ||||
|     Derived * derived = 0; | ||||
|     derived = polymorphic_downcast<Derived*>( base );  // downcast | ||||
|     assert( derived->kind() == 'D' ); | ||||
|  | ||||
|     derived = 0; | ||||
|     derived = polymorphic_cast<Derived*>( base ); // downcast, throw on error | ||||
|     assert( derived->kind() == 'D' ); | ||||
|  | ||||
|     base2 = polymorphic_cast<Base2*>( base ); // crosscast | ||||
|     assert( base2->kind2() == '2' ); | ||||
|  | ||||
|      //  tests which should result in errors being detected | ||||
|     int err_count = 0; | ||||
|     base = new Base; | ||||
|  | ||||
|     if ( argc > 1 && *argv[1] == '1' ) | ||||
|         { derived = polymorphic_downcast<Derived*>( base ); } // #1 assert failure | ||||
|  | ||||
|     bool caught_exception = false; | ||||
|     try { derived = polymorphic_cast<Derived*>( base ); } | ||||
|     catch (std::bad_cast) | ||||
|         { cout<<"caught bad_cast\n"; caught_exception = true; } | ||||
|     if ( !caught_exception ) ++err_count; | ||||
|     //  the following is just so generated code can be inspected | ||||
|     if ( derived->kind() == 'B' ) ++err_count; | ||||
|  | ||||
| //  test implicit_cast and numeric_cast  -------------------------------------// | ||||
|      | ||||
|     //  tests which should succeed | ||||
|     long small_value = 1; | ||||
|     long small_negative_value = -1; | ||||
|     long large_value = std::numeric_limits<long>::max(); | ||||
|     long large_negative_value = std::numeric_limits<long>::min(); | ||||
|     signed char c = 0; | ||||
|  | ||||
|     c = large_value;  // see if compiler generates warning | ||||
|  | ||||
|     c = numeric_cast<signed char>( small_value ); | ||||
|     assert( c == 1 ); | ||||
|     c = 0; | ||||
|     c = numeric_cast<signed char>( small_value ); | ||||
|     assert( c == 1 ); | ||||
|     c = 0; | ||||
|     c = numeric_cast<signed char>( small_negative_value ); | ||||
|     assert( c == -1 ); | ||||
|  | ||||
|     //  tests which should result in errors being detected | ||||
|  | ||||
|     caught_exception = false; | ||||
|     try { c = numeric_cast<signed char>( large_value ); } | ||||
|     catch (bad_numeric_cast) | ||||
|         { cout<<"caught bad_numeric_cast #1\n"; caught_exception = true; } | ||||
|     if ( !caught_exception ) ++err_count; | ||||
|  | ||||
|     caught_exception = false; | ||||
|     try { c = numeric_cast<signed char>( large_negative_value ); } | ||||
|     catch (bad_numeric_cast) | ||||
|         { cout<<"caught bad_numeric_cast #2\n"; caught_exception = true; } | ||||
|     if ( !caught_exception ) ++err_count; | ||||
|  | ||||
|     unsigned long ul; | ||||
|     caught_exception = false; | ||||
|     try { ul = numeric_cast<unsigned long>( large_negative_value ); } | ||||
|     catch (bad_numeric_cast) | ||||
|         { cout<<"caught bad_numeric_cast #3\n"; caught_exception = true; } | ||||
|     if ( !caught_exception ) ++err_count; | ||||
|  | ||||
|     caught_exception = false; | ||||
|     try { ul = numeric_cast<unsigned long>( small_negative_value ); } | ||||
|     catch (bad_numeric_cast) | ||||
|         { cout<<"caught bad_numeric_cast #4\n"; caught_exception = true; } | ||||
|     if ( !caught_exception ) ++err_count; | ||||
|  | ||||
|     caught_exception = false; | ||||
|     try { numeric_cast<int>( std::numeric_limits<double>::max() ); } | ||||
|     catch (bad_numeric_cast) | ||||
|         { cout<<"caught bad_numeric_cast #5\n"; caught_exception = true; } | ||||
|     if ( !caught_exception ) ++err_count; | ||||
|  | ||||
|     cout << err_count << " errors detected\nTest " | ||||
|          << (err_count==0 ? "passed\n" : "failed\n"); | ||||
|     return err_count; | ||||
| }   // main | ||||
| @@ -1,23 +1,51 @@ | ||||
|  // 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.    | ||||
| // boost::compressed_pair test program | ||||
|  | ||||
| // standalone test program for <boost/compressed_pair.hpp> | ||||
| // Revised 03 Oct 2000:  | ||||
| //    Enabled tests for VC6. | ||||
| //  (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. | ||||
|  | ||||
| #include <iostream> | ||||
| #include <typeinfo> | ||||
| #include <cassert> | ||||
|  | ||||
| #include <boost/compressed_pair.hpp> | ||||
| #include <boost/type_traits/type_traits_test.hpp> | ||||
|  | ||||
| using namespace boost; | ||||
|  | ||||
| #ifdef __BORLANDC__ | ||||
| #pragma option -w-ccc -w-rch -w-eff -w-aus | ||||
| #endif | ||||
|  | ||||
| // | ||||
| // define tests here | ||||
| unsigned failures = 0; | ||||
| unsigned test_count = 0; | ||||
|  | ||||
| #define value_test(v, x) ++test_count;\ | ||||
|                          if(v != x){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;} | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| #define type_test(v, x)  ++test_count;\ | ||||
|                          if(boost::is_same<v, x>::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<v, x>).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 | ||||
|  | ||||
| struct empty_POD_UDT{}; | ||||
| struct empty_UDT | ||||
| { | ||||
|   ~empty_UDT(){}; | ||||
| }; | ||||
| namespace boost { | ||||
| #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION | ||||
| template <> struct is_empty<empty_UDT> | ||||
| @@ -36,25 +64,8 @@ template <> struct is_POD<empty_POD_UDT> | ||||
| #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(int argc, char *argv[ ]) | ||||
| int main() | ||||
| { | ||||
|    compressed_pair<int, double> cp1(1, 1.3); | ||||
|    assert(cp1.first() == 1); | ||||
| @@ -67,25 +78,15 @@ int main(int argc, char *argv[ ]) | ||||
|    assert(cp1b.second() == 1.3); | ||||
|    assert(cp1.first() == 2); | ||||
|    assert(cp1.second() == 2.3); | ||||
|    compressed_pair<non_empty1, non_empty2> cp1c(non_empty1(9)); | ||||
|    assert(cp1c.second() == non_empty2()); | ||||
|    assert(cp1c.first() == non_empty1(9)); | ||||
|    compressed_pair<non_empty1, non_empty2> cp1d(non_empty2(9)); | ||||
|    assert(cp1d.second() == non_empty2(9)); | ||||
|    assert(cp1d.first() == non_empty1()); | ||||
|  | ||||
|    compressed_pair<int, double> cp1e(cp1); | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|    compressed_pair<empty_UDT, int> cp2(2); | ||||
|    assert(cp2.second() == 2); | ||||
| #endif | ||||
|    compressed_pair<int, empty_UDT> cp3(1); | ||||
|    assert(cp3.first() ==1); | ||||
|    compressed_pair<empty_UDT, empty_UDT> cp4; | ||||
|    compressed_pair<empty_UDT, empty_POD_UDT> cp5; | ||||
|    compressed_pair<int, empty_UDT> cp9(empty_UDT()); | ||||
|    compressed_pair<int, empty_UDT> cp10(1); | ||||
|    assert(cp10.first() == 1); | ||||
| #if defined(BOOST_MSVC6_MEMBER_TEMPLATES) || !defined(BOOST_NO_MEMBER_TEMPLATES) || !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|    int i = 0; | ||||
|    compressed_pair<int&, int&> cp6(i,i); | ||||
|    assert(cp6.first() == i); | ||||
| @@ -96,43 +97,33 @@ int main(int argc, char *argv[ ]) | ||||
|    cp7.first(); | ||||
|    double* pd = cp7.second(); | ||||
| #endif | ||||
|    soft_value_test(true, (sizeof(compressed_pair<empty_UDT, int>) < sizeof(std::pair<empty_UDT, int>))) | ||||
|    soft_value_test(true, (sizeof(compressed_pair<int, empty_UDT>) < sizeof(std::pair<int, empty_UDT>))) | ||||
|    soft_value_test(true, (sizeof(compressed_pair<empty_UDT, empty_UDT>) < sizeof(std::pair<empty_UDT, empty_UDT>))) | ||||
|    soft_value_test(true, (sizeof(compressed_pair<empty_UDT, empty_POD_UDT>) < sizeof(std::pair<empty_UDT, empty_POD_UDT>))) | ||||
|    soft_value_test(true, (sizeof(compressed_pair<empty_UDT, compressed_pair<empty_POD_UDT, int> >) < sizeof(std::pair<empty_UDT, std::pair<empty_POD_UDT, int> >))) | ||||
|    value_test(true, (sizeof(compressed_pair<empty_UDT, int>) < sizeof(std::pair<empty_UDT, int>))) | ||||
|    value_test(true, (sizeof(compressed_pair<int, empty_UDT>) < sizeof(std::pair<int, empty_UDT>))) | ||||
|    value_test(true, (sizeof(compressed_pair<empty_UDT, empty_UDT>) < sizeof(std::pair<empty_UDT, empty_UDT>))) | ||||
|    value_test(true, (sizeof(compressed_pair<empty_UDT, empty_POD_UDT>) < sizeof(std::pair<empty_UDT, empty_POD_UDT>))) | ||||
|    value_test(true, (sizeof(compressed_pair<empty_UDT, compressed_pair<empty_POD_UDT, int> >) < sizeof(std::pair<empty_UDT, std::pair<empty_POD_UDT, int> >))) | ||||
|  | ||||
|    return check_result(argc, argv); | ||||
|    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<int, double>; | ||||
| template class compressed_pair<int, int>; | ||||
| template class compressed_pair<empty_UDT, int>; | ||||
| template class compressed_pair<int, empty_UDT>; | ||||
| template class compressed_pair<empty_UDT, empty_UDT>; | ||||
| template class compressed_pair<empty_UDT, empty_POD_UDT>; | ||||
| #else | ||||
| template class boost::compressed_pair<int, double>; | ||||
| template class boost::compressed_pair<int, int>; | ||||
| template class boost::compressed_pair<empty_UDT, int>; | ||||
| template class boost::compressed_pair<int, empty_UDT>; | ||||
| template class boost::compressed_pair<empty_UDT, empty_UDT>; | ||||
| template class boost::compressed_pair<empty_UDT, empty_POD_UDT>; | ||||
| #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<double, int&>::first(); | ||||
| template int& compressed_pair<double, int&>::second(); | ||||
| #if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)) | ||||
| template compressed_pair<double, int&>::compressed_pair(int&); | ||||
| #endif | ||||
| template compressed_pair<double, int&>::compressed_pair(call_traits<double>::param_type,int&); | ||||
| // | ||||
| // and then arrays: | ||||
| @@ -140,15 +131,10 @@ template compressed_pair<double, int&>::compressed_pair(call_traits<double>::par | ||||
| template call_traits<int[2]>::reference compressed_pair<double, int[2]>::second(); | ||||
| #endif | ||||
| template call_traits<double>::reference compressed_pair<double, int[2]>::first(); | ||||
| #if !(defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ < 95)) | ||||
| template compressed_pair<double, int[2]>::compressed_pair(call_traits<double>::param_type); | ||||
| #endif | ||||
| template compressed_pair<double, int[2]>::compressed_pair(const double&); | ||||
| template compressed_pair<double, int[2]>::compressed_pair(); | ||||
| #endif // __MWERKS__ | ||||
| #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|  | ||||
| unsigned int expected_failures = 0; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										23
									
								
								include/boost/call_traits.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								include/boost/call_traits.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| //  (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and | ||||
| //  distribute this software is granted provided this copyright notice appears | ||||
| //  in all copies. This software is provided "as is" without express or implied | ||||
| //  warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
| //  See boost/detail/call_traits.hpp and boost/detail/ob_call_traits.hpp | ||||
| //  for full copyright notices. | ||||
|  | ||||
| #ifndef BOOST_CALL_TRAITS_HPP | ||||
| #define BOOST_CALL_TRAITS_HPP | ||||
|  | ||||
| #ifndef BOOST_CONFIG_HPP | ||||
| #include <boost/config.hpp> | ||||
| #endif | ||||
|  | ||||
| #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| #include <boost/detail/ob_call_traits.hpp> | ||||
| #else | ||||
| #include <boost/detail/call_traits.hpp> | ||||
| #endif | ||||
|  | ||||
| #endif // BOOST_CALL_TRAITS_HPP | ||||
							
								
								
									
										23
									
								
								include/boost/compressed_pair.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								include/boost/compressed_pair.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| //  (C) Copyright Boost.org 2000. Permission to copy, use, modify, sell and | ||||
| //  distribute this software is granted provided this copyright notice appears | ||||
| //  in all copies. This software is provided "as is" without express or implied | ||||
| //  warranty, and with no claim as to its suitability for any purpose. | ||||
|  | ||||
| //  See http://www.boost.org for most recent version including documentation. | ||||
| //  See boost/detail/compressed_pair.hpp and boost/detail/ob_compressed_pair.hpp | ||||
| //  for full copyright notices. | ||||
|  | ||||
| #ifndef BOOST_COMPRESSED_PAIR_HPP | ||||
| #define BOOST_COMPRESSED_PAIR_HPP | ||||
|  | ||||
| #ifndef BOOST_CONFIG_HPP | ||||
| #include <boost/config.hpp> | ||||
| #endif | ||||
|  | ||||
| #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| #include <boost/detail/ob_compressed_pair.hpp> | ||||
| #else | ||||
| #include <boost/detail/compressed_pair.hpp> | ||||
| #endif | ||||
|  | ||||
| #endif // BOOST_COMPRESSED_PAIR_HPP | ||||
							
								
								
									
										135
									
								
								include/boost/detail/call_traits.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								include/boost/detail/call_traits.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,135 @@ | ||||
| //  (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. | ||||
|  | ||||
| /* Release notes: | ||||
|    23rd July 2000: | ||||
|       Fixed array specialization. (JM) | ||||
|       Added Borland specific fixes for reference types | ||||
|       (issue raised by Steve Cleary). | ||||
| */ | ||||
|  | ||||
| #ifndef BOOST_DETAIL_CALL_TRAITS_HPP | ||||
| #define BOOST_DETAIL_CALL_TRAITS_HPP | ||||
|  | ||||
| #ifndef BOOST_CONFIG_HPP | ||||
| #include <boost/config.hpp> | ||||
| #endif | ||||
|  | ||||
| #ifndef BOOST_TYPE_TRAITS_HPP | ||||
| #include <boost/type_traits.hpp> | ||||
| #endif | ||||
|  | ||||
| namespace boost{ | ||||
|  | ||||
| namespace detail{ | ||||
|  | ||||
| template <typename T, bool isp, bool b1, bool b2> | ||||
| struct ct_imp | ||||
| { | ||||
|    typedef const T& param_type; | ||||
| }; | ||||
|  | ||||
| template <typename T, bool isp> | ||||
| struct ct_imp<T, isp, true, true> | ||||
| { | ||||
|    typedef T const param_type; | ||||
| }; | ||||
|  | ||||
| template <typename T, bool b1, bool b2> | ||||
| struct ct_imp<T, true, b1, b2> | ||||
| { | ||||
|    typedef T const param_type; | ||||
| }; | ||||
|  | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| struct call_traits | ||||
| { | ||||
| public: | ||||
|    typedef T value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    // | ||||
|    // C++ Builder workaround: we should be able to define a compile time | ||||
|    // constant and pass that as a single template parameter to ct_imp<T,bool>, | ||||
|    // however compiler bugs prevent this - instead pass three bool's to | ||||
|    // ct_imp<T,bool,bool,bool> and add an extra partial specialisation | ||||
|    // of ct_imp to handle the logic. (JM) | ||||
|    typedef typename detail::ct_imp<T, ::boost::is_pointer<typename remove_const<T>::type>::value, ::boost::is_arithmetic<typename remove_const<T>::type>::value, sizeof(T) <= sizeof(void*)>::param_type param_type; | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| struct call_traits<T&> | ||||
| { | ||||
|    typedef T& value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    typedef T& param_type;  // hh removed const | ||||
| }; | ||||
|  | ||||
| #if defined(__BORLANDC__) && (__BORLANDC__ <= 0x550) | ||||
| // these are illegal specialisations; cv-qualifies applied to | ||||
| // references have no effect according to [8.3.2p1], | ||||
| // C++ Builder requires them though as it treats cv-qualified | ||||
| // references as distinct types... | ||||
| template <typename T> | ||||
| struct call_traits<T&const> | ||||
| { | ||||
|    typedef T& value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    typedef T& param_type;  // hh removed const | ||||
| }; | ||||
| template <typename T> | ||||
| struct call_traits<T&volatile> | ||||
| { | ||||
|    typedef T& value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    typedef T& param_type;  // hh removed const | ||||
| }; | ||||
| template <typename T> | ||||
| struct call_traits<T&const volatile> | ||||
| { | ||||
|    typedef T& value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    typedef T& param_type;  // hh removed const | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| template <typename T, std::size_t N> | ||||
| struct call_traits<T [N]> | ||||
| { | ||||
| private: | ||||
|    typedef T array_type[N]; | ||||
| public: | ||||
|    // degrades array to pointer: | ||||
|    typedef const T* value_type; | ||||
|    typedef array_type& reference; | ||||
|    typedef const array_type& const_reference; | ||||
|    typedef const T* const param_type; | ||||
| }; | ||||
|  | ||||
| template <typename T, std::size_t N> | ||||
| struct call_traits<const T [N]> | ||||
| { | ||||
| private: | ||||
|    typedef const T array_type[N]; | ||||
| public: | ||||
|    // degrades array to pointer: | ||||
|    typedef const T* value_type; | ||||
|    typedef array_type& reference; | ||||
|    typedef const array_type& const_reference; | ||||
|    typedef const T* const param_type; | ||||
| }; | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // BOOST_DETAIL_CALL_TRAITS_HPP | ||||
							
								
								
									
										420
									
								
								include/boost/detail/compressed_pair.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										420
									
								
								include/boost/detail/compressed_pair.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,420 @@ | ||||
| //  (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. | ||||
|  | ||||
| // | ||||
| // JM changes 25 Jan 2000: | ||||
| // Removed default arguments from compressed_pair_switch to get | ||||
| // C++ Builder 4 to accept them | ||||
| // rewriten swap to get gcc and C++ builder to compile. | ||||
| // added partial specialisations for case T1 == T2 to avoid duplicate constructor defs. | ||||
|  | ||||
| #ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP | ||||
| #define BOOST_DETAIL_COMPRESSED_PAIR_HPP | ||||
|  | ||||
| #include <algorithm> | ||||
| #ifndef BOOST_TYPE_TRAITS_HPP | ||||
| #include <boost/type_traits.hpp> | ||||
| #endif | ||||
| #ifndef BOOST_CALL_TRAITS_HPP | ||||
| #include <boost/call_traits.hpp> | ||||
| #endif | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| // compressed_pair | ||||
|  | ||||
| namespace details | ||||
| { | ||||
|    // JM altered 26 Jan 2000: | ||||
|    template <class T1, class T2, bool IsSame, bool FirstEmpty, bool SecondEmpty> | ||||
|    struct compressed_pair_switch; | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    struct compressed_pair_switch<T1, T2, false, false, false> | ||||
|       {static const int value = 0;}; | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    struct compressed_pair_switch<T1, T2, false, true, true> | ||||
|       {static const int value = 3;}; | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    struct compressed_pair_switch<T1, T2, false, true, false> | ||||
|       {static const int value = 1;}; | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    struct compressed_pair_switch<T1, T2, false, false, true> | ||||
|       {static const int value = 2;}; | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    struct compressed_pair_switch<T1, T2, true, true, true> | ||||
|       {static const int value = 4;}; | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    struct compressed_pair_switch<T1, T2, true, false, false> | ||||
|       {static const int value = 5;}; | ||||
|  | ||||
|    template <class T1, class T2, int Version> class compressed_pair_imp; | ||||
|  | ||||
| #ifdef __GNUC__ | ||||
|    // workaround for GCC (JM): | ||||
|    using std::swap; | ||||
| #endif | ||||
|    // | ||||
|    // can't call unqualified swap from within classname::swap | ||||
|    // as Koenig lookup rules will find only the classname::swap | ||||
|    // member function not the global declaration, so use cp_swap | ||||
|    // as a forwarding function (JM): | ||||
|    template <typename T> | ||||
|    inline void cp_swap(T& t1, T& t2) | ||||
|    { | ||||
|       using std::swap; | ||||
|       swap(t1, t2); | ||||
|    } | ||||
|  | ||||
|    // 0    derive from neither | ||||
|  | ||||
|    template <class T1, class T2> | ||||
|    class compressed_pair_imp<T1, T2, 0> | ||||
|    { | ||||
|    public: | ||||
|       typedef T1                                                 first_type; | ||||
|       typedef T2                                                 second_type; | ||||
|       typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|       typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|       typedef typename call_traits<first_type>::reference        first_reference; | ||||
|       typedef typename call_traits<second_type>::reference       second_reference; | ||||
|       typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|       typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|       compressed_pair_imp() {}  | ||||
|  | ||||
|       compressed_pair_imp(first_param_type x, second_param_type y) | ||||
|          : first_(x), second_(y) {} | ||||
|  | ||||
|       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 T1, class T2> | ||||
|    class compressed_pair_imp<T1, T2, 1> | ||||
|       : private T1 | ||||
|    { | ||||
|    public: | ||||
|       typedef T1                                                 first_type; | ||||
|       typedef T2                                                 second_type; | ||||
|       typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|       typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|       typedef typename call_traits<first_type>::reference        first_reference; | ||||
|       typedef typename call_traits<second_type>::reference       second_reference; | ||||
|       typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|       typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|       compressed_pair_imp() {} | ||||
|  | ||||
|       compressed_pair_imp(first_param_type x, second_param_type y) | ||||
|          : first_type(x), second_(y) {} | ||||
|  | ||||
|       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 T1, class T2> | ||||
|    class compressed_pair_imp<T1, T2, 2> | ||||
|       : private T2 | ||||
|    { | ||||
|    public: | ||||
|       typedef T1                                                 first_type; | ||||
|       typedef T2                                                 second_type; | ||||
|       typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|       typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|       typedef typename call_traits<first_type>::reference        first_reference; | ||||
|       typedef typename call_traits<second_type>::reference       second_reference; | ||||
|       typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|       typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|       compressed_pair_imp() {} | ||||
|  | ||||
|       compressed_pair_imp(first_param_type x, second_param_type y) | ||||
|          : second_type(y), first_(x) {} | ||||
|  | ||||
|       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 T1, class T2> | ||||
|    class compressed_pair_imp<T1, T2, 3> | ||||
|       : private T1, | ||||
|         private T2 | ||||
|    { | ||||
|    public: | ||||
|       typedef T1                                                 first_type; | ||||
|       typedef T2                                                 second_type; | ||||
|       typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|       typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|       typedef typename call_traits<first_type>::reference        first_reference; | ||||
|       typedef typename call_traits<second_type>::reference       second_reference; | ||||
|       typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|       typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|       compressed_pair_imp() {} | ||||
|  | ||||
|       compressed_pair_imp(first_param_type x, second_param_type y) | ||||
|          : first_type(x), second_type(y) {} | ||||
|  | ||||
|       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 T1, class T2> | ||||
|    class compressed_pair_imp<T1, T2, 4> | ||||
|       : private T1 | ||||
|    { | ||||
|    public: | ||||
|       typedef T1                                                 first_type; | ||||
|       typedef T2                                                 second_type; | ||||
|       typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|       typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|       typedef typename call_traits<first_type>::reference        first_reference; | ||||
|       typedef typename call_traits<second_type>::reference       second_reference; | ||||
|       typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|       typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|       compressed_pair_imp() {} | ||||
|  | ||||
|       compressed_pair_imp(first_param_type x, second_param_type) | ||||
|          : first_type(x) {} | ||||
|  | ||||
|       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 T1, class T2> | ||||
|    class compressed_pair_imp<T1, T2, 5> | ||||
|    { | ||||
|    public: | ||||
|       typedef T1                                                 first_type; | ||||
|       typedef T2                                                 second_type; | ||||
|       typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|       typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|       typedef typename call_traits<first_type>::reference        first_reference; | ||||
|       typedef typename call_traits<second_type>::reference       second_reference; | ||||
|       typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|       typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|       compressed_pair_imp() {} | ||||
|  | ||||
|       compressed_pair_imp(first_param_type x, second_param_type y) | ||||
|          : first_(x), second_(y) {} | ||||
|  | ||||
|       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<T1, T2, 5>& y) | ||||
|       { | ||||
|          cp_swap(first_, y.first_); | ||||
|          cp_swap(second_, y.second_); | ||||
|       } | ||||
|    private: | ||||
|       first_type first_; | ||||
|       second_type second_; | ||||
|    }; | ||||
|  | ||||
| }  // details | ||||
|  | ||||
| template <class T1, class T2> | ||||
| class compressed_pair | ||||
|    : private ::boost::details::compressed_pair_imp<T1, T2, | ||||
|              ::boost::details::compressed_pair_switch< | ||||
|                     T1, | ||||
|                     T2, | ||||
|                     ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value, | ||||
|                     ::boost::is_empty<T1>::value, | ||||
|                     ::boost::is_empty<T2>::value>::value> | ||||
| { | ||||
| private: | ||||
|    typedef details::compressed_pair_imp<T1, T2, | ||||
|              ::boost::details::compressed_pair_switch< | ||||
|                     T1, | ||||
|                     T2, | ||||
|                     ::boost::is_same<typename remove_cv<T1>::type, typename remove_cv<T2>::type>::value, | ||||
|                     ::boost::is_empty<T1>::value, | ||||
|                     ::boost::is_empty<T2>::value>::value> base; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair() : base() {} | ||||
|             compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} | ||||
|    explicit compressed_pair(first_param_type x) : base(x) {} | ||||
|    explicit compressed_pair(second_param_type y) : base(y) {} | ||||
|  | ||||
|    first_reference       first()       {return base::first();} | ||||
|    first_const_reference first() const {return base::first();} | ||||
|  | ||||
|    second_reference       second()       {return base::second();} | ||||
|    second_const_reference second() const {return base::second();} | ||||
|  | ||||
|    void swap(compressed_pair& y) { base::swap(y); } | ||||
| }; | ||||
|  | ||||
| // JM | ||||
| // Partial specialisation for case where T1 == T2: | ||||
| // | ||||
| template <class T> | ||||
| class compressed_pair<T, T> | ||||
|    : private details::compressed_pair_imp<T, T, | ||||
|              ::boost::details::compressed_pair_switch< | ||||
|                     T, | ||||
|                     T, | ||||
|                     ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value, | ||||
|                     ::boost::is_empty<T>::value, | ||||
|                     ::boost::is_empty<T>::value>::value> | ||||
| { | ||||
| private: | ||||
|    typedef details::compressed_pair_imp<T, T, | ||||
|              ::boost::details::compressed_pair_switch< | ||||
|                     T, | ||||
|                     T, | ||||
|                     ::boost::is_same<typename remove_cv<T>::type, typename remove_cv<T>::type>::value, | ||||
|                     ::boost::is_empty<T>::value, | ||||
|                     ::boost::is_empty<T>::value>::value> base; | ||||
| public: | ||||
|    typedef T                                                  first_type; | ||||
|    typedef T                                                  second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair() : base() {} | ||||
|             compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} | ||||
|    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 <class T1, class T2> | ||||
| inline | ||||
| void | ||||
| swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y) | ||||
| { | ||||
|    x.swap(y); | ||||
| } | ||||
|  | ||||
| } // boost | ||||
|  | ||||
| #endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP | ||||
|  | ||||
|  | ||||
							
								
								
									
										35
									
								
								include/boost/detail/ob_call_traits.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								include/boost/detail/ob_call_traits.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| //  (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: | ||||
| // | ||||
| #ifndef BOOST_OB_CALL_TRAITS_HPP | ||||
| #define BOOST_OB_CALL_TRAITS_HPP | ||||
|  | ||||
| #ifndef BOOST_CONFIG_HPP | ||||
| #include <boost/config.hpp> | ||||
| #endif | ||||
|  | ||||
| #ifndef BOOST_TYPE_TRAITS_HPP | ||||
| #include <boost/type_traits.hpp> | ||||
| #endif | ||||
|  | ||||
| namespace boost{ | ||||
|  | ||||
| template <typename T> | ||||
| struct call_traits | ||||
| { | ||||
|    typedef T value_type; | ||||
|    typedef T& reference; | ||||
|    typedef const T& const_reference; | ||||
|    typedef const T& param_type; | ||||
| }; | ||||
|  | ||||
| } | ||||
|  | ||||
| #endif // BOOST_OB_CALL_TRAITS_HPP | ||||
| @@ -5,15 +5,8 @@ | ||||
| //  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: | ||||
| @@ -26,11 +19,8 @@ | ||||
| #define BOOST_OB_COMPRESSED_PAIR_HPP | ||||
|  | ||||
| #include <algorithm> | ||||
| #ifndef BOOST_OBJECT_TYPE_TRAITS_HPP | ||||
| #include <boost/type_traits/object_traits.hpp> | ||||
| #endif | ||||
| #ifndef BOOST_SAME_TRAITS_HPP | ||||
| #include <boost/type_traits/same_traits.hpp> | ||||
| #ifndef BOOST_TYPE_TRAITS_HPP | ||||
| #include <boost/type_traits.hpp> | ||||
| #endif | ||||
| #ifndef BOOST_CALL_TRAITS_HPP | ||||
| #include <boost/call_traits.hpp> | ||||
| @@ -38,424 +28,6 @@ | ||||
|  | ||||
| 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 T1, class T2> | ||||
| class compressed_pair; | ||||
|  | ||||
| namespace detail{ | ||||
|  | ||||
| template <class A, class T1, class T2> | ||||
| struct best_conversion_traits | ||||
| { | ||||
|    typedef char one; | ||||
|    typedef char (&two)[2]; | ||||
|    static A a; | ||||
|    static one test(T1); | ||||
|    static two test(T2); | ||||
|  | ||||
|    enum { value = sizeof(test(a)) }; | ||||
| }; | ||||
|  | ||||
| template <int> | ||||
| struct init_one; | ||||
|  | ||||
| template <> | ||||
| struct init_one<1> | ||||
| { | ||||
|    template <class A, class T1, class T2> | ||||
|    static void init(const A& a, T1* p1, T2*) | ||||
|    { | ||||
|       *p1 = a; | ||||
|    } | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct init_one<2> | ||||
| { | ||||
|    template <class A, class T1, class T2> | ||||
|    static void init(const A& a, T1*, T2* p2) | ||||
|    { | ||||
|       *p2 = a; | ||||
|    } | ||||
| }; | ||||
|  | ||||
|  | ||||
| // T1 != T2, both non-empty | ||||
| template <class T1, class T2> | ||||
| class compressed_pair_0 | ||||
| { | ||||
| private: | ||||
|    T1 _first; | ||||
|    T2 _second; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair_0() : _first(), _second() {} | ||||
|             compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {} | ||||
|    template <class A> | ||||
|    explicit compressed_pair_0(const A& val) | ||||
|    { | ||||
|       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second); | ||||
|    } | ||||
|    compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x) | ||||
|       : _first(x.first()), _second(x.second()) {} | ||||
|  | ||||
| #if 0 | ||||
|   compressed_pair_0& operator=(const compressed_pair_0& x) { | ||||
|     cout << "assigning compressed pair 0" << endl; | ||||
|     _first = x._first; | ||||
|     _second = x._second; | ||||
|     cout << "finished assigning compressed pair 0" << endl; | ||||
|     return *this; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|    first_reference       first()       { return _first; } | ||||
|    first_const_reference first() const { return _first; } | ||||
|  | ||||
|    second_reference       second()       { return _second; } | ||||
|    second_const_reference second() const { return _second; } | ||||
|  | ||||
|    void swap(compressed_pair_0& y) | ||||
|    { | ||||
|       using std::swap; | ||||
|       swap(_first, y._first); | ||||
|       swap(_second, y._second); | ||||
|    } | ||||
| }; | ||||
|  | ||||
| // T1 != T2, T2 empty | ||||
| template <class T1, class T2> | ||||
| class compressed_pair_1 : T2 | ||||
| { | ||||
| private: | ||||
|    T1 _first; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair_1() : T2(), _first() {} | ||||
|             compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {} | ||||
|  | ||||
|    template <class A> | ||||
|    explicit compressed_pair_1(const A& val) | ||||
|    { | ||||
|       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this)); | ||||
|    } | ||||
|  | ||||
|    compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x) | ||||
|       : T2(x.second()), _first(x.first()) {} | ||||
|  | ||||
| #ifdef BOOST_MSVC | ||||
|   // Total weirdness. If the assignment to _first is moved after | ||||
|   // the call to the inherited operator=, then this breaks graph/test/graph.cpp | ||||
|   // by way of iterator_adaptor. | ||||
|   compressed_pair_1& operator=(const compressed_pair_1& x) { | ||||
|     _first = x._first; | ||||
|     T2::operator=(x); | ||||
|     return *this; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|    first_reference       first()       { return _first; } | ||||
|    first_const_reference first() const { return _first; } | ||||
|  | ||||
|    second_reference       second()       { return *this; } | ||||
|    second_const_reference second() const { return *this; } | ||||
|  | ||||
|    void swap(compressed_pair_1& y) | ||||
|    { | ||||
|       // no need to swap empty base class: | ||||
|       using std::swap; | ||||
|       swap(_first, y._first); | ||||
|    } | ||||
| }; | ||||
|  | ||||
| // T1 != T2, T1 empty | ||||
| template <class T1, class T2> | ||||
| class compressed_pair_2 : T1 | ||||
| { | ||||
| private: | ||||
|    T2 _second; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair_2() : T1(), _second() {} | ||||
|             compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {} | ||||
|    template <class A> | ||||
|    explicit compressed_pair_2(const A& val) | ||||
|    { | ||||
|       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second); | ||||
|    } | ||||
|    compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x) | ||||
|       : T1(x.first()), _second(x.second()) {} | ||||
|  | ||||
| #if 0 | ||||
|   compressed_pair_2& operator=(const compressed_pair_2& x) { | ||||
|     cout << "assigning compressed pair 2" << endl; | ||||
|     T1::operator=(x); | ||||
|     _second = x._second; | ||||
|     cout << "finished assigning compressed pair 2" << endl; | ||||
|     return *this; | ||||
|   } | ||||
| #endif | ||||
|    first_reference       first()       { return *this; } | ||||
|    first_const_reference first() const { return *this; } | ||||
|  | ||||
|    second_reference       second()       { return _second; } | ||||
|    second_const_reference second() const { return _second; } | ||||
|  | ||||
|    void swap(compressed_pair_2& y) | ||||
|    { | ||||
|       // no need to swap empty base class: | ||||
|       using std::swap; | ||||
|       swap(_second, y._second); | ||||
|    } | ||||
| }; | ||||
|  | ||||
| // T1 != T2, both empty | ||||
| template <class T1, class T2> | ||||
| class compressed_pair_3 : T1, T2 | ||||
| { | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair_3() : T1(), T2() {} | ||||
|             compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {} | ||||
|    template <class A> | ||||
|    explicit compressed_pair_3(const A& val) | ||||
|    { | ||||
|       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this)); | ||||
|    } | ||||
|    compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x) | ||||
|       : T1(x.first()), T2(x.second()) {} | ||||
|  | ||||
|    first_reference       first()       { return *this; } | ||||
|    first_const_reference first() const { return *this; } | ||||
|  | ||||
|    second_reference       second()       { return *this; } | ||||
|    second_const_reference second() const { return *this; } | ||||
|  | ||||
|    void swap(compressed_pair_3& y) | ||||
|    { | ||||
|       // no need to swap empty base classes: | ||||
|    } | ||||
| }; | ||||
|  | ||||
| // T1 == T2, and empty | ||||
| template <class T1, class T2> | ||||
| class compressed_pair_4 : T1 | ||||
| { | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair_4() : T1() {} | ||||
|             compressed_pair_4(first_param_type x, second_param_type) : T1(x) {} | ||||
|    // only one single argument constructor since T1 == T2 | ||||
|    explicit compressed_pair_4(first_param_type x) : T1(x) {} | ||||
|    compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x) | ||||
|       : T1(x.first()){} | ||||
|  | ||||
|    first_reference       first()       { return *this; } | ||||
|    first_const_reference first() const { return *this; } | ||||
|  | ||||
|    second_reference       second()       { return *this; } | ||||
|    second_const_reference second() const { return *this; } | ||||
|  | ||||
|    void swap(compressed_pair_4& y) | ||||
|    { | ||||
|       // no need to swap empty base classes: | ||||
|    } | ||||
| }; | ||||
|  | ||||
| // T1 == T2, not empty | ||||
| template <class T1, class T2> | ||||
| class compressed_pair_5 | ||||
| { | ||||
| private: | ||||
|    T1 _first; | ||||
|    T2 _second; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair_5() : _first(), _second() {} | ||||
|             compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {} | ||||
|    // only one single argument constructor since T1 == T2 | ||||
|    explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {} | ||||
|    compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c)  | ||||
|       : _first(c.first()), _second(c.second()) {} | ||||
|  | ||||
|    first_reference       first()       { return _first; } | ||||
|    first_const_reference first() const { return _first; } | ||||
|  | ||||
|    second_reference       second()       { return _second; } | ||||
|    second_const_reference second() const { return _second; } | ||||
|  | ||||
|    void swap(compressed_pair_5& y) | ||||
|    { | ||||
|       using std::swap; | ||||
|       swap(_first, y._first); | ||||
|       swap(_second, y._second); | ||||
|    } | ||||
| }; | ||||
|  | ||||
| template <bool e1, bool e2, bool same> | ||||
| struct compressed_pair_chooser | ||||
| { | ||||
|    template <class T1, class T2> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef compressed_pair_0<T1, T2> type; | ||||
|    }; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct compressed_pair_chooser<false, true, false> | ||||
| { | ||||
|    template <class T1, class T2> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef compressed_pair_1<T1, T2> type; | ||||
|    }; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct compressed_pair_chooser<true, false, false> | ||||
| { | ||||
|    template <class T1, class T2> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef compressed_pair_2<T1, T2> type; | ||||
|    }; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct compressed_pair_chooser<true, true, false> | ||||
| { | ||||
|    template <class T1, class T2> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef compressed_pair_3<T1, T2> type; | ||||
|    }; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct compressed_pair_chooser<true, true, true> | ||||
| { | ||||
|    template <class T1, class T2> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef compressed_pair_4<T1, T2> type; | ||||
|    }; | ||||
| }; | ||||
|  | ||||
| template <> | ||||
| struct compressed_pair_chooser<false, false, true> | ||||
| { | ||||
|    template <class T1, class T2> | ||||
|    struct rebind | ||||
|    { | ||||
|       typedef compressed_pair_5<T1, T2> type; | ||||
|    }; | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| struct compressed_pair_traits | ||||
| { | ||||
| private: | ||||
|    typedef compressed_pair_chooser<is_empty<T1>::value, is_empty<T2>::value, is_same<T1,T2>::value> chooser; | ||||
|    typedef typename chooser::template rebind<T1, T2> bound_type; | ||||
| public: | ||||
|    typedef typename bound_type::type type; | ||||
| }; | ||||
|  | ||||
| } // namespace detail | ||||
|  | ||||
| template <class T1, class T2> | ||||
| class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type | ||||
| { | ||||
| private: | ||||
|    typedef typename detail::compressed_pair_traits<T1, T2>::type base_type; | ||||
| public: | ||||
|    typedef T1                                                 first_type; | ||||
|    typedef T2                                                 second_type; | ||||
|    typedef typename call_traits<first_type>::param_type       first_param_type; | ||||
|    typedef typename call_traits<second_type>::param_type      second_param_type; | ||||
|    typedef typename call_traits<first_type>::reference        first_reference; | ||||
|    typedef typename call_traits<second_type>::reference       second_reference; | ||||
|    typedef typename call_traits<first_type>::const_reference  first_const_reference; | ||||
|    typedef typename call_traits<second_type>::const_reference second_const_reference; | ||||
|  | ||||
|             compressed_pair() : base_type() {} | ||||
|             compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {} | ||||
|    template <class A> | ||||
|    explicit compressed_pair(const A& x) : base_type(x){} | ||||
|  | ||||
|    first_reference       first()       { return base_type::first(); } | ||||
|    first_const_reference first() const { return base_type::first(); } | ||||
|  | ||||
|    second_reference       second()       { return base_type::second(); } | ||||
|    second_const_reference second() const { return base_type::second(); } | ||||
| }; | ||||
|  | ||||
| template <class T1, class T2> | ||||
| inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y) | ||||
| { | ||||
|    x.swap(y); | ||||
| } | ||||
|  | ||||
| #else | ||||
| // no partial specialisation, no member templates: | ||||
|  | ||||
| template <class T1, class T2> | ||||
| class compressed_pair | ||||
| @@ -499,11 +71,7 @@ inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y) | ||||
|    x.swap(y); | ||||
| } | ||||
|  | ||||
| #endif | ||||
|  | ||||
| } // boost | ||||
|  | ||||
| #endif // BOOST_OB_COMPRESSED_PAIR_HPP | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										559
									
								
								include/boost/operators.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										559
									
								
								include/boost/operators.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,559 @@ | ||||
| //  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<T,U> second operand type for first two | ||||
| //            operators.(Beman Dawes) | ||||
| //  12 Nov 99 Add operators templates (Ed Brey) | ||||
| //  11 Nov 99 Add single template parameter version for compilers without | ||||
| //            partial specialization (Beman Dawes) | ||||
| //  10 Nov 99 Initial version | ||||
|  | ||||
| // 10 Jun 00: | ||||
| // An additional optional template parameter was added to most of  | ||||
| // operator templates to support the base class chaining technique (see  | ||||
| // documentation for the details). Unfortunately, a straightforward | ||||
| // implementation of this change would have broken compatibility with the | ||||
| // previous version of the library by making it impossible to use the same | ||||
| // template name (e.g. 'addable') for both the 1- and 2-argument versions of | ||||
| // an operator template. This implementation solves the backward-compatibility | ||||
| // issue at the cost of some simplicity. | ||||
| // | ||||
| // One of the complications is an existence of special auxiliary class template | ||||
| // 'is_chained_base<>' (see 'detail' namespace below), which is used | ||||
| // to determine whether its template parameter is a library's operator template | ||||
| // or not. You have to specialize 'is_chained_base<>' for each new  | ||||
| // operator template you add to the library. | ||||
| // | ||||
| // However, most of the non-trivial implementation details are hidden behind  | ||||
| // several local macros defined below, and as soon as you understand them, | ||||
| // you understand the whole library implementation.  | ||||
|  | ||||
| #ifndef BOOST_OPERATORS_HPP | ||||
| #define BOOST_OPERATORS_HPP | ||||
|  | ||||
| #include <boost/config.hpp> | ||||
| #include <boost/iterator.hpp> | ||||
|  | ||||
| #if defined(__sgi) && !defined(__GNUC__) | ||||
| #pragma set woff 1234 | ||||
| #endif | ||||
|  | ||||
| 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 <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct less_than_comparable2 : B | ||||
| { | ||||
|      friend bool operator<=(const T& x, const U& y) { return !(x > y); } | ||||
|      friend bool operator>=(const T& x, const U& y) { return !(x < y); } | ||||
|      friend bool operator>(const U& x, const T& y)  { return y < x; } | ||||
|      friend bool operator<(const U& x, const T& y)  { return y > x; } | ||||
|      friend bool operator<=(const U& x, const T& y) { return !(y < x); } | ||||
|      friend bool operator>=(const U& x, const T& y) { return !(y > x); } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct less_than_comparable1 : B | ||||
| { | ||||
|      friend bool operator>(const T& x, const T& y)  { return y < x; } | ||||
|      friend bool operator<=(const T& x, const T& y) { return !(y < x); } | ||||
|      friend bool operator>=(const T& x, const T& y) { return !(x < y); } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct equality_comparable2 : B | ||||
| { | ||||
|      friend bool operator==(const U& y, const T& x) { return x == y; } | ||||
|      friend bool operator!=(const U& y, const T& x) { return !(x == y); } | ||||
|      friend bool operator!=(const T& y, const U& x) { return !(y == x); } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct equality_comparable1 : B | ||||
| { | ||||
|      friend bool operator!=(const T& x, const T& y) { return !(x == y); } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct multipliable2 : B | ||||
| { | ||||
|      friend T operator*(T x, const U& y) { return x *= y; } | ||||
|      friend T operator*(const U& y, T x) { return x *= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct multipliable1 : B | ||||
| { | ||||
|      friend T operator*(T x, const T& y) { return x *= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct addable2 : B | ||||
| { | ||||
|      friend T operator+(T x, const U& y) { return x += y; } | ||||
|      friend T operator+(const U& y, T x) { return x += y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct addable1 : B | ||||
| { | ||||
|      friend T operator+(T x, const T& y) { return x += y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct subtractable2 : B | ||||
| { | ||||
|      friend T operator-(T x, const U& y) { return x -= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct subtractable1 : B | ||||
| { | ||||
|      friend T operator-(T x, const T& y) { return x -= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct dividable2 : B | ||||
| { | ||||
|      friend T operator/(T x, const U& y) { return x /= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct dividable1 : B | ||||
| { | ||||
|      friend T operator/(T x, const T& y) { return x /= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct modable2 : B | ||||
| { | ||||
|      friend T operator%(T x, const U& y) { return x %= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct modable1 : B | ||||
| { | ||||
|      friend T operator%(T x, const T& y) { return x %= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct xorable2 : B | ||||
| { | ||||
|      friend T operator^(T x, const U& y) { return x ^= y; } | ||||
|      friend T operator^(const U& y, T x) { return x ^= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct xorable1 : B | ||||
| { | ||||
|      friend T operator^(T x, const T& y) { return x ^= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct andable2 : B | ||||
| { | ||||
|      friend T operator&(T x, const U& y) { return x &= y; } | ||||
|      friend T operator&(const U& y, T x) { return x &= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct andable1 : B | ||||
| { | ||||
|      friend T operator&(T x, const T& y) { return x &= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class U, class B = ::boost::detail::empty_base> | ||||
| struct orable2 : B | ||||
| { | ||||
|      friend T operator|(T x, const U& y) { return x |= y; } | ||||
|      friend T operator|(const U& y, T x) { return x |= y; } | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct orable1 : B | ||||
| { | ||||
|      friend T operator|(T x, const T& y) { return x |= y; } | ||||
| }; | ||||
|  | ||||
| //  incrementable and decrementable contributed by Jeremy Siek | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct incrementable : B | ||||
| { | ||||
|   friend T operator++(T& x, int) | ||||
|   { | ||||
|     incrementable_type tmp(x); | ||||
|     ++x; | ||||
|     return tmp; | ||||
|   } | ||||
| private: // The use of this typedef works around a Borland bug | ||||
|   typedef T incrementable_type; | ||||
| }; | ||||
|  | ||||
| template <class T, class B = ::boost::detail::empty_base> | ||||
| struct decrementable : B | ||||
| { | ||||
|   friend T operator--(T& x, int) | ||||
|   { | ||||
|     decrementable_type tmp(x); | ||||
|     --x; | ||||
|     return tmp; | ||||
|   } | ||||
| private: // The use of this typedef works around a Borland bug | ||||
|   typedef T decrementable_type; | ||||
| }; | ||||
|  | ||||
| //  Iterator operator classes (contributed by Jeremy Siek) ------------------// | ||||
|  | ||||
| template <class T, class P, class B = ::boost::detail::empty_base> | ||||
| struct dereferenceable : B | ||||
| { | ||||
|   P operator->() const | ||||
|   {  | ||||
|     return &*static_cast<const T&>(*this);  | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <class T, class I, class R, class B = ::boost::detail::empty_base> | ||||
| struct indexable : B | ||||
| { | ||||
|   R operator[](I n) const | ||||
|   { | ||||
|     return *(static_cast<const T&>(*this) + n); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| #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 <class T, class U, class B = ::boost::detail::empty_base>        \ | ||||
|      struct template_name : ::template_name<T, U, B> {}; | ||||
|  | ||||
| #    define BOOST_IMPORT_TEMPLATE1(template_name)                              \ | ||||
|      template <class T, class B = ::boost::detail::empty_base>                 \ | ||||
|      struct template_name : ::template_name<T, B> {}; | ||||
|  | ||||
| #  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<class T> 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<class T, class U, class B>                              \ | ||||
|   struct is_chained_base< ::boost::template_name2<T, U, B> > {     \ | ||||
|     typedef ::boost::detail::true_t value;                         \ | ||||
|   }; | ||||
|  | ||||
| // Import a 1-type-argument operator template into boost (if neccessary) and | ||||
| // provide a specialization of 'is_chained_base<>' for it. | ||||
| # define BOOST_OPERATOR_TEMPLATE1(template_name1)                  \ | ||||
|   BOOST_IMPORT_TEMPLATE1(template_name1)                           \ | ||||
|   template<class T, class B>                                       \ | ||||
|   struct is_chained_base< ::boost::template_name1<T, B> > {        \ | ||||
|     typedef ::boost::detail::true_t value;                         \ | ||||
|   }; | ||||
|  | ||||
| // BOOST_OPERATOR_TEMPLATE(template_name) defines template_name<> such that it | ||||
| // can be used for specifying both 1-argument and 2-argument forms. Requires the | ||||
| // existence of two previously defined class templates named '<template_name>1' | ||||
| // and '<template_name>2' which must implement the corresponding 1- and 2- | ||||
| // argument forms. | ||||
| // | ||||
| // The template type parameter O == is_chained_base<U>::value is used to | ||||
| // distinguish whether the 2nd argument to <template_name> is being used for | ||||
| // base class chaining from another boost operator template or is describing a | ||||
| // 2nd operand type. O == true_t only when U is actually an another operator | ||||
| // template from the library. Partial specialization is used to select an | ||||
| // implementation in terms of either '<template_name>1' or '<template_name>2'. | ||||
| // | ||||
|  | ||||
| # define BOOST_OPERATOR_TEMPLATE(template_name)                    \ | ||||
| template <class T                                                  \ | ||||
|          ,class U = T                                              \ | ||||
|          ,class B = ::boost::detail::empty_base                    \ | ||||
|          ,class O = typename is_chained_base<U>::value             \ | ||||
|          >                                                         \ | ||||
| struct template_name : template_name##2<T, U, B> {};               \ | ||||
|                                                                    \ | ||||
| template<class T, class U, class B>                                \ | ||||
| struct template_name<T, U, B, ::boost::detail::true_t>             \ | ||||
|   : template_name##1<T, U> {};                                     \ | ||||
|                                                                    \ | ||||
| template <class T, class B>                                        \ | ||||
| struct template_name<T, T, B, ::boost::detail::false_t>            \ | ||||
|   : template_name##1<T, B> {};                                     \ | ||||
|                                                                    \ | ||||
| template<class T, class U, class B, class O>                       \ | ||||
| struct is_chained_base< ::boost::template_name<T, U, B, O> > {     \ | ||||
|   typedef ::boost::detail::true_t value;                           \ | ||||
| };                                                                 \ | ||||
|                                                                    \ | ||||
| BOOST_OPERATOR_TEMPLATE2(template_name##2)                         \ | ||||
| BOOST_OPERATOR_TEMPLATE1(template_name##1) | ||||
|  | ||||
|  | ||||
| #else // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|  | ||||
| #  define BOOST_OPERATOR_TEMPLATE2(template_name2) \ | ||||
|         BOOST_IMPORT_TEMPLATE2(template_name2) | ||||
| #  define BOOST_OPERATOR_TEMPLATE1(template_name1) \ | ||||
|         BOOST_IMPORT_TEMPLATE1(template_name1) | ||||
|  | ||||
|    // In this case we can only assume that template_name<> is equivalent to the | ||||
|    // more commonly needed template_name1<> form. | ||||
| #  define BOOST_OPERATOR_TEMPLATE(template_name)                   \ | ||||
|    template <class T, class B = ::boost::detail::empty_base>       \ | ||||
|    struct template_name : template_name##1<T, B> {}; | ||||
|  | ||||
| #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
|  | ||||
| namespace boost { | ||||
|      | ||||
| BOOST_OPERATOR_TEMPLATE(less_than_comparable) | ||||
| BOOST_OPERATOR_TEMPLATE(equality_comparable) | ||||
| BOOST_OPERATOR_TEMPLATE(multipliable) | ||||
| BOOST_OPERATOR_TEMPLATE(addable) | ||||
| BOOST_OPERATOR_TEMPLATE(subtractable) | ||||
| BOOST_OPERATOR_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 <class T, class I, class R, class B = ::boost::detail::empty_base> | ||||
|    struct indexable : ::indexable<T,I,R,B> {}; | ||||
| # else | ||||
|    using ::indexable; | ||||
| # endif | ||||
| #endif | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template <class T, class I, class R, class B> | ||||
| struct is_chained_base< ::boost::indexable<T, I, R, B> > { | ||||
|   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 <class T, class U> | ||||
| struct operators2 | ||||
|     : less_than_comparable2<T,U | ||||
|     , equality_comparable2<T,U | ||||
|     , addable2<T,U | ||||
|     , subtractable2<T,U | ||||
|     , multipliable2<T,U | ||||
|     , dividable2<T,U | ||||
|     , modable2<T,U | ||||
|     , orable2<T,U | ||||
|     , andable2<T,U | ||||
|     , xorable2<T,U | ||||
|       > > > > > > > > > > {}; | ||||
|  | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| template <class T, class U = T> | ||||
| struct operators : operators2<T, U> {}; | ||||
|  | ||||
| template <class T> struct operators<T, T> | ||||
| #else | ||||
| template <class T> struct operators | ||||
| #endif | ||||
|     : less_than_comparable<T | ||||
|     , equality_comparable<T | ||||
|     , addable<T | ||||
|     , subtractable<T | ||||
|     , multipliable<T | ||||
|     , dividable<T | ||||
|     , modable<T | ||||
|     , orable<T | ||||
|     , andable<T | ||||
|     , xorable<T | ||||
|     , incrementable<T | ||||
|     , decrementable<T | ||||
|       > > > > > > > > > > > > {}; | ||||
|  | ||||
| //  Iterator helper classes (contributed by Jeremy Siek) -------------------// | ||||
| template <class T, | ||||
|           class V, | ||||
|           class D = std::ptrdiff_t, | ||||
|           class P = V*, | ||||
|           class R = V&> | ||||
| struct forward_iterator_helper | ||||
|   : equality_comparable<T | ||||
|   , incrementable<T | ||||
|   , dereferenceable<T,P | ||||
|   , boost::iterator<std::forward_iterator_tag, V, D | ||||
|     > > > > {}; | ||||
|  | ||||
| template <class T, | ||||
|           class V, | ||||
|           class D = std::ptrdiff_t, | ||||
|           class P = V*, | ||||
|           class R = V&> | ||||
| struct bidirectional_iterator_helper | ||||
|   : equality_comparable<T | ||||
|   , incrementable<T | ||||
|   , decrementable<T | ||||
|   , dereferenceable<T,P | ||||
|   , boost::iterator<std::bidirectional_iterator_tag, V, D | ||||
|     > > > > > {}; | ||||
|  | ||||
| template <class T, | ||||
|           class V,  | ||||
|           class D = std::ptrdiff_t, | ||||
|           class P = V*, | ||||
|           class R = V&> | ||||
| struct random_access_iterator_helper | ||||
|   : equality_comparable<T | ||||
|   , less_than_comparable<T | ||||
|   , incrementable<T | ||||
|   , decrementable<T | ||||
|   , dereferenceable<T,P | ||||
|   , addable2<T,D | ||||
|   , subtractable2<T,D | ||||
|   , indexable<T,D,R | ||||
|   , boost::iterator<std::random_access_iterator_tag, V, D | ||||
|     > > > > > > > > > | ||||
| { | ||||
| #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 | ||||
							
								
								
									
										69
									
								
								include/boost/utility.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								include/boost/utility.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| //  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 <boost/config.hpp> | ||||
| #include <cstddef>            // for size_t | ||||
|  | ||||
| namespace boost | ||||
| { | ||||
|  | ||||
| //  next() and prior() template functions  -----------------------------------// | ||||
|  | ||||
|     //  Helper functions for classes like bidirectional iterators not supporting | ||||
|     //  operator+ and operator-. | ||||
|     // | ||||
|     //  Usage: | ||||
|     //    const std::list<T>::iterator p = get_some_iterator(); | ||||
|     //    const std::list<T>::iterator prev = boost::prior(p); | ||||
|  | ||||
|     //  Contributed by Dave Abrahams | ||||
|  | ||||
|     template <class T> | ||||
|     T next(T x) { return ++x; } | ||||
|  | ||||
|     template <class T> | ||||
|     T prior(T x) { return --x; } | ||||
|  | ||||
|  | ||||
| //  class noncopyable  -------------------------------------------------------// | ||||
|  | ||||
|     //  Private copy constructor and copy assignment ensure classes derived from | ||||
|     //  class noncopyable cannot be copied. | ||||
|  | ||||
|     //  Contributed by Dave Abrahams | ||||
|  | ||||
|     class noncopyable | ||||
|     { | ||||
|     protected: | ||||
|         noncopyable(){} | ||||
|         ~noncopyable(){} | ||||
|     private:  // emphasize the following members are private | ||||
|         noncopyable( const noncopyable& ); | ||||
|         const noncopyable& operator=( const noncopyable& ); | ||||
|     }; // noncopyable | ||||
|  | ||||
| } // namespace boost | ||||
|  | ||||
| #endif  // BOOST_UTILITY_HPP | ||||
|  | ||||
							
								
								
									
										45
									
								
								iterator_adaptor_examples.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								iterator_adaptor_examples.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| // (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 <functional> | ||||
| #include <algorithm> | ||||
| #include <iostream> | ||||
| #include <boost/iterator_adaptors.hpp> | ||||
|  | ||||
| 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. | ||||
|  | ||||
|   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; | ||||
|  | ||||
|   // Here is an example of counting from 0 to 5 using the integer_range class. | ||||
|  | ||||
|   boost::integer_range<int> r(0,5); | ||||
|  | ||||
|   std::cout << "counting to from 0 to 4:" << std::endl; | ||||
|   std::copy(r.begin(), r.end(), std::ostream_iterator<int>(std::cout, " ")); | ||||
|   std::cout << std::endl; | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										143
									
								
								iterator_adaptor_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								iterator_adaptor_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,143 @@ | ||||
| //  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 <iostream> | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <functional> | ||||
| #include <boost/iterator_adaptors.hpp> | ||||
| #include <boost/iterator_tests.hpp> | ||||
|  | ||||
| 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 | ||||
|   <dummyT*, const dummyT*,  | ||||
|    my_iter_traits, my_const_iter_traits> 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; | ||||
| }; | ||||
|  | ||||
| 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<mult_functor, int*, | ||||
|       boost::iterator<std::random_access_iterator_tag,int> >::type | ||||
|       i(y, mult_functor(2)); | ||||
|     boost::random_access_iterator_test(i, N, x); | ||||
|   } | ||||
|   // Test indirect_iterator | ||||
|   { | ||||
|     dummyT* ptr[N]; | ||||
|     for (int k = 0; k < N; ++k) | ||||
|       ptr[k] = array + k; | ||||
|      | ||||
|     typedef dummyT* DummyPtr; | ||||
|     typedef boost::indirect_iterators<DummyPtr*, const DummyPtr*, | ||||
|       boost::iterator<std::random_access_iterator_tag, DummyPtr>, | ||||
|       boost::iterator<std::random_access_iterator_tag, const DummyPtr>, | ||||
|       boost::iterator<std::random_access_iterator_tag, dummyT> | ||||
|       > 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 reverse_iterators | ||||
|   { | ||||
|     dummyT reversed[N]; | ||||
|     std::copy(array, array + N, reversed); | ||||
|     std::reverse(reversed, reversed + N); | ||||
|      | ||||
|     typedef boost::reverse_iterators<dummyT*, const dummyT*, | ||||
|       boost::iterator<std::random_access_iterator_tag,dummyT>, | ||||
|       boost::iterator<std::random_access_iterator_tag,const dummyT> | ||||
|       > 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<int> r(0, 5); | ||||
|     boost::random_access_iterator_test(r.begin(), r.size(), int_array); | ||||
|   } | ||||
|  | ||||
|   std::cout << "test successful " << std::endl; | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
							
								
								
									
										631
									
								
								iterator_adaptors.htm
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										631
									
								
								iterator_adaptors.htm
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,631 @@ | ||||
| <html> | ||||
|  | ||||
| <head> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> | ||||
| <meta name="GENERATOR" content="Microsoft FrontPage 4.0"> | ||||
| <meta name="ProgId" content="FrontPage.Editor.Document"> | ||||
| <title>Header boost/iterator_adaptors.hpp Documentation</title> | ||||
| </head> | ||||
|  | ||||
| <body bgcolor="#FFFFFF" text="#000000"> | ||||
|  | ||||
| <h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align="center" width="277" height="86">Header | ||||
| <a href="../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a></h1> | ||||
|  | ||||
| <p>Header <a | ||||
| href="http://www.boost.org/boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a> | ||||
| </p> | ||||
|  | ||||
| <p>The file <a | ||||
| href="http://www.boost.org/boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a> | ||||
| includes the main <tt>iterator_adaptors</tt> class and several other classes | ||||
| for constructing commonly used iterator adaptors.</p> | ||||
|  | ||||
| <ul> | ||||
|   <li><a href="#iterator_adaptors"><tt>iterator_adaptors</tt></a>. | ||||
|   <li><a href="#iterator_adaptor"><tt>iterator_adaptor</tt></a>. | ||||
|   <li><a href="#transform_iterator"><tt>transform_iterator</tt></a> | ||||
|   <li><a href="#indirect_iterators"><tt>indirect_iterators</tt></a> | ||||
|   <li><a href="#reverse_iterators"><tt>reverse_iterators</tt></a> | ||||
|   <li><a href="#integer_range"><tt>integer_range</tt></a> | ||||
| </ul> | ||||
|  | ||||
|  | ||||
| <!-- put in something about Andrei Alexandrescu's contribution? --> | ||||
|  | ||||
| <p><a href="http://www.boost.org/people/dave_abrahams.htm">Dave | ||||
| Abrahams</a> 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 <tt>indirect_iterators</tt> and | ||||
| <tt>reverse_iterators</tt> classes.<br> | ||||
|  | ||||
| <a href="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</a> | ||||
| contributed <tt>transform_iterator</tt>, <tt>integer_range</tt>, | ||||
| and this documentation. | ||||
|  | ||||
| <h3><a name="iterator_adaptors">The Iterator Adaptors Class</a></h3> | ||||
|  | ||||
| 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 | ||||
| <tt>operator->()</tt>. The purpose of the | ||||
| <tt>iterator_adaptors</tt> class is to make it easier to implement an | ||||
| iterator class, and even easier to extend and adapt existing iterator | ||||
| types. The <tt>iterator_adaptors</tt> class itself is not an adaptor | ||||
| class but a <i>type generator</i>. It generates a pair of adaptor classes, | ||||
| one class for the mutable iterator and one class for the const | ||||
| iterator. The definition of the <tt>iterator_adaptors</tt> class is as | ||||
| follows: | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
| 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; | ||||
| }; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
| <p>The <tt>Iterator</tt> and <tt>ConstIterator</tt> template parameters | ||||
| are the iterator types that you want to adapt. The <tt>Traits</tt> and | ||||
| <tt>ConstTraits</tt> must be iterator traits classes.  The traits | ||||
| parameters default to the specialization of the | ||||
| <tt>std::iterator_traits</tt> class for the adapted iterators. If you | ||||
| want the traits for your new iterator adaptor (<tt>value_type</tt>, | ||||
| <tt>iterator_category</tt>, etc.) to be the same as the adapted | ||||
| iterator then use the default, otherwise create your own traits | ||||
| classes and pass them in <a href="#1">[1]</a>.  | ||||
|  | ||||
|  | ||||
| <p>The <tt>Policies</tt> class that you pass in will become the heart of | ||||
| the iterator adaptor. The policy class determines how your new adaptor | ||||
| class will behave. The <tt>Policies</tt> class must implement 3, 4, or | ||||
| 7 of the core iterator operations depending on whether you wish the | ||||
| new iterator adaptor class to be a | ||||
| <a href="http://www.sgi.com/Technology/STL/ForwardIterator.html"> | ||||
| ForwardIterator</a>, | ||||
| <a href="http://www.sgi.com/Technology/STL/BidirectionalIterator.html"> | ||||
| BidirectionalIterator</a>, or <a | ||||
| href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html"> | ||||
| RandomAccessIterator</a>. Make sure that the | ||||
| <tt>iterator_category</tt> type of the traits class you pass in | ||||
| matches the category of iterator that you want to create. The default | ||||
| policy class, <tt>default_iterator_policies</tt>, 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 | ||||
| <tt>default_iterator_policies</tt> to avoid retyping the usual | ||||
| behaviours. You should also look at <tt>default_iterator_policies</tt> | ||||
| as the "boiler-plate" for your own policy classes. The | ||||
| following is definition of the <tt>default_iterator_policies</tt> | ||||
| class: | ||||
|  | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
| 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> | ||||
|   void increment(Iterator& x) const | ||||
|     { ++x; } | ||||
|  | ||||
|   template <class Iterator1, class Iterator2> | ||||
|   bool equal(Iterator1& x, Iterator2& y) const | ||||
|     { return x == y; } | ||||
|  | ||||
|   // required for a BidirectionalIterator | ||||
|   template <class Iterator> | ||||
|   void decrement(Iterator& x) const | ||||
|     { --x; } | ||||
|  | ||||
|   // required for a RandomAccessIterator | ||||
|   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 y - x; } | ||||
|  | ||||
|   template <class Iterator1, class Iterator2> | ||||
|   bool less(Iterator1& x, Iterator2& y) const | ||||
|     { return x < y; } | ||||
| }; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
| <p> | ||||
| The generated iterator adaptor types will have the following | ||||
| constructors. | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
| <i>iterator</i>(const Iterator& i, const Policies& p = Policies()) | ||||
|  | ||||
| <i>const_iterator</i>(const ConstIterator& i, const Policies& p = Policies()) | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
| <h3><a name="iterator_adaptor">The Iterator Adaptor Class</a></h3> | ||||
|  | ||||
| This is the class used inside of the <tt>iterator_adaptors</tt> type | ||||
| generator. Use this class directly (instead of using | ||||
| <tt>iterator_adaptors</tt>) 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 <tt>std::set</tt>'s iterators. Use the same type for | ||||
| the <tt>Iterator</tt> and <tt>NonconstIterator</tt> template | ||||
| arguments. | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
| template <class Iterator,  | ||||
|           class Policies = default_iterator_policies, | ||||
|           class NonconstIterator = Iterator,          | ||||
|           class Traits = std::iterator_traits<Iterator> > | ||||
| struct iterator_adaptor; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
|  | ||||
| <p> | ||||
| 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. | ||||
|  | ||||
| <h3><a name="transform_iterator">The Transform Iterator Class</a></h3> | ||||
|  | ||||
| It is often useful to automatically apply some function to the value | ||||
| returned by dereferencing (<tt>operator*()</tt>) an iterator. The | ||||
| <tt>transform_iterators</tt> class makes it easy to create an iterator | ||||
| adaptor that does just that. | ||||
|  | ||||
| First let us consider what the <tt>Policies</tt> class for the transform | ||||
| iterator should look like. We are only changing one of the iterator | ||||
| behaviours, so we will inherit from | ||||
| <tt>default_iterator_policies</tt>. 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 | ||||
| <tt>result_type</tt> of the function, so <a | ||||
| href="http://www.sgi.com/Technology/STL/AdaptableUnaryFunction.html"> | ||||
| AdaptableUnaryFunction</a> is the corrent concept to choose for the | ||||
| function object type. Now for the heart of our iterator adaptor, we | ||||
| implement the <tt>dereference</tt> method, applying the function | ||||
| object to <tt>*i</tt>. The <tt>type<Reference></tt> 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 <a | ||||
| href="#2">[2]</a>. | ||||
|  | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
|   template <class AdaptableUnaryFunction> | ||||
|   struct transform_iterator_policies : public default_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; | ||||
|   }; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
| 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 <tt>value_type</tt> and <tt>reference</tt> type of our | ||||
| transform iterator will be the <tt>result_type</tt> of the function | ||||
| object.  The <tt>difference_type</tt> and <tt>iterator_category</tt> | ||||
| will be the same as the adapted iterator. | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
|   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; | ||||
|   }; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
| The final step is to use the <tt>iterator_adaptor</tt> 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 | ||||
| <tt>iterator_adaptor</tt>. 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 <tt>transform_iterators</tt> class | ||||
| we use the <tt>transform_iterator_traits</tt> class defined above to | ||||
| create the traits class for the new transform iterator. We then use | ||||
| the <tt>iterator_adaptor</tt> class to extract the generated | ||||
| iterator adaptor type. | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
| 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; | ||||
| }; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
| <p> | ||||
| The following is a simple example of how to use the | ||||
| <tt>transform_iterators</tt> class to iterate through a range of | ||||
| numbers, multiplying each of them by 2 when they are dereferenced. | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
| #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; | ||||
| } | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
|  | ||||
| <h3><a name="indirect_iterators">The Indirect Iterators Class</a></h3> | ||||
|  | ||||
| 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 | ||||
| <tt>operator*()</tt>. The implementation of this is similar to the | ||||
| <tt>transform_iterators</tt><a href="#3">[3]</a>. We first create a | ||||
| policies class which does a double-dereference in the | ||||
| <tt>dereference()</tt> method. We then create a traits class, this | ||||
| time also including a template parameter for the traits of the second | ||||
| level iterators as well as the first. Lastly we wrap this up in the | ||||
| type generator <tt>indirect_iterators</tt>, using | ||||
| <tt>iterator_adaptors</tt> to do most of the work. | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
|   struct indirect_iterator_policies : public default_iterator_policies | ||||
|   { | ||||
|     template <class Reference, class Iterator> | ||||
|     Reference dereference(type<Reference>, const Iterator& x) const | ||||
|       { return **x; } | ||||
|   }; | ||||
|  | ||||
|   template <class IndirectIterator, | ||||
| 	    class IndirectTraits = std::iterator_traits<IndirectIterator>, | ||||
| 	    class Traits =  | ||||
| 	      std::iterator_traits<typename IndirectTraits::value_type> | ||||
| 	   > | ||||
|   struct indirect_traits | ||||
|   { | ||||
|     typedef typename IndirectTraits::difference_type difference_type; | ||||
|     typedef typename Traits::value_type value_type; | ||||
|     typedef typename Traits::pointer pointer; | ||||
|     typedef typename Traits::reference reference; | ||||
|     typedef typename IndirectTraits::iterator_category iterator_category; | ||||
|   }; | ||||
|  | ||||
|   template <class IndirectIterator, class ConstIndirectIterator, | ||||
|             class IndirectTraits =  | ||||
|               std::iterator_traits<IndirectIterator>, | ||||
|             class ConstIndirectTraits =  | ||||
|               std::iterator_traits<ConstIndirectIterator>, | ||||
|             class Traits = | ||||
|               std::iterator_traits<typename IndirectTraits::value_type> | ||||
|            > | ||||
|   struct indirect_iterators | ||||
|   { | ||||
|     typedef typename IndirectTraits::value_type Iterator; | ||||
|     typedef typename Traits::value_type ValueType; | ||||
|     typedef iterator_adaptors<IndirectIterator, ConstIndirectIterator, | ||||
|       indirect_traits<IndirectIterator, IndirectTraits, Traits>, | ||||
|       indirect_traits<ConstIndirectIterator, ConstIndirectTraits, Traits>, | ||||
|       indirect_iterator_policies | ||||
|       > Adaptors; | ||||
|     typedef typename Adaptors::iterator iterator; | ||||
|     typedef typename Adaptors::const_iterator const_iterator; | ||||
|   }; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
| <h3><a name="reverse_iterators">The Reverse Iterators Class</a></h3> | ||||
|  | ||||
| <p> | ||||
| Yes, there is already a <tt>reverse_iterator</tt> adaptor class | ||||
| defined in the C++ Standard, but using the <tt>iterator_adaptors</tt> | ||||
| class we can re-implement this classic adaptor in a more succinct and | ||||
| elegant fashion. Also, this makes for a good example of using | ||||
| <tt>iterator_adaptors</tt> that is in familiar territory. | ||||
|  | ||||
| <p> | ||||
| The first step is to create the <tt>Policies</tt> class. As in the | ||||
| <tt>std::reverse_iterator</tt> class, we need to flip all the | ||||
| operations of the iterator. Increment will become decrement, advancing | ||||
| by <tt>n</tt> will become retreating by <tt>n</tt>, etc.  | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
| 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; } | ||||
| }; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
| 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 <tt>transform_iterator</tt>. We can skip to | ||||
| the final stage of creating a type generator class for our reverse | ||||
| iterators using the <tt>iterator_adaptor</tt> class. | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
| 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; | ||||
| }; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
| A typical use of the <tt>reverse_iterators</tt> class is in | ||||
| user-defined container types. You can use the | ||||
| <tt>reverse_iterators</tt> class to generate the reverse iterators for | ||||
| your container. | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
| 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; | ||||
|   ... | ||||
| }; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
|  | ||||
| <h3><a name="integer_range">The Integer Range Class</a></h3> | ||||
|  | ||||
| The <tt>iterator_adaptors</tt> 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 | ||||
| <tt>operator++()</tt>, <tt>operator--()</tt>, etc. The one operator | ||||
| they are lacking is the <tt>operator*()</tt>, 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. | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
| struct counting_iterator_policies : public default_iterator_policies | ||||
| { | ||||
|   template <class IntegerType> | ||||
|   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; | ||||
| }; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
| 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 | ||||
| <tt>integer_range</tt>. | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
| 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; | ||||
| }; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
| <p> | ||||
| The following is an example of how to use the | ||||
| <tt>integer_range</tt> class to count from 0 to 4. | ||||
|  | ||||
| <p> | ||||
| <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 COLS=2> | ||||
| <TR><TD WIDTH=30 VALIGN=TOP></TD><TD> | ||||
| <PRE> | ||||
| 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; | ||||
| </PRE></TD></TABLE> | ||||
|  | ||||
| <h3>Challenge</h3> | ||||
|  | ||||
| <p> | ||||
| There is an unlimited number of ways the the | ||||
| <tt>iterator_adaptors</tt> class can be used to create iterators. One | ||||
| interesting exercise would be to re-implement the iterators of | ||||
| <tt>std::list</tt> and <tt>std::slist</tt> using | ||||
| <tt>iterator_adaptors</tt>, where the adapted <tt>Iterator</tt> types | ||||
| would be node pointers. | ||||
|  | ||||
|  | ||||
| <h3>Notes</h3> | ||||
|  | ||||
| <p> | ||||
| <a name="1">[1]</a> | ||||
| If your compiler does not support partial specialization and hence | ||||
| does not have a working <tt>std::iterator_traits</tt> class, you will | ||||
| not be able to use the defaults and will need to supply your own | ||||
| <tt>Traits</tt> and <tt>ConstTraits</tt> classes. | ||||
|  | ||||
| <p> | ||||
| <a name="2">[2]</a> | ||||
| The reference type could also be obtained from | ||||
| <tt>std::iterator_traits</tt>, but that is not portable on compilers | ||||
| that do not support partial specialization. | ||||
|  | ||||
| <p> | ||||
| <a name="3">[3]</a> | ||||
| It would have been more elegant to implement <tt>indirect_iterators</tt> | ||||
| using <tt>transform_iterators</tt>, but for subtle reasons that would require | ||||
| the use of <tt>boost::remove_cv</tt> which is not portable. | ||||
|  | ||||
| <h3>Implementation Notes</h3> | ||||
|  | ||||
| The code is somewhat complicated because there are three iterator | ||||
| adaptor class: <tt>forward_iterator_adaptor</tt>, | ||||
| <tt>bidirectional_iterator_adaptor</tt>, and | ||||
| <tt>random_access_iterator_adaptor</tt>. The alternative would be to | ||||
| just have one iterator adaptor equivalent to the | ||||
| <tt>random_access_iterator_adaptor</tt>.  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 | ||||
| <a href="http://www.sgi.com/Technology/STL/RandomAccessIterator.html"> | ||||
| RandomAccessIterator</a> 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. | ||||
|  | ||||
|  | ||||
|  | ||||
| <hr> | ||||
| <p>Revised <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->17 Jun 2000<!--webbot bot="Timestamp" endspan i-checksum="15055" --></p> | ||||
| <p><EFBFBD> Copyright Jeremy Siek 2000. Permission to copy, use, | ||||
| modify, sell and distribute this document is granted provided this copyright | ||||
| notice appears in all copies. This document is provided "as is" | ||||
| without express or implied warranty, and with no claim as to its suitability for | ||||
| any purpose.</p> | ||||
|  | ||||
| </body> | ||||
|  | ||||
| </html> | ||||
							
								
								
									
										169
									
								
								iterators_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								iterators_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,169 @@ | ||||
| //  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 <string> | ||||
| #include <iostream> | ||||
| using namespace std; | ||||
|  | ||||
| #include <boost/operators.hpp> | ||||
| using namespace boost; | ||||
|  | ||||
|  | ||||
| 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; | ||||
| }; | ||||
|  | ||||
|  | ||||
| int | ||||
| main() | ||||
| { | ||||
|   string array[] = { "apple", "orange", "pear", "peach", "grape", "plum"  }; | ||||
|   { | ||||
|     test_iter<string,string&,string*> 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<string, const string&, const string*> 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; | ||||
| } | ||||
							
								
								
									
										38
									
								
								noncopyable_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								noncopyable_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| //  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 <boost/utility.hpp> | ||||
| #include <iostream> | ||||
|  | ||||
| //  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 | ||||
|    | ||||
							
								
								
									
										481
									
								
								operators_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										481
									
								
								operators_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,481 @@ | ||||
| //  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 <boost/operators.hpp> | ||||
| #include <cassert> | ||||
| #include <iostream> | ||||
| #include <boost/min_rand.hpp> | ||||
|  | ||||
|  | ||||
| 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 T> | ||||
|     class Wrapped1 : boost::operators<Wrapped1<T> > | ||||
|     { | ||||
|     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 <class T> | ||||
|     T true_value(Wrapped1<T> x) { return x.value(); }     | ||||
|  | ||||
|     template <class T, class U> | ||||
|     class Wrapped2 : | ||||
|         boost::operators<Wrapped2<T, U> >, | ||||
|         boost::operators2<Wrapped2<T, U>, U> | ||||
|     { | ||||
|     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 <class T, class U> | ||||
|     T true_value(Wrapped2<T,U> x) { return x.value(); } | ||||
|      | ||||
|     //  MyInt uses only the single template-argument form of all_operators<> | ||||
|     typedef Wrapped1<int> MyInt; | ||||
|  | ||||
|     typedef Wrapped2<long, long> MyLong; | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     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 <class X1, class Y1, class X2, class Y2> | ||||
|     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 <class X1, class Y1, class X2, class Y2> | ||||
|     void test_less_than_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_less_than_comparable_aux(x1, y1, x2, y2); | ||||
|         test_less_than_comparable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_equality_comparable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 == y1) == (x2 == y2)); | ||||
|         assert((x1 != y1) == (x2 != y2)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_equality_comparable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_equality_comparable_aux(x1, y1, x2, y2); | ||||
|         test_equality_comparable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_multipliable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 * y1).value() == (x2 * y2)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_multipliable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_multipliable_aux(x1, y1, x2, y2); | ||||
|         test_multipliable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_addable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 + y1).value() == (x2 + y2)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_addable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_addable_aux(x1, y1, x2, y2); | ||||
|         test_addable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_subtractable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         assert((x1 - y1).value() == x2 - y2); | ||||
|     } | ||||
|  | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_dividable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         if (y2 != 0) | ||||
|             assert((x1 / y1).value() == x2 / y2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_modable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         if (y2 != 0) | ||||
|             assert((x1 / y1).value() == x2 / y2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_xorable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 ^ y1).value() == (x2 ^ y2)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_xorable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_xorable_aux(x1, y1, x2, y2); | ||||
|         test_xorable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_andable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 & y1).value() == (x2 & y2)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_andable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_andable_aux(x1, y1, x2, y2); | ||||
|         test_andable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_orable_aux(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         assert((x1 | y1).value() == (x2 | y2)); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_orable(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         sanity_check(x1, y1, x2, y2); | ||||
|         test_orable_aux(x1, y1, x2, y2); | ||||
|         test_orable_aux(y1, x1, y2, x2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class X2> | ||||
|     void test_incrementable(X1 x1, X2 x2) | ||||
|     { | ||||
|         sanity_check(x1, x1, x2, x2); | ||||
|         assert(x1++.value() == x2++); | ||||
|         assert(x1.value() == x2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class X2> | ||||
|     void test_decrementable(X1 x1, X2 x2) | ||||
|     { | ||||
|         sanity_check(x1, x1, x2, x2); | ||||
|         assert(x1--.value() == x2--); | ||||
|         assert(x1.value() == x2); | ||||
|     } | ||||
|      | ||||
|     template <class X1, class Y1, class X2, class Y2> | ||||
|     void test_all(X1 x1, Y1 y1, X2 x2, Y2 y2) | ||||
|     { | ||||
|         test_less_than_comparable(x1, y1, x2, y2); | ||||
|         test_equality_comparable(x1, y1, x2, y2); | ||||
|         test_multipliable(x1, y1, x2, y2); | ||||
|         test_addable(x1, y1, x2, y2); | ||||
|         test_subtractable(x1, y1, x2, y2); | ||||
|         test_dividable(x1, y1, x2, y2); | ||||
|         test_modable(x1, y1, x2, y2); | ||||
|         test_xorable(x1, y1, x2, y2); | ||||
|         test_andable(x1, y1, x2, y2); | ||||
|         test_orable(x1, y1, x2, y2); | ||||
|         test_incrementable(x1, x2); | ||||
|         test_decrementable(x1, x2); | ||||
|     } | ||||
|      | ||||
|     template <class Big, class Small> | ||||
|     struct tester | ||||
|     { | ||||
|         void operator()(boost::min_rand& randomizer) const | ||||
|         { | ||||
|             Big b1 = Big(randomizer()); | ||||
|             Big b2 = Big(randomizer()); | ||||
|             Small s = Small(randomizer()); | ||||
|              | ||||
|             test_all(Wrapped1<Big>(b1), Wrapped1<Big>(b2), b1, b2); | ||||
|             test_all(Wrapped2<Big, Small>(b1), s, b1, s); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     // added as a regression test. We had a bug which this uncovered. | ||||
|     struct Point | ||||
|         : boost::addable<Point, | ||||
|         boost::subtractable<Point> > | ||||
|     { | ||||
|         Point( int h, int v ) : h(h), v(v) {} | ||||
|         Point() :h(0), v(0) {} | ||||
|         const Point& operator+=( const Point& rhs ) { h += rhs.h; v += rhs.v; return *this; } | ||||
|         const Point& operator-=( const Point& rhs ) { h -= rhs.h; v -= rhs.v; return *this; } | ||||
|  | ||||
|         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<int>; | ||||
| template Wrapped1<long>; | ||||
| template Wrapped1<unsigned int>; | ||||
| template Wrapped1<unsigned long>; | ||||
|  | ||||
| template Wrapped2<int, int>; | ||||
| template Wrapped2<int, signed char>; | ||||
| template Wrapped2<long, signed char>; | ||||
| template Wrapped2<long, int>; | ||||
| template Wrapped2<long, long>; | ||||
| template Wrapped2<unsigned int, unsigned int>; | ||||
| template Wrapped2<unsigned int, unsigned char>; | ||||
| template Wrapped2<unsigned long, unsigned int>; | ||||
| template Wrapped2<unsigned long, unsigned char>; | ||||
| template Wrapped2<unsigned long, unsigned long>; | ||||
| #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<long, int>()(r); | ||||
|         tester<long, signed char>()(r); | ||||
|         tester<long, long>()(r); | ||||
|         tester<int, int>()(r); | ||||
|         tester<int, signed char>()(r); | ||||
|          | ||||
|         tester<unsigned long, unsigned int>()(r); | ||||
|         tester<unsigned long, unsigned char>()(r); | ||||
|         tester<unsigned long, unsigned long>()(r); | ||||
|         tester<unsigned int, unsigned int>()(r); | ||||
|         tester<unsigned int, unsigned char>()(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; | ||||
| } | ||||
							
								
								
									
										534
									
								
								type_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										534
									
								
								type_traits_test.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,534 @@ | ||||
| //  (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. | ||||
|  | ||||
| /* Release notes: | ||||
|    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 <iostream> | ||||
| #include <typeinfo> | ||||
|  | ||||
| #include <boost/type_traits.hpp> | ||||
|  | ||||
| using namespace boost; | ||||
|  | ||||
| #ifdef __BORLANDC__ | ||||
| #pragma option -w-ccc -w-rch -w-eff -w-aus | ||||
| #endif | ||||
|  | ||||
| // | ||||
| // define tests here | ||||
| unsigned failures = 0; | ||||
| unsigned test_count = 0; | ||||
|  | ||||
| #define value_test(v, x) ++test_count;\ | ||||
|                          if(v != x){++failures; std::cout << "checking value of " << #x << "...failed" << std::endl;} | ||||
| #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION | ||||
| #define type_test(v, x)  ++test_count;\ | ||||
|                          if(is_same<v, x>::value == false){\ | ||||
|                            ++failures; \ | ||||
|                            std::cout << "checking type of " << #x << "...failed" << std::endl; \ | ||||
|                            std::cout << "   expected type was " << #v << std::endl; \ | ||||
|                            std::cout << "   " << typeid(is_same<v, x>).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 | ||||
|  | ||||
| // 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<enum_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct is_POD<POD_UDT> | ||||
| { static const bool value = true; }; | ||||
| // this type is not POD, so we have to specialize the has_* individually | ||||
| template <> struct has_trivial_constructor<empty_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct has_trivial_copy<empty_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct has_trivial_assign<empty_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct is_POD<empty_POD_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct is_union<union_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct is_union<POD_union_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct is_POD<POD_union_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct is_union<empty_union_UDT> | ||||
| { static const bool value = true; }; | ||||
| // this type is not POD, so we have to specialize the has_* individually | ||||
| template <> struct has_trivial_constructor<empty_union_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct has_trivial_copy<empty_union_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct has_trivial_assign<empty_union_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct is_union<empty_POD_union_UDT> | ||||
| { static const bool value = true; }; | ||||
| template <> struct is_POD<empty_POD_union_UDT> | ||||
| { static const bool value = true; }; | ||||
| } | ||||
| #else | ||||
| namespace boost { | ||||
| template <> struct is_enum<enum_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct is_POD<POD_UDT> | ||||
| { enum{ value = true }; }; | ||||
| // this type is not POD, so we have to specialize the has_* individually | ||||
| template <> struct has_trivial_constructor<empty_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct has_trivial_copy<empty_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct has_trivial_assign<empty_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct is_POD<empty_POD_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct is_union<union_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct is_union<POD_union_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct is_POD<POD_union_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct is_union<empty_union_UDT> | ||||
| { enum{ value = true }; }; | ||||
| // this type is not POD, so we have to specialize the has_* individually | ||||
| template <> struct has_trivial_constructor<empty_union_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct has_trivial_copy<empty_union_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct has_trivial_assign<empty_union_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct is_union<empty_POD_union_UDT> | ||||
| { enum{ value = true }; }; | ||||
| template <> struct is_POD<empty_POD_union_UDT> | ||||
| { enum{ value = true }; }; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| // 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; | ||||
|    typedef const r_type cr_type; | ||||
|  | ||||
|    type_test(int, remove_reference<int>::type) | ||||
|    type_test(const int, remove_reference<const int>::type) | ||||
|    type_test(int, remove_reference<int&>::type) | ||||
|    type_test(const int, remove_reference<const int&>::type) | ||||
|    type_test(volatile int, remove_reference<volatile int&>::type) | ||||
|    type_test(int, remove_reference<cr_type>::type) | ||||
|  | ||||
|    type_test(int, remove_const<const int>::type) | ||||
|    // Steve: fails on BCB4 | ||||
|    type_test(volatile int, remove_const<volatile int>::type) | ||||
|    // Steve: fails on BCB4 | ||||
|    type_test(volatile int, remove_const<const volatile int>::type) | ||||
|    type_test(int, remove_const<int>::type) | ||||
|    type_test(int*, remove_const<int* const>::type) | ||||
|    type_test(int, remove_volatile<volatile int>::type) | ||||
|    // Steve: fails on BCB4 | ||||
|    type_test(const int, remove_volatile<const int>::type) | ||||
|    // Steve: fails on BCB4 | ||||
|    type_test(const int, remove_volatile<const volatile int>::type) | ||||
|    type_test(int, remove_volatile<int>::type) | ||||
|    type_test(int*, remove_volatile<int* volatile>::type) | ||||
|    type_test(int, remove_cv<volatile int>::type) | ||||
|    type_test(int, remove_cv<const int>::type) | ||||
|    type_test(int, remove_cv<const volatile int>::type) | ||||
|    type_test(int, remove_cv<int>::type) | ||||
|    type_test(int*, remove_cv<int* volatile>::type) | ||||
|    type_test(int*, remove_cv<int* const>::type) | ||||
|    type_test(int*, remove_cv<int* const volatile>::type) | ||||
|    type_test(const int *, remove_cv<const int * const>::type) | ||||
|    type_test(int, remove_bounds<int>::type) | ||||
|    type_test(int*, remove_bounds<int*>::type) | ||||
|    type_test(int, remove_bounds<int[3]>::type) | ||||
|    type_test(int[3], remove_bounds<int[2][3]>::type) | ||||
|  | ||||
|    std::cout << std::endl << "Checking type properties..." << std::endl << std::endl; | ||||
|  | ||||
|    value_test(true, (is_same<int, int>::value)) | ||||
|    value_test(false, (is_same<int, const int>::value)) | ||||
|    value_test(false, (is_same<int, int&>::value)) | ||||
|    value_test(false, (is_same<int*, const int*>::value)) | ||||
|    value_test(false, (is_same<int*, int*const>::value)) | ||||
|    value_test(false, (is_same<int, int[2]>::value)) | ||||
|  | ||||
|    value_test(false, is_const<int>::value) | ||||
|    value_test(true, is_const<const int>::value) | ||||
|    value_test(false, is_const<volatile int>::value) | ||||
|    value_test(true, is_const<const volatile int>::value) | ||||
|  | ||||
|    value_test(false, is_volatile<int>::value) | ||||
|    value_test(false, is_volatile<const int>::value) | ||||
|    value_test(true, is_volatile<volatile int>::value) | ||||
|    value_test(true, is_volatile<const volatile int>::value) | ||||
|  | ||||
|    value_test(true, is_void<void>::value) | ||||
|    // Steve: fails on BCB4 | ||||
|    // JM: but looks as though it should according to [3.9.3p1]? | ||||
|    //value_test(false, is_void<const void>::value) | ||||
|    value_test(false, is_void<int>::value) | ||||
|  | ||||
|    value_test(false, is_standard_unsigned_integral<UDT>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<void>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<bool>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<char>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<signed char>::value) | ||||
|    value_test(true, is_standard_unsigned_integral<unsigned char>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<wchar_t>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<short>::value) | ||||
|    value_test(true, is_standard_unsigned_integral<unsigned short>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<int>::value) | ||||
|    value_test(true, is_standard_unsigned_integral<unsigned int>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<long>::value) | ||||
|    value_test(true, is_standard_unsigned_integral<unsigned long>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<float>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<double>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<long double>::value) | ||||
|    #ifdef ULLONG_MAX | ||||
|    value_test(false, is_standard_unsigned_integral<long long>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<unsigned long long>::value) | ||||
|    #endif | ||||
|    #if defined(__BORLANDC__) || defined(_MSC_VER) | ||||
|    value_test(false, is_standard_unsigned_integral<__int64>::value) | ||||
|    value_test(false, is_standard_unsigned_integral<unsigned __int64>::value) | ||||
|    #endif | ||||
|  | ||||
|    value_test(false, is_standard_signed_integral<UDT>::value) | ||||
|    value_test(false, is_standard_signed_integral<void>::value) | ||||
|    value_test(false, is_standard_signed_integral<bool>::value) | ||||
|    value_test(false, is_standard_signed_integral<char>::value) | ||||
|    value_test(true, is_standard_signed_integral<signed char>::value) | ||||
|    value_test(false, is_standard_signed_integral<unsigned char>::value) | ||||
|    value_test(false, is_standard_signed_integral<wchar_t>::value) | ||||
|    value_test(true, is_standard_signed_integral<short>::value) | ||||
|    value_test(false, is_standard_signed_integral<unsigned short>::value) | ||||
|    value_test(true, is_standard_signed_integral<int>::value) | ||||
|    value_test(false, is_standard_signed_integral<unsigned int>::value) | ||||
|    value_test(true, is_standard_signed_integral<long>::value) | ||||
|    value_test(false, is_standard_signed_integral<unsigned long>::value) | ||||
|    value_test(false, is_standard_signed_integral<float>::value) | ||||
|    value_test(false, is_standard_signed_integral<double>::value) | ||||
|    value_test(false, is_standard_signed_integral<long double>::value) | ||||
|    #ifdef ULLONG_MAX | ||||
|    value_test(false, is_standard_signed_integral<long long>::value) | ||||
|    value_test(false, is_standard_signed_integral<unsigned long long>::value) | ||||
|    #endif | ||||
|    #if defined(__BORLANDC__) || defined(_MSC_VER) | ||||
|    value_test(false, is_standard_signed_integral<__int64>::value) | ||||
|    value_test(false, is_standard_signed_integral<unsigned __int64>::value) | ||||
|    #endif | ||||
|  | ||||
|    value_test(false, is_standard_arithmetic<UDT>::value) | ||||
|    value_test(false, is_standard_arithmetic<void>::value) | ||||
|    value_test(true, is_standard_arithmetic<bool>::value) | ||||
|    value_test(true, is_standard_arithmetic<char>::value) | ||||
|    value_test(true, is_standard_arithmetic<signed char>::value) | ||||
|    value_test(true, is_standard_arithmetic<unsigned char>::value) | ||||
|    value_test(true, is_standard_arithmetic<wchar_t>::value) | ||||
|    value_test(true, is_standard_arithmetic<short>::value) | ||||
|    value_test(true, is_standard_arithmetic<unsigned short>::value) | ||||
|    value_test(true, is_standard_arithmetic<int>::value) | ||||
|    value_test(true, is_standard_arithmetic<unsigned int>::value) | ||||
|    value_test(true, is_standard_arithmetic<long>::value) | ||||
|    value_test(true, is_standard_arithmetic<unsigned long>::value) | ||||
|    value_test(true, is_standard_arithmetic<float>::value) | ||||
|    value_test(true, is_standard_arithmetic<double>::value) | ||||
|    value_test(true, is_standard_arithmetic<long double>::value) | ||||
|    #ifdef ULLONG_MAX | ||||
|    value_test(false, is_standard_arithmetic<long long>::value) | ||||
|    value_test(false, is_standard_arithmetic<unsigned long long>::value) | ||||
|    #endif | ||||
|    #if defined(__BORLANDC__) || defined(_MSC_VER) | ||||
|    value_test(false, is_standard_arithmetic<__int64>::value) | ||||
|    value_test(false, is_standard_arithmetic<unsigned __int64>::value) | ||||
|    #endif | ||||
|  | ||||
|    value_test(false, is_standard_fundamental<UDT>::value) | ||||
|    value_test(true, is_standard_fundamental<void>::value) | ||||
|    value_test(true, is_standard_fundamental<bool>::value) | ||||
|    value_test(true, is_standard_fundamental<char>::value) | ||||
|    value_test(true, is_standard_fundamental<signed char>::value) | ||||
|    value_test(true, is_standard_fundamental<unsigned char>::value) | ||||
|    value_test(true, is_standard_fundamental<wchar_t>::value) | ||||
|    value_test(true, is_standard_fundamental<short>::value) | ||||
|    value_test(true, is_standard_fundamental<unsigned short>::value) | ||||
|    value_test(true, is_standard_fundamental<int>::value) | ||||
|    value_test(true, is_standard_fundamental<unsigned int>::value) | ||||
|    value_test(true, is_standard_fundamental<long>::value) | ||||
|    value_test(true, is_standard_fundamental<unsigned long>::value) | ||||
|    value_test(true, is_standard_fundamental<float>::value) | ||||
|    value_test(true, is_standard_fundamental<double>::value) | ||||
|    value_test(true, is_standard_fundamental<long double>::value) | ||||
|    #ifdef ULLONG_MAX | ||||
|    value_test(false, is_standard_fundamental<long long>::value) | ||||
|    value_test(false, is_standard_fundamental<unsigned long long>::value) | ||||
|    #endif | ||||
|    #if defined(__BORLANDC__) || defined(_MSC_VER) | ||||
|    value_test(false, is_standard_fundamental<__int64>::value) | ||||
|    value_test(false, is_standard_fundamental<unsigned __int64>::value) | ||||
|    #endif | ||||
|  | ||||
|    value_test(false, is_arithmetic<UDT>::value) | ||||
|    value_test(true, is_arithmetic<char>::value) | ||||
|    value_test(true, is_arithmetic<signed char>::value) | ||||
|    value_test(true, is_arithmetic<unsigned char>::value) | ||||
|    value_test(true, is_arithmetic<wchar_t>::value) | ||||
|    value_test(true, is_arithmetic<short>::value) | ||||
|    value_test(true, is_arithmetic<unsigned short>::value) | ||||
|    value_test(true, is_arithmetic<int>::value) | ||||
|    value_test(true, is_arithmetic<unsigned int>::value) | ||||
|    value_test(true, is_arithmetic<long>::value) | ||||
|    value_test(true, is_arithmetic<unsigned long>::value) | ||||
|    value_test(true, is_arithmetic<float>::value) | ||||
|    value_test(true, is_arithmetic<double>::value) | ||||
|    value_test(true, is_arithmetic<long double>::value) | ||||
|    value_test(true, is_arithmetic<bool>::value) | ||||
|    #ifdef ULLONG_MAX | ||||
|    value_test(true, is_arithmetic<long long>::value) | ||||
|    value_test(true, is_arithmetic<unsigned long long>::value) | ||||
|    #endif | ||||
|    #if defined(__BORLANDC__) || defined(_MSC_VER) | ||||
|    value_test(true, is_arithmetic<__int64>::value) | ||||
|    value_test(true, is_arithmetic<unsigned __int64>::value) | ||||
|    #endif | ||||
|  | ||||
|    value_test(false, is_array<int>::value) | ||||
|    value_test(false, is_array<int*>::value) | ||||
|    value_test(true, is_array<int[2]>::value) | ||||
|    value_test(true, is_array<int[2][3]>::value) | ||||
|    value_test(true, is_array<UDT[2]>::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_pointer<int>::value) | ||||
|    value_test(false, is_pointer<int&>::value) | ||||
|    value_test(true, is_pointer<int*>::value) | ||||
|    // Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1 | ||||
|    value_test(false, is_pointer<int*const>::value) | ||||
|    // Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1 | ||||
|    value_test(false, is_pointer<int*volatile>::value) | ||||
|    // Steve: was 'true', should be 'false', via 3.9.2p3, 3.9.3p1 | ||||
|    value_test(false, is_pointer<int*const volatile>::value) | ||||
|    value_test(true, is_pointer<f1>::value) | ||||
|    value_test(true, is_pointer<f2>::value) | ||||
|    value_test(true, is_pointer<f3>::value) | ||||
|    // Steve: was 'true', should be 'false', via 3.9.2p3 | ||||
|    value_test(false, is_pointer<mf1>::value) | ||||
|    // Steve: was 'true', should be 'false', via 3.9.2p3 | ||||
|    value_test(false, is_pointer<mf2>::value) | ||||
|    // Steve: was 'true', should be 'false', via 3.9.2p3 | ||||
|    value_test(false, is_pointer<mf3>::value) | ||||
|    // Steve: was 'true', should be 'false', via 3.9.2p3 | ||||
|    value_test(false, is_pointer<mf4>::value) | ||||
|  | ||||
|    value_test(false, is_reference<bool>::value) | ||||
|    value_test(true, is_reference<int&>::value) | ||||
|    value_test(true, is_reference<const int&>::value) | ||||
|    value_test(true, is_reference<volatile int &>::value) | ||||
|    value_test(true, is_reference<r_type>::value) | ||||
|    value_test(true, is_reference<cr_type>::value) | ||||
|  | ||||
|    value_test(false, is_class<int>::value) | ||||
|    value_test(false, is_class<const int>::value) | ||||
|    value_test(false, is_class<volatile int>::value) | ||||
|    value_test(false, is_class<int*>::value) | ||||
|    value_test(false, is_class<int* const>::value) | ||||
|    value_test(false, is_class<int[2]>::value) | ||||
|    value_test(false, is_class<int&>::value) | ||||
|    value_test(false, is_class<mf4>::value) | ||||
|    value_test(false, is_class<f1>::value) | ||||
|    value_test(false, is_class<enum_UDT>::value) | ||||
|    value_test(true, is_class<UDT>::value) | ||||
|    value_test(true, is_class<UDT const>::value) | ||||
|    value_test(true, is_class<UDT volatile>::value) | ||||
|    value_test(true, is_class<empty_UDT>::value) | ||||
|    value_test(true, is_class<std::iostream>::value) | ||||
|    value_test(false, is_class<UDT*>::value) | ||||
|    value_test(false, is_class<UDT[2]>::value) | ||||
|    value_test(false, is_class<UDT&>::value) | ||||
|  | ||||
|    value_test(true, is_object<int>::value) | ||||
|    value_test(true, is_object<UDT>::value) | ||||
|    value_test(false, is_object<int&>::value) | ||||
|    value_test(false, is_object<void>::value) | ||||
|    value_test(true, is_standard_scalar<int>::value) | ||||
|    value_test(true, is_extension_scalar<void*>::value) | ||||
|  | ||||
|    value_test(false, is_enum<int>::value) | ||||
|    value_test(true, is_enum<enum_UDT>::value) | ||||
|  | ||||
|    value_test(false, is_member_pointer<f1>::value) | ||||
|    value_test(false, is_member_pointer<f2>::value) | ||||
|    value_test(false, is_member_pointer<f3>::value) | ||||
|    value_test(true, is_member_pointer<mf1>::value) | ||||
|    value_test(true, is_member_pointer<mf2>::value) | ||||
|    value_test(true, is_member_pointer<mf3>::value) | ||||
|    value_test(true, is_member_pointer<mf4>::value) | ||||
|  | ||||
|    value_test(false, is_empty<int>::value) | ||||
|    value_test(false, is_empty<int*>::value) | ||||
|    value_test(false, is_empty<int&>::value) | ||||
|    value_test(false, is_empty<int[2]>::value) | ||||
|    value_test(false, is_empty<f1>::value) | ||||
|    value_test(false, is_empty<mf1>::value) | ||||
|    value_test(false, is_empty<UDT>::value) | ||||
|    value_test(true, is_empty<empty_UDT>::value) | ||||
|    value_test(true, is_empty<empty_POD_UDT>::value) | ||||
|    value_test(true, is_empty<empty_union_UDT>::value) | ||||
|    value_test(false, is_empty<enum_UDT>::value) | ||||
|  | ||||
|    value_test(true, has_trivial_constructor<int>::value) | ||||
|    value_test(true, has_trivial_constructor<int*>::value) | ||||
|    value_test(true, has_trivial_constructor<int*const>::value) | ||||
|    value_test(true, has_trivial_constructor<const int>::value) | ||||
|    value_test(true, has_trivial_constructor<volatile int>::value) | ||||
|    value_test(true, has_trivial_constructor<int[2]>::value) | ||||
|    value_test(true, has_trivial_constructor<int[3][2]>::value) | ||||
|    value_test(true, has_trivial_constructor<int[2][4][5][6][3]>::value) | ||||
|    value_test(true, has_trivial_constructor<f1>::value) | ||||
|    value_test(true, has_trivial_constructor<mf2>::value) | ||||
|    value_test(false, has_trivial_constructor<UDT>::value) | ||||
|    value_test(true, has_trivial_constructor<empty_UDT>::value) | ||||
|    value_test(true, has_trivial_constructor<enum_UDT>::value) | ||||
|  | ||||
|    value_test(true, has_trivial_copy<int>::value) | ||||
|    value_test(true, has_trivial_copy<int*>::value) | ||||
|    value_test(true, has_trivial_copy<int*const>::value) | ||||
|    value_test(true, has_trivial_copy<const int>::value) | ||||
|    // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10 | ||||
|    value_test(true, has_trivial_copy<volatile int>::value) | ||||
|    value_test(true, has_trivial_copy<int[2]>::value) | ||||
|    value_test(true, has_trivial_copy<int[3][2]>::value) | ||||
|    value_test(true, has_trivial_copy<int[2][4][5][6][3]>::value) | ||||
|    value_test(true, has_trivial_copy<f1>::value) | ||||
|    value_test(true, has_trivial_copy<mf2>::value) | ||||
|    value_test(false, has_trivial_copy<UDT>::value) | ||||
|    value_test(true, has_trivial_copy<empty_UDT>::value) | ||||
|    value_test(true, has_trivial_copy<enum_UDT>::value) | ||||
|  | ||||
|    value_test(true, has_trivial_assign<int>::value) | ||||
|    value_test(true, has_trivial_assign<int*>::value) | ||||
|    value_test(true, has_trivial_assign<int*const>::value) | ||||
|    value_test(true, has_trivial_assign<const int>::value) | ||||
|    // Steve: was 'false' -- should be 'true' via 3.9p3, 3.9p10 | ||||
|    value_test(true, has_trivial_assign<volatile int>::value) | ||||
|    value_test(true, has_trivial_assign<int[2]>::value) | ||||
|    value_test(true, has_trivial_assign<int[3][2]>::value) | ||||
|    value_test(true, has_trivial_assign<int[2][4][5][6][3]>::value) | ||||
|    value_test(true, has_trivial_assign<f1>::value) | ||||
|    value_test(true, has_trivial_assign<mf2>::value) | ||||
|    value_test(false, has_trivial_assign<UDT>::value) | ||||
|    value_test(true, has_trivial_assign<empty_UDT>::value) | ||||
|    value_test(true, has_trivial_assign<enum_UDT>::value) | ||||
|  | ||||
|    value_test(true, has_trivial_destructor<int>::value) | ||||
|    value_test(true, has_trivial_destructor<int*>::value) | ||||
|    value_test(true, has_trivial_destructor<int*const>::value) | ||||
|    value_test(true, has_trivial_destructor<const int>::value) | ||||
|    value_test(true, has_trivial_destructor<volatile int>::value) | ||||
|    value_test(true, has_trivial_destructor<int[2]>::value) | ||||
|    value_test(true, has_trivial_destructor<int[3][2]>::value) | ||||
|    value_test(true, has_trivial_destructor<int[2][4][5][6][3]>::value) | ||||
|    value_test(true, has_trivial_destructor<f1>::value) | ||||
|    value_test(true, has_trivial_destructor<mf2>::value) | ||||
|    value_test(false, has_trivial_destructor<UDT>::value) | ||||
|    value_test(false, has_trivial_destructor<empty_UDT>::value) | ||||
|    value_test(true, has_trivial_destructor<enum_UDT>::value) | ||||
|  | ||||
|    value_test(true, is_POD<int>::value) | ||||
|    value_test(true, is_POD<int*>::value) | ||||
|    // Steve: was 'true', should be 'false', via 3.9p10 | ||||
|    value_test(false, is_POD<int&>::value) | ||||
|    value_test(true, is_POD<int*const>::value) | ||||
|    value_test(true, is_POD<const int>::value) | ||||
|    // Steve: was 'false', should be 'true', via 3.9p10 | ||||
|    value_test(true, is_POD<volatile int>::value) | ||||
|    // Steve: was 'true', should be 'false', via 3.9p10 | ||||
|    value_test(false, is_POD<const int&>::value) | ||||
|    value_test(true, is_POD<int[2]>::value) | ||||
|    value_test(true, is_POD<int[3][2]>::value) | ||||
|    value_test(true, is_POD<int[2][4][5][6][3]>::value) | ||||
|    value_test(true, is_POD<f1>::value) | ||||
|    value_test(true, is_POD<mf2>::value) | ||||
|    value_test(false, is_POD<UDT>::value) | ||||
|    value_test(false, is_POD<empty_UDT>::value) | ||||
|    value_test(true, is_POD<enum_UDT>::value) | ||||
|  | ||||
|    std::cout << std::endl << test_count << " tests completed (" << failures << " failures)... press any key to exit"; | ||||
|    std::cin.get(); | ||||
|    return failures; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user