Chris@16: // (C) Copyright Steve Cleary, Beman Dawes, Howard Hinnant & John Maddock 2000. Chris@16: // Use, modification and distribution are subject to the Boost Software License, Chris@16: // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt). Chris@16: // Chris@16: // See http://www.boost.org/libs/utility for most recent version including documentation. Chris@16: Chris@16: // compressed_pair: pair that "compresses" empty members Chris@101: // (see libs/utility/doc/html/compressed_pair.html) Chris@16: // Chris@16: // JM changes 25 Jan 2004: Chris@16: // For the case where T1 == T2 and both are empty, then first() and second() Chris@16: // should return different objects. Chris@16: // JM changes 25 Jan 2000: Chris@16: // Removed default arguments from compressed_pair_switch to get Chris@16: // C++ Builder 4 to accept them Chris@16: // rewriten swap to get gcc and C++ builder to compile. Chris@16: // added partial specialisations for case T1 == T2 to avoid duplicate constructor defs. Chris@16: Chris@16: #ifndef BOOST_DETAIL_COMPRESSED_PAIR_HPP Chris@16: #define BOOST_DETAIL_COMPRESSED_PAIR_HPP Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning(push) Chris@16: # pragma warning(disable:4512) Chris@16: #endif Chris@16: namespace boost Chris@16: { Chris@16: Chris@16: template Chris@16: class compressed_pair; Chris@16: Chris@16: Chris@16: // compressed_pair Chris@16: Chris@16: namespace details Chris@16: { Chris@16: // JM altered 26 Jan 2000: Chris@16: template Chris@16: struct compressed_pair_switch; Chris@16: Chris@16: template Chris@16: struct compressed_pair_switch Chris@16: {static const int value = 0;}; Chris@16: Chris@16: template Chris@16: struct compressed_pair_switch Chris@16: {static const int value = 3;}; Chris@16: Chris@16: template Chris@16: struct compressed_pair_switch Chris@16: {static const int value = 1;}; Chris@16: Chris@16: template Chris@16: struct compressed_pair_switch Chris@16: {static const int value = 2;}; Chris@16: Chris@16: template Chris@16: struct compressed_pair_switch Chris@16: {static const int value = 4;}; Chris@16: Chris@16: template Chris@16: struct compressed_pair_switch Chris@16: {static const int value = 5;}; Chris@16: Chris@16: template class compressed_pair_imp; Chris@16: Chris@16: #ifdef __GNUC__ Chris@16: // workaround for GCC (JM): Chris@16: using std::swap; Chris@16: #endif Chris@16: // Chris@16: // can't call unqualified swap from within classname::swap Chris@16: // as Koenig lookup rules will find only the classname::swap Chris@16: // member function not the global declaration, so use cp_swap Chris@16: // as a forwarding function (JM): Chris@16: template Chris@16: inline void cp_swap(T& t1, T& t2) Chris@16: { Chris@16: #ifndef __GNUC__ Chris@16: using std::swap; Chris@16: #endif Chris@16: swap(t1, t2); Chris@16: } Chris@16: Chris@16: // 0 derive from neither Chris@16: Chris@16: template Chris@16: class compressed_pair_imp Chris@16: { Chris@16: public: Chris@16: typedef T1 first_type; Chris@16: typedef T2 second_type; Chris@16: typedef typename call_traits::param_type first_param_type; Chris@16: typedef typename call_traits::param_type second_param_type; Chris@16: typedef typename call_traits::reference first_reference; Chris@16: typedef typename call_traits::reference second_reference; Chris@16: typedef typename call_traits::const_reference first_const_reference; Chris@16: typedef typename call_traits::const_reference second_const_reference; Chris@16: Chris@16: compressed_pair_imp() {} Chris@16: Chris@16: compressed_pair_imp(first_param_type x, second_param_type y) Chris@16: : first_(x), second_(y) {} Chris@16: Chris@16: compressed_pair_imp(first_param_type x) Chris@16: : first_(x) {} Chris@16: Chris@16: compressed_pair_imp(second_param_type y) Chris@16: : second_(y) {} Chris@16: Chris@16: first_reference first() {return first_;} Chris@16: first_const_reference first() const {return first_;} Chris@16: Chris@16: second_reference second() {return second_;} Chris@16: second_const_reference second() const {return second_;} Chris@16: Chris@16: void swap(::boost::compressed_pair& y) Chris@16: { Chris@16: cp_swap(first_, y.first()); Chris@16: cp_swap(second_, y.second()); Chris@16: } Chris@16: private: Chris@16: first_type first_; Chris@16: second_type second_; Chris@16: }; Chris@16: Chris@16: // 1 derive from T1 Chris@16: Chris@16: template Chris@16: class compressed_pair_imp Chris@16: : protected ::boost::remove_cv::type Chris@16: { Chris@16: public: Chris@16: typedef T1 first_type; Chris@16: typedef T2 second_type; Chris@16: typedef typename call_traits::param_type first_param_type; Chris@16: typedef typename call_traits::param_type second_param_type; Chris@16: typedef typename call_traits::reference first_reference; Chris@16: typedef typename call_traits::reference second_reference; Chris@16: typedef typename call_traits::const_reference first_const_reference; Chris@16: typedef typename call_traits::const_reference second_const_reference; Chris@16: Chris@16: compressed_pair_imp() {} Chris@16: Chris@16: compressed_pair_imp(first_param_type x, second_param_type y) Chris@16: : first_type(x), second_(y) {} Chris@16: Chris@16: compressed_pair_imp(first_param_type x) Chris@16: : first_type(x) {} Chris@16: Chris@16: compressed_pair_imp(second_param_type y) Chris@16: : second_(y) {} Chris@16: Chris@16: first_reference first() {return *this;} Chris@16: first_const_reference first() const {return *this;} Chris@16: Chris@16: second_reference second() {return second_;} Chris@16: second_const_reference second() const {return second_;} Chris@16: Chris@16: void swap(::boost::compressed_pair& y) Chris@16: { Chris@16: // no need to swap empty base class: Chris@16: cp_swap(second_, y.second()); Chris@16: } Chris@16: private: Chris@16: second_type second_; Chris@16: }; Chris@16: Chris@16: // 2 derive from T2 Chris@16: Chris@16: template Chris@16: class compressed_pair_imp Chris@16: : protected ::boost::remove_cv::type Chris@16: { Chris@16: public: Chris@16: typedef T1 first_type; Chris@16: typedef T2 second_type; Chris@16: typedef typename call_traits::param_type first_param_type; Chris@16: typedef typename call_traits::param_type second_param_type; Chris@16: typedef typename call_traits::reference first_reference; Chris@16: typedef typename call_traits::reference second_reference; Chris@16: typedef typename call_traits::const_reference first_const_reference; Chris@16: typedef typename call_traits::const_reference second_const_reference; Chris@16: Chris@16: compressed_pair_imp() {} Chris@16: Chris@16: compressed_pair_imp(first_param_type x, second_param_type y) Chris@16: : second_type(y), first_(x) {} Chris@16: Chris@16: compressed_pair_imp(first_param_type x) Chris@16: : first_(x) {} Chris@16: Chris@16: compressed_pair_imp(second_param_type y) Chris@16: : second_type(y) {} Chris@16: Chris@16: first_reference first() {return first_;} Chris@16: first_const_reference first() const {return first_;} Chris@16: Chris@16: second_reference second() {return *this;} Chris@16: second_const_reference second() const {return *this;} Chris@16: Chris@16: void swap(::boost::compressed_pair& y) Chris@16: { Chris@16: // no need to swap empty base class: Chris@16: cp_swap(first_, y.first()); Chris@16: } Chris@16: Chris@16: private: Chris@16: first_type first_; Chris@16: }; Chris@16: Chris@16: // 3 derive from T1 and T2 Chris@16: Chris@16: template Chris@16: class compressed_pair_imp Chris@16: : protected ::boost::remove_cv::type, Chris@16: protected ::boost::remove_cv::type Chris@16: { Chris@16: public: Chris@16: typedef T1 first_type; Chris@16: typedef T2 second_type; Chris@16: typedef typename call_traits::param_type first_param_type; Chris@16: typedef typename call_traits::param_type second_param_type; Chris@16: typedef typename call_traits::reference first_reference; Chris@16: typedef typename call_traits::reference second_reference; Chris@16: typedef typename call_traits::const_reference first_const_reference; Chris@16: typedef typename call_traits::const_reference second_const_reference; Chris@16: Chris@16: compressed_pair_imp() {} Chris@16: Chris@16: compressed_pair_imp(first_param_type x, second_param_type y) Chris@16: : first_type(x), second_type(y) {} Chris@16: Chris@16: compressed_pair_imp(first_param_type x) Chris@16: : first_type(x) {} Chris@16: Chris@16: compressed_pair_imp(second_param_type y) Chris@16: : second_type(y) {} Chris@16: Chris@16: first_reference first() {return *this;} Chris@16: first_const_reference first() const {return *this;} Chris@16: Chris@16: second_reference second() {return *this;} Chris@16: second_const_reference second() const {return *this;} Chris@16: // Chris@16: // no need to swap empty bases: Chris@16: void swap(::boost::compressed_pair&) {} Chris@16: }; Chris@16: Chris@16: // JM Chris@16: // 4 T1 == T2, T1 and T2 both empty Chris@16: // Originally this did not store an instance of T2 at all Chris@16: // but that led to problems beause it meant &x.first() == &x.second() Chris@16: // which is not true for any other kind of pair, so now we store an instance Chris@16: // of T2 just in case the user is relying on first() and second() returning Chris@16: // different objects (albeit both empty). Chris@16: template Chris@16: class compressed_pair_imp Chris@16: : protected ::boost::remove_cv::type Chris@16: { Chris@16: public: Chris@16: typedef T1 first_type; Chris@16: typedef T2 second_type; Chris@16: typedef typename call_traits::param_type first_param_type; Chris@16: typedef typename call_traits::param_type second_param_type; Chris@16: typedef typename call_traits::reference first_reference; Chris@16: typedef typename call_traits::reference second_reference; Chris@16: typedef typename call_traits::const_reference first_const_reference; Chris@16: typedef typename call_traits::const_reference second_const_reference; Chris@16: Chris@16: compressed_pair_imp() {} Chris@16: Chris@16: compressed_pair_imp(first_param_type x, second_param_type y) Chris@16: : first_type(x), m_second(y) {} Chris@16: Chris@16: compressed_pair_imp(first_param_type x) Chris@16: : first_type(x), m_second(x) {} Chris@16: Chris@16: first_reference first() {return *this;} Chris@16: first_const_reference first() const {return *this;} Chris@16: Chris@16: second_reference second() {return m_second;} Chris@16: second_const_reference second() const {return m_second;} Chris@16: Chris@16: void swap(::boost::compressed_pair&) {} Chris@16: private: Chris@16: T2 m_second; Chris@16: }; Chris@16: Chris@16: // 5 T1 == T2 and are not empty: //JM Chris@16: Chris@16: template Chris@16: class compressed_pair_imp Chris@16: { Chris@16: public: Chris@16: typedef T1 first_type; Chris@16: typedef T2 second_type; Chris@16: typedef typename call_traits::param_type first_param_type; Chris@16: typedef typename call_traits::param_type second_param_type; Chris@16: typedef typename call_traits::reference first_reference; Chris@16: typedef typename call_traits::reference second_reference; Chris@16: typedef typename call_traits::const_reference first_const_reference; Chris@16: typedef typename call_traits::const_reference second_const_reference; Chris@16: Chris@16: compressed_pair_imp() {} Chris@16: Chris@16: compressed_pair_imp(first_param_type x, second_param_type y) Chris@16: : first_(x), second_(y) {} Chris@16: Chris@16: compressed_pair_imp(first_param_type x) Chris@16: : first_(x), second_(x) {} Chris@16: Chris@16: first_reference first() {return first_;} Chris@16: first_const_reference first() const {return first_;} Chris@16: Chris@16: second_reference second() {return second_;} Chris@16: second_const_reference second() const {return second_;} Chris@16: Chris@16: void swap(::boost::compressed_pair& y) Chris@16: { Chris@16: cp_swap(first_, y.first()); Chris@16: cp_swap(second_, y.second()); Chris@16: } Chris@16: private: Chris@16: first_type first_; Chris@16: second_type second_; Chris@16: }; Chris@16: Chris@16: } // details Chris@16: Chris@16: template Chris@16: class compressed_pair Chris@16: : private ::boost::details::compressed_pair_imp::type, typename remove_cv::type>::value, Chris@16: ::boost::is_empty::value, Chris@16: ::boost::is_empty::value>::value> Chris@16: { Chris@16: private: Chris@16: typedef details::compressed_pair_imp::type, typename remove_cv::type>::value, Chris@16: ::boost::is_empty::value, Chris@16: ::boost::is_empty::value>::value> base; Chris@16: public: Chris@16: typedef T1 first_type; Chris@16: typedef T2 second_type; Chris@16: typedef typename call_traits::param_type first_param_type; Chris@16: typedef typename call_traits::param_type second_param_type; Chris@16: typedef typename call_traits::reference first_reference; Chris@16: typedef typename call_traits::reference second_reference; Chris@16: typedef typename call_traits::const_reference first_const_reference; Chris@16: typedef typename call_traits::const_reference second_const_reference; Chris@16: Chris@16: compressed_pair() : base() {} Chris@16: compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} Chris@16: explicit compressed_pair(first_param_type x) : base(x) {} Chris@16: explicit compressed_pair(second_param_type y) : base(y) {} Chris@16: Chris@16: first_reference first() {return base::first();} Chris@16: first_const_reference first() const {return base::first();} Chris@16: Chris@16: second_reference second() {return base::second();} Chris@16: second_const_reference second() const {return base::second();} Chris@16: Chris@16: void swap(compressed_pair& y) { base::swap(y); } Chris@16: }; Chris@16: Chris@16: // JM Chris@16: // Partial specialisation for case where T1 == T2: Chris@16: // Chris@16: template Chris@16: class compressed_pair Chris@16: : private details::compressed_pair_imp::type, typename remove_cv::type>::value, Chris@16: ::boost::is_empty::value, Chris@16: ::boost::is_empty::value>::value> Chris@16: { Chris@16: private: Chris@16: typedef details::compressed_pair_imp::type, typename remove_cv::type>::value, Chris@16: ::boost::is_empty::value, Chris@16: ::boost::is_empty::value>::value> base; Chris@16: public: Chris@16: typedef T first_type; Chris@16: typedef T second_type; Chris@16: typedef typename call_traits::param_type first_param_type; Chris@16: typedef typename call_traits::param_type second_param_type; Chris@16: typedef typename call_traits::reference first_reference; Chris@16: typedef typename call_traits::reference second_reference; Chris@16: typedef typename call_traits::const_reference first_const_reference; Chris@16: typedef typename call_traits::const_reference second_const_reference; Chris@16: Chris@16: compressed_pair() : base() {} Chris@16: compressed_pair(first_param_type x, second_param_type y) : base(x, y) {} Chris@16: #if !(defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x530)) Chris@16: explicit Chris@16: #endif Chris@16: compressed_pair(first_param_type x) : base(x) {} Chris@16: Chris@16: first_reference first() {return base::first();} Chris@16: first_const_reference first() const {return base::first();} Chris@16: Chris@16: second_reference second() {return base::second();} Chris@16: second_const_reference second() const {return base::second();} Chris@16: Chris@16: void swap(::boost::compressed_pair& y) { base::swap(y); } Chris@16: }; Chris@16: Chris@16: template Chris@16: inline Chris@16: void Chris@16: swap(compressed_pair& x, compressed_pair& y) Chris@16: { Chris@16: x.swap(y); Chris@16: } Chris@16: Chris@16: } // boost Chris@16: Chris@16: #ifdef BOOST_MSVC Chris@16: # pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: #endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP Chris@16: