forked from boostorg/utility
		
	
		
			
				
	
	
		
			511 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			511 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //  (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000.
 | |
| //  Use, modification and distribution are subject to the Boost Software License,
 | |
| //  Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
 | |
| //  http://www.boost.org/LICENSE_1_0.txt).
 | |
| //
 | |
| //  See http://www.boost.org/libs/utility for most recent version including documentation.
 | |
| //  see libs/utility/compressed_pair.hpp
 | |
| //
 | |
| /* Release notes:
 | |
|    20 Jan 2001:
 | |
|         Fixed obvious bugs (David Abrahams)
 | |
|    07 Oct 2000:
 | |
|       Added better single argument constructor support.
 | |
|    03 Oct 2000:
 | |
|       Added VC6 support (JM).
 | |
|    23rd July 2000:
 | |
|       Additional comments added. (JM)
 | |
|    Jan 2000:
 | |
|       Original version: this version crippled for use with crippled compilers
 | |
|       - John Maddock Jan 2000.
 | |
| */
 | |
| 
 | |
| 
 | |
| #ifndef BOOST_OB_COMPRESSED_PAIR_HPP
 | |
| #define BOOST_OB_COMPRESSED_PAIR_HPP
 | |
| 
 | |
| #include <algorithm>
 | |
| #ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
 | |
| #include <boost/type_traits/object_traits.hpp>
 | |
| #endif
 | |
| #ifndef BOOST_SAME_TRAITS_HPP
 | |
| #include <boost/type_traits/same_traits.hpp>
 | |
| #endif
 | |
| #ifndef BOOST_CALL_TRAITS_HPP
 | |
| #include <boost/call_traits.hpp>
 | |
| #endif
 | |
| 
 | |
| namespace boost
 | |
| {
 | |
| #ifdef BOOST_MSVC6_MEMBER_TEMPLATES
 | |
| //
 | |
| // use member templates to emulate
 | |
| // partial specialisation.  Note that due to
 | |
| // problems with overload resolution with VC6
 | |
| // each of the compressed_pair versions that follow
 | |
| // have one template single-argument constructor
 | |
| // in place of two specific constructors:
 | |
| //
 | |
| 
 | |
| template <class T1, class T2>
 | |
| class compressed_pair;
 | |
| 
 | |
| namespace detail{
 | |
| 
 | |
| template <class A, class T1, class T2>
 | |
| struct best_conversion_traits
 | |
| {
 | |
|    typedef char one;
 | |
|    typedef char (&two)[2];
 | |
|    static A a;
 | |
|    static one test(T1);
 | |
|    static two test(T2);
 | |
| 
 | |
|    enum { value = sizeof(test(a)) };
 | |
| };
 | |
| 
 | |
| template <int>
 | |
| struct init_one;
 | |
| 
 | |
| template <>
 | |
| struct init_one<1>
 | |
| {
 | |
|    template <class A, class T1, class T2>
 | |
|    static void init(const A& a, T1* p1, T2*)
 | |
|    {
 | |
|       *p1 = a;
 | |
|    }
 | |
| };
 | |
| 
 | |
| template <>
 | |
| struct init_one<2>
 | |
| {
 | |
|    template <class A, class T1, class T2>
 | |
|    static void init(const A& a, T1*, T2* p2)
 | |
|    {
 | |
|       *p2 = a;
 | |
|    }
 | |
| };
 | |
| 
 | |
| 
 | |
| // T1 != T2, both non-empty
 | |
| template <class T1, class T2>
 | |
| class compressed_pair_0
 | |
| {
 | |
| private:
 | |
|    T1 _first;
 | |
|    T2 _second;
 | |
| public:
 | |
|    typedef T1                                                 first_type;
 | |
|    typedef T2                                                 second_type;
 | |
|    typedef typename call_traits<first_type>::param_type       first_param_type;
 | |
|    typedef typename call_traits<second_type>::param_type      second_param_type;
 | |
|    typedef typename call_traits<first_type>::reference        first_reference;
 | |
|    typedef typename call_traits<second_type>::reference       second_reference;
 | |
|    typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | |
|    typedef typename call_traits<second_type>::const_reference second_const_reference;
 | |
| 
 | |
|             compressed_pair_0() : _first(), _second() {}
 | |
|             compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {}
 | |
|    template <class A>
 | |
|    explicit compressed_pair_0(const A& val)
 | |
|    {
 | |
|       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
 | |
|    }
 | |
|    compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x)
 | |
|       : _first(x.first()), _second(x.second()) {}
 | |
| 
 | |
| #if 0
 | |
|   compressed_pair_0& operator=(const compressed_pair_0& x) {
 | |
|     cout << "assigning compressed pair 0" << endl;
 | |
|     _first = x._first;
 | |
|     _second = x._second;
 | |
|     cout << "finished assigning compressed pair 0" << endl;
 | |
|     return *this;
 | |
|   }
 | |
| #endif
 | |
| 
 | |
|    first_reference       first()       { return _first; }
 | |
|    first_const_reference first() const { return _first; }
 | |
| 
 | |
|    second_reference       second()       { return _second; }
 | |
|    second_const_reference second() const { return _second; }
 | |
| 
 | |
|    void swap(compressed_pair_0& y)
 | |
|    {
 | |
|       using std::swap;
 | |
|       swap(_first, y._first);
 | |
|       swap(_second, y._second);
 | |
|    }
 | |
| };
 | |
| 
 | |
| // T1 != T2, T2 empty
 | |
| template <class T1, class T2>
 | |
| class compressed_pair_1 : T2
 | |
| {
 | |
| private:
 | |
|    T1 _first;
 | |
| public:
 | |
|    typedef T1                                                 first_type;
 | |
|    typedef T2                                                 second_type;
 | |
|    typedef typename call_traits<first_type>::param_type       first_param_type;
 | |
|    typedef typename call_traits<second_type>::param_type      second_param_type;
 | |
|    typedef typename call_traits<first_type>::reference        first_reference;
 | |
|    typedef typename call_traits<second_type>::reference       second_reference;
 | |
|    typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | |
|    typedef typename call_traits<second_type>::const_reference second_const_reference;
 | |
| 
 | |
|             compressed_pair_1() : T2(), _first() {}
 | |
|             compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
 | |
| 
 | |
|    template <class A>
 | |
|    explicit compressed_pair_1(const A& val)
 | |
|    {
 | |
|       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
 | |
|    }
 | |
| 
 | |
|    compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
 | |
|       : T2(x.second()), _first(x.first()) {}
 | |
| 
 | |
| #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
 | |
|   // Total weirdness. If the assignment to _first is moved after
 | |
|   // the call to the inherited operator=, then this breaks graph/test/graph.cpp
 | |
|   // by way of iterator_adaptor.
 | |
|   compressed_pair_1& operator=(const compressed_pair_1& x) {
 | |
|     _first = x._first;
 | |
|     T2::operator=(x);
 | |
|     return *this;
 | |
|   }
 | |
| #endif
 | |
| 
 | |
|    first_reference       first()       { return _first; }
 | |
|    first_const_reference first() const { return _first; }
 | |
| 
 | |
|    second_reference       second()       { return *this; }
 | |
|    second_const_reference second() const { return *this; }
 | |
| 
 | |
|    void swap(compressed_pair_1& y)
 | |
|    {
 | |
|       // no need to swap empty base class:
 | |
|       using std::swap;
 | |
|       swap(_first, y._first);
 | |
|    }
 | |
| };
 | |
| 
 | |
| // T1 != T2, T1 empty
 | |
| template <class T1, class T2>
 | |
| class compressed_pair_2 : T1
 | |
| {
 | |
| private:
 | |
|    T2 _second;
 | |
| public:
 | |
|    typedef T1                                                 first_type;
 | |
|    typedef T2                                                 second_type;
 | |
|    typedef typename call_traits<first_type>::param_type       first_param_type;
 | |
|    typedef typename call_traits<second_type>::param_type      second_param_type;
 | |
|    typedef typename call_traits<first_type>::reference        first_reference;
 | |
|    typedef typename call_traits<second_type>::reference       second_reference;
 | |
|    typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | |
|    typedef typename call_traits<second_type>::const_reference second_const_reference;
 | |
| 
 | |
|             compressed_pair_2() : T1(), _second() {}
 | |
|             compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {}
 | |
|    template <class A>
 | |
|    explicit compressed_pair_2(const A& val)
 | |
|    {
 | |
|       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
 | |
|    }
 | |
|    compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x)
 | |
|       : T1(x.first()), _second(x.second()) {}
 | |
| 
 | |
| #if 0
 | |
|   compressed_pair_2& operator=(const compressed_pair_2& x) {
 | |
|     cout << "assigning compressed pair 2" << endl;
 | |
|     T1::operator=(x);
 | |
|     _second = x._second;
 | |
|     cout << "finished assigning compressed pair 2" << endl;
 | |
|     return *this;
 | |
|   }
 | |
| #endif
 | |
|    first_reference       first()       { return *this; }
 | |
|    first_const_reference first() const { return *this; }
 | |
| 
 | |
|    second_reference       second()       { return _second; }
 | |
|    second_const_reference second() const { return _second; }
 | |
| 
 | |
|    void swap(compressed_pair_2& y)
 | |
|    {
 | |
|       // no need to swap empty base class:
 | |
|       using std::swap;
 | |
|       swap(_second, y._second);
 | |
|    }
 | |
| };
 | |
| 
 | |
| // T1 != T2, both empty
 | |
| template <class T1, class T2>
 | |
| class compressed_pair_3 : T1, T2
 | |
| {
 | |
| public:
 | |
|    typedef T1                                                 first_type;
 | |
|    typedef T2                                                 second_type;
 | |
|    typedef typename call_traits<first_type>::param_type       first_param_type;
 | |
|    typedef typename call_traits<second_type>::param_type      second_param_type;
 | |
|    typedef typename call_traits<first_type>::reference        first_reference;
 | |
|    typedef typename call_traits<second_type>::reference       second_reference;
 | |
|    typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | |
|    typedef typename call_traits<second_type>::const_reference second_const_reference;
 | |
| 
 | |
|             compressed_pair_3() : T1(), T2() {}
 | |
|             compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {}
 | |
|    template <class A>
 | |
|    explicit compressed_pair_3(const A& val)
 | |
|    {
 | |
|       init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
 | |
|    }
 | |
|    compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x)
 | |
|       : T1(x.first()), T2(x.second()) {}
 | |
| 
 | |
|    first_reference       first()       { return *this; }
 | |
|    first_const_reference first() const { return *this; }
 | |
| 
 | |
|    second_reference       second()       { return *this; }
 | |
|    second_const_reference second() const { return *this; }
 | |
| 
 | |
|    void swap(compressed_pair_3& y)
 | |
|    {
 | |
|       // no need to swap empty base classes:
 | |
|    }
 | |
| };
 | |
| 
 | |
| // T1 == T2, and empty
 | |
| template <class T1, class T2>
 | |
| class compressed_pair_4 : T1
 | |
| {
 | |
| public:
 | |
|    typedef T1                                                 first_type;
 | |
|    typedef T2                                                 second_type;
 | |
|    typedef typename call_traits<first_type>::param_type       first_param_type;
 | |
|    typedef typename call_traits<second_type>::param_type      second_param_type;
 | |
|    typedef typename call_traits<first_type>::reference        first_reference;
 | |
|    typedef typename call_traits<second_type>::reference       second_reference;
 | |
|    typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | |
|    typedef typename call_traits<second_type>::const_reference second_const_reference;
 | |
| 
 | |
|             compressed_pair_4() : T1() {}
 | |
|             compressed_pair_4(first_param_type x, second_param_type y) : T1(x), m_second(y) {}
 | |
|    // only one single argument constructor since T1 == T2
 | |
|    explicit compressed_pair_4(first_param_type x) : T1(x), m_second(x) {}
 | |
|    compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
 | |
|       : T1(x.first()), m_second(x.second()) {}
 | |
| 
 | |
|    first_reference       first()       { return *this; }
 | |
|    first_const_reference first() const { return *this; }
 | |
| 
 | |
|    second_reference       second()       { return m_second; }
 | |
|    second_const_reference second() const { return m_second; }
 | |
| 
 | |
|    void swap(compressed_pair_4& y)
 | |
|    {
 | |
|       // no need to swap empty base classes:
 | |
|    }
 | |
| private:
 | |
|    T2 m_second;
 | |
| };
 | |
| 
 | |
| // T1 == T2, not empty
 | |
| template <class T1, class T2>
 | |
| class compressed_pair_5
 | |
| {
 | |
| private:
 | |
|    T1 _first;
 | |
|    T2 _second;
 | |
| public:
 | |
|    typedef T1                                                 first_type;
 | |
|    typedef T2                                                 second_type;
 | |
|    typedef typename call_traits<first_type>::param_type       first_param_type;
 | |
|    typedef typename call_traits<second_type>::param_type      second_param_type;
 | |
|    typedef typename call_traits<first_type>::reference        first_reference;
 | |
|    typedef typename call_traits<second_type>::reference       second_reference;
 | |
|    typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | |
|    typedef typename call_traits<second_type>::const_reference second_const_reference;
 | |
| 
 | |
|             compressed_pair_5() : _first(), _second() {}
 | |
|             compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
 | |
|    // only one single argument constructor since T1 == T2
 | |
|    explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
 | |
|    compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c) 
 | |
|       : _first(c.first()), _second(c.second()) {}
 | |
| 
 | |
|    first_reference       first()       { return _first; }
 | |
|    first_const_reference first() const { return _first; }
 | |
| 
 | |
|    second_reference       second()       { return _second; }
 | |
|    second_const_reference second() const { return _second; }
 | |
| 
 | |
|    void swap(compressed_pair_5& y)
 | |
|    {
 | |
|       using std::swap;
 | |
|       swap(_first, y._first);
 | |
|       swap(_second, y._second);
 | |
|    }
 | |
| };
 | |
| 
 | |
| template <bool e1, bool e2, bool same>
 | |
| struct compressed_pair_chooser
 | |
| {
 | |
|    template <class T1, class T2>
 | |
|    struct rebind
 | |
|    {
 | |
|       typedef compressed_pair_0<T1, T2> type;
 | |
|    };
 | |
| };
 | |
| 
 | |
| template <>
 | |
| struct compressed_pair_chooser<false, true, false>
 | |
| {
 | |
|    template <class T1, class T2>
 | |
|    struct rebind
 | |
|    {
 | |
|       typedef compressed_pair_1<T1, T2> type;
 | |
|    };
 | |
| };
 | |
| 
 | |
| template <>
 | |
| struct compressed_pair_chooser<true, false, false>
 | |
| {
 | |
|    template <class T1, class T2>
 | |
|    struct rebind
 | |
|    {
 | |
|       typedef compressed_pair_2<T1, T2> type;
 | |
|    };
 | |
| };
 | |
| 
 | |
| template <>
 | |
| struct compressed_pair_chooser<true, true, false>
 | |
| {
 | |
|    template <class T1, class T2>
 | |
|    struct rebind
 | |
|    {
 | |
|       typedef compressed_pair_3<T1, T2> type;
 | |
|    };
 | |
| };
 | |
| 
 | |
| template <>
 | |
| struct compressed_pair_chooser<true, true, true>
 | |
| {
 | |
|    template <class T1, class T2>
 | |
|    struct rebind
 | |
|    {
 | |
|       typedef compressed_pair_4<T1, T2> type;
 | |
|    };
 | |
| };
 | |
| 
 | |
| template <>
 | |
| struct compressed_pair_chooser<false, false, true>
 | |
| {
 | |
|    template <class T1, class T2>
 | |
|    struct rebind
 | |
|    {
 | |
|       typedef compressed_pair_5<T1, T2> type;
 | |
|    };
 | |
| };
 | |
| 
 | |
| template <class T1, class T2>
 | |
| struct compressed_pair_traits
 | |
| {
 | |
| private:
 | |
|    typedef compressed_pair_chooser<is_empty<T1>::value, is_empty<T2>::value, is_same<T1,T2>::value> chooser;
 | |
|    typedef typename chooser::template rebind<T1, T2> bound_type;
 | |
| public:
 | |
|    typedef typename bound_type::type type;
 | |
| };
 | |
| 
 | |
| } // namespace detail
 | |
| 
 | |
| template <class T1, class T2>
 | |
| class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
 | |
| {
 | |
| private:
 | |
|    typedef typename detail::compressed_pair_traits<T1, T2>::type base_type;
 | |
| public:
 | |
|    typedef T1                                                 first_type;
 | |
|    typedef T2                                                 second_type;
 | |
|    typedef typename call_traits<first_type>::param_type       first_param_type;
 | |
|    typedef typename call_traits<second_type>::param_type      second_param_type;
 | |
|    typedef typename call_traits<first_type>::reference        first_reference;
 | |
|    typedef typename call_traits<second_type>::reference       second_reference;
 | |
|    typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | |
|    typedef typename call_traits<second_type>::const_reference second_const_reference;
 | |
| 
 | |
|             compressed_pair() : base_type() {}
 | |
|             compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {}
 | |
|    template <class A>
 | |
|    explicit compressed_pair(const A& x) : base_type(x){}
 | |
| 
 | |
|    first_reference       first()       { return base_type::first(); }
 | |
|    first_const_reference first() const { return base_type::first(); }
 | |
| 
 | |
|    second_reference       second()       { return base_type::second(); }
 | |
|    second_const_reference second() const { return base_type::second(); }
 | |
| };
 | |
| 
 | |
| template <class T1, class T2>
 | |
| inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
 | |
| {
 | |
|    x.swap(y);
 | |
| }
 | |
| 
 | |
| #else
 | |
| // no partial specialisation, no member templates:
 | |
| 
 | |
| template <class T1, class T2>
 | |
| class compressed_pair
 | |
| {
 | |
| private:
 | |
|    T1 _first;
 | |
|    T2 _second;
 | |
| public:
 | |
|    typedef T1                                                 first_type;
 | |
|    typedef T2                                                 second_type;
 | |
|    typedef typename call_traits<first_type>::param_type       first_param_type;
 | |
|    typedef typename call_traits<second_type>::param_type      second_param_type;
 | |
|    typedef typename call_traits<first_type>::reference        first_reference;
 | |
|    typedef typename call_traits<second_type>::reference       second_reference;
 | |
|    typedef typename call_traits<first_type>::const_reference  first_const_reference;
 | |
|    typedef typename call_traits<second_type>::const_reference second_const_reference;
 | |
| 
 | |
|             compressed_pair() : _first(), _second() {}
 | |
|             compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {}
 | |
|    explicit compressed_pair(first_param_type x) : _first(x), _second() {}
 | |
|    // can't define this in case T1 == T2:
 | |
|    // explicit compressed_pair(second_param_type y) : _first(), _second(y) {}
 | |
| 
 | |
|    first_reference       first()       { return _first; }
 | |
|    first_const_reference first() const { return _first; }
 | |
| 
 | |
|    second_reference       second()       { return _second; }
 | |
|    second_const_reference second() const { return _second; }
 | |
| 
 | |
|    void swap(compressed_pair& y)
 | |
|    {
 | |
|       using std::swap;
 | |
|       swap(_first, y._first);
 | |
|       swap(_second, y._second);
 | |
|    }
 | |
| };
 | |
| 
 | |
| template <class T1, class T2>
 | |
| inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
 | |
| {
 | |
|    x.swap(y);
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| } // boost
 | |
| 
 | |
| #endif // BOOST_OB_COMPRESSED_PAIR_HPP
 | |
| 
 | |
| 
 | |
| 
 |