444 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			444 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | //  (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. | ||
|  | 
 | ||
|  | // compressed_pair: pair that "compresses" empty members | ||
|  | // (see libs/utility/doc/html/compressed_pair.html) | ||
|  | // | ||
|  | // JM changes 25 Jan 2004: | ||
|  | // For the case where T1 == T2 and both are empty, then first() and second() | ||
|  | // should return different objects. | ||
|  | // 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> | ||
|  | 
 | ||
|  | #include <boost/type_traits/remove_cv.hpp> | ||
|  | #include <boost/type_traits/is_empty.hpp> | ||
|  | #include <boost/type_traits/is_same.hpp> | ||
|  | #include <boost/call_traits.hpp> | ||
|  | 
 | ||
|  | #ifdef BOOST_MSVC | ||
|  | # pragma warning(push) | ||
|  | # pragma warning(disable:4512) | ||
|  | #endif  | ||
|  | namespace boost | ||
|  | { | ||
|  | 
 | ||
|  | template <class T1, class T2> | ||
|  | class compressed_pair; | ||
|  | 
 | ||
|  | 
 | ||
|  | // 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) | ||
|  |    { | ||
|  | #ifndef __GNUC__ | ||
|  |       using std::swap; | ||
|  | #endif | ||
|  |       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) {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(first_param_type x) | ||
|  |          : first_(x) {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(second_param_type y) | ||
|  |          : second_(y) {} | ||
|  | 
 | ||
|  |       first_reference       first()       {return first_;} | ||
|  |       first_const_reference first() const {return first_;} | ||
|  | 
 | ||
|  |       second_reference       second()       {return second_;} | ||
|  |       second_const_reference second() const {return second_;} | ||
|  | 
 | ||
|  |       void swap(::boost::compressed_pair<T1, T2>& 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> | ||
|  |       : protected ::boost::remove_cv<T1>::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_imp() {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(first_param_type x, second_param_type y) | ||
|  |          : first_type(x), second_(y) {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(first_param_type x) | ||
|  |          : first_type(x) {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(second_param_type y) | ||
|  |          : second_(y) {} | ||
|  | 
 | ||
|  |       first_reference       first()       {return *this;} | ||
|  |       first_const_reference first() const {return *this;} | ||
|  | 
 | ||
|  |       second_reference       second()       {return second_;} | ||
|  |       second_const_reference second() const {return second_;} | ||
|  | 
 | ||
|  |       void swap(::boost::compressed_pair<T1,T2>& 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> | ||
|  |       : protected ::boost::remove_cv<T2>::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_imp() {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(first_param_type x, second_param_type y) | ||
|  |          : second_type(y), first_(x) {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(first_param_type x) | ||
|  |          : first_(x) {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(second_param_type y) | ||
|  |          : second_type(y) {} | ||
|  | 
 | ||
|  |       first_reference       first()       {return first_;} | ||
|  |       first_const_reference first() const {return first_;} | ||
|  | 
 | ||
|  |       second_reference       second()       {return *this;} | ||
|  |       second_const_reference second() const {return *this;} | ||
|  | 
 | ||
|  |       void swap(::boost::compressed_pair<T1,T2>& 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> | ||
|  |       : protected ::boost::remove_cv<T1>::type, | ||
|  |         protected ::boost::remove_cv<T2>::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_imp() {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(first_param_type x, second_param_type y) | ||
|  |          : first_type(x), second_type(y) {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(first_param_type x) | ||
|  |          : first_type(x) {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(second_param_type y) | ||
|  |          : second_type(y) {} | ||
|  | 
 | ||
|  |       first_reference       first()       {return *this;} | ||
|  |       first_const_reference first() const {return *this;} | ||
|  | 
 | ||
|  |       second_reference       second()       {return *this;} | ||
|  |       second_const_reference second() const {return *this;} | ||
|  |       // | ||
|  |       // no need to swap empty bases: | ||
|  |       void swap(::boost::compressed_pair<T1,T2>&) {} | ||
|  |    }; | ||
|  | 
 | ||
|  |    // JM | ||
|  |    // 4    T1 == T2, T1 and T2 both empty | ||
|  |    //      Originally this did not store an instance of T2 at all | ||
|  |    //      but that led to problems beause it meant &x.first() == &x.second() | ||
|  |    //      which is not true for any other kind of pair, so now we store an instance | ||
|  |    //      of T2 just in case the user is relying on first() and second() returning | ||
|  |    //      different objects (albeit both empty). | ||
|  |    template <class T1, class T2> | ||
|  |    class compressed_pair_imp<T1, T2, 4> | ||
|  |       : protected ::boost::remove_cv<T1>::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_imp() {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(first_param_type x, second_param_type y) | ||
|  |          : first_type(x), m_second(y) {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(first_param_type x) | ||
|  |          : first_type(x), m_second(x) {} | ||
|  | 
 | ||
|  |       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(::boost::compressed_pair<T1,T2>&) {} | ||
|  |    private: | ||
|  |       T2 m_second; | ||
|  |    }; | ||
|  | 
 | ||
|  |    // 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) {} | ||
|  | 
 | ||
|  |       compressed_pair_imp(first_param_type x) | ||
|  |          : first_(x), second_(x) {} | ||
|  | 
 | ||
|  |       first_reference       first()       {return first_;} | ||
|  |       first_const_reference first() const {return first_;} | ||
|  | 
 | ||
|  |       second_reference       second()       {return second_;} | ||
|  |       second_const_reference second() const {return second_;} | ||
|  | 
 | ||
|  |       void swap(::boost::compressed_pair<T1, T2>& 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) {} | ||
|  | #if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) | ||
|  |    explicit  | ||
|  | #endif | ||
|  |       compressed_pair(first_param_type x) : base(x) {} | ||
|  | 
 | ||
|  |    first_reference       first()       {return base::first();} | ||
|  |    first_const_reference first() const {return base::first();} | ||
|  | 
 | ||
|  |    second_reference       second()       {return base::second();} | ||
|  |    second_const_reference second() const {return base::second();} | ||
|  | 
 | ||
|  |    void swap(::boost::compressed_pair<T,T>& 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 | ||
|  | 
 | ||
|  | #ifdef BOOST_MSVC | ||
|  | # pragma warning(pop) | ||
|  | #endif  | ||
|  | 
 | ||
|  | #endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP | ||
|  | 
 |