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