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: // see libs/utility/compressed_pair.hpp Chris@16: // Chris@16: /* Release notes: Chris@16: 20 Jan 2001: Chris@16: Fixed obvious bugs (David Abrahams) Chris@16: 07 Oct 2000: Chris@16: Added better single argument constructor support. Chris@16: 03 Oct 2000: Chris@16: Added VC6 support (JM). Chris@16: 23rd July 2000: Chris@16: Additional comments added. (JM) Chris@16: Jan 2000: Chris@16: Original version: this version crippled for use with crippled compilers Chris@16: - John Maddock Jan 2000. Chris@16: */ Chris@16: Chris@16: Chris@16: #ifndef BOOST_OB_COMPRESSED_PAIR_HPP Chris@16: #define BOOST_OB_COMPRESSED_PAIR_HPP Chris@16: Chris@16: #include Chris@16: #ifndef BOOST_OBJECT_TYPE_TRAITS_HPP Chris@16: #include Chris@16: #endif Chris@16: #ifndef BOOST_SAME_TRAITS_HPP Chris@16: #include Chris@16: #endif Chris@16: #ifndef BOOST_CALL_TRAITS_HPP Chris@16: #include Chris@16: #endif Chris@16: Chris@16: namespace boost Chris@16: { Chris@16: #ifdef BOOST_MSVC6_MEMBER_TEMPLATES Chris@16: // Chris@16: // use member templates to emulate Chris@16: // partial specialisation. Note that due to Chris@16: // problems with overload resolution with VC6 Chris@16: // each of the compressed_pair versions that follow Chris@16: // have one template single-argument constructor Chris@16: // in place of two specific constructors: Chris@16: // Chris@16: Chris@16: template Chris@16: class compressed_pair; Chris@16: Chris@16: namespace detail{ Chris@16: Chris@16: template Chris@16: struct best_conversion_traits Chris@16: { Chris@16: typedef char one; Chris@16: typedef char (&two)[2]; Chris@16: static A a; Chris@16: static one test(T1); Chris@16: static two test(T2); Chris@16: Chris@16: enum { value = sizeof(test(a)) }; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct init_one; Chris@16: Chris@16: template <> Chris@16: struct init_one<1> Chris@16: { Chris@16: template Chris@16: static void init(const A& a, T1* p1, T2*) Chris@16: { Chris@16: *p1 = a; Chris@16: } Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct init_one<2> Chris@16: { Chris@16: template Chris@16: static void init(const A& a, T1*, T2* p2) Chris@16: { Chris@16: *p2 = a; Chris@16: } Chris@16: }; Chris@16: Chris@16: Chris@16: // T1 != T2, both non-empty Chris@16: template Chris@16: class compressed_pair_0 Chris@16: { Chris@16: private: Chris@16: T1 _first; Chris@16: T2 _second; 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_0() : _first(), _second() {} Chris@16: compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {} Chris@16: template Chris@16: explicit compressed_pair_0(const A& val) Chris@16: { Chris@16: init_one::value>::init(val, &_first, &_second); Chris@16: } Chris@16: compressed_pair_0(const ::boost::compressed_pair& x) Chris@16: : _first(x.first()), _second(x.second()) {} Chris@16: Chris@16: #if 0 Chris@16: compressed_pair_0& operator=(const compressed_pair_0& x) { Chris@16: cout << "assigning compressed pair 0" << endl; Chris@16: _first = x._first; Chris@16: _second = x._second; Chris@16: cout << "finished assigning compressed pair 0" << endl; Chris@16: return *this; Chris@16: } Chris@16: #endif 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(compressed_pair_0& y) Chris@16: { Chris@16: using std::swap; Chris@16: swap(_first, y._first); Chris@16: swap(_second, y._second); Chris@16: } Chris@16: }; Chris@16: Chris@16: // T1 != T2, T2 empty Chris@16: template Chris@16: class compressed_pair_1 : T2 Chris@16: { Chris@16: private: Chris@16: T1 _first; 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_1() : T2(), _first() {} Chris@16: compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {} Chris@16: Chris@16: template Chris@16: explicit compressed_pair_1(const A& val) Chris@16: { Chris@16: init_one::value>::init(val, &_first, static_cast(this)); Chris@16: } Chris@16: Chris@16: compressed_pair_1(const ::boost::compressed_pair& x) Chris@16: : T2(x.second()), _first(x.first()) {} 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(compressed_pair_1& y) Chris@16: { Chris@16: // no need to swap empty base class: Chris@16: using std::swap; Chris@16: swap(_first, y._first); Chris@16: } Chris@16: }; Chris@16: Chris@16: // T1 != T2, T1 empty Chris@16: template Chris@16: class compressed_pair_2 : T1 Chris@16: { Chris@16: private: Chris@16: T2 _second; 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_2() : T1(), _second() {} Chris@16: compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {} Chris@16: template Chris@16: explicit compressed_pair_2(const A& val) Chris@16: { Chris@16: init_one::value>::init(val, static_cast(this), &_second); Chris@16: } Chris@16: compressed_pair_2(const ::boost::compressed_pair& x) Chris@16: : T1(x.first()), _second(x.second()) {} Chris@16: Chris@16: #if 0 Chris@16: compressed_pair_2& operator=(const compressed_pair_2& x) { Chris@16: cout << "assigning compressed pair 2" << endl; Chris@16: T1::operator=(x); Chris@16: _second = x._second; Chris@16: cout << "finished assigning compressed pair 2" << endl; Chris@16: return *this; Chris@16: } Chris@16: #endif 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(compressed_pair_2& y) Chris@16: { Chris@16: // no need to swap empty base class: Chris@16: using std::swap; Chris@16: swap(_second, y._second); Chris@16: } Chris@16: }; Chris@16: Chris@16: // T1 != T2, both empty Chris@16: template Chris@16: class compressed_pair_3 : T1, T2 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_3() : T1(), T2() {} Chris@16: compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {} Chris@16: template Chris@16: explicit compressed_pair_3(const A& val) Chris@16: { Chris@16: init_one::value>::init(val, static_cast(this), static_cast(this)); Chris@16: } Chris@16: compressed_pair_3(const ::boost::compressed_pair& x) Chris@16: : T1(x.first()), T2(x.second()) {} 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: void swap(compressed_pair_3& y) Chris@16: { Chris@16: // no need to swap empty base classes: Chris@16: } Chris@16: }; Chris@16: Chris@16: // T1 == T2, and empty Chris@16: template Chris@16: class compressed_pair_4 : T1 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_4() : T1() {} Chris@16: compressed_pair_4(first_param_type x, second_param_type y) : T1(x), m_second(y) {} Chris@16: // only one single argument constructor since T1 == T2 Chris@16: explicit compressed_pair_4(first_param_type x) : T1(x), m_second(x) {} Chris@16: compressed_pair_4(const ::boost::compressed_pair& x) Chris@16: : T1(x.first()), m_second(x.second()) {} 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(compressed_pair_4& y) Chris@16: { Chris@16: // no need to swap empty base classes: Chris@16: } Chris@16: private: Chris@16: T2 m_second; Chris@16: }; Chris@16: Chris@16: // T1 == T2, not empty Chris@16: template Chris@16: class compressed_pair_5 Chris@16: { Chris@16: private: Chris@16: T1 _first; Chris@16: T2 _second; 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_5() : _first(), _second() {} Chris@16: compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {} Chris@16: // only one single argument constructor since T1 == T2 Chris@16: explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {} Chris@16: compressed_pair_5(const ::boost::compressed_pair& c) Chris@16: : _first(c.first()), _second(c.second()) {} 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(compressed_pair_5& y) Chris@16: { Chris@16: using std::swap; Chris@16: swap(_first, y._first); Chris@16: swap(_second, y._second); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct compressed_pair_chooser Chris@16: { Chris@16: template Chris@16: struct rebind Chris@16: { Chris@16: typedef compressed_pair_0 type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct compressed_pair_chooser Chris@16: { Chris@16: template Chris@16: struct rebind Chris@16: { Chris@16: typedef compressed_pair_1 type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct compressed_pair_chooser Chris@16: { Chris@16: template Chris@16: struct rebind Chris@16: { Chris@16: typedef compressed_pair_2 type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct compressed_pair_chooser Chris@16: { Chris@16: template Chris@16: struct rebind Chris@16: { Chris@16: typedef compressed_pair_3 type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct compressed_pair_chooser Chris@16: { Chris@16: template Chris@16: struct rebind Chris@16: { Chris@16: typedef compressed_pair_4 type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct compressed_pair_chooser Chris@16: { Chris@16: template Chris@16: struct rebind Chris@16: { Chris@16: typedef compressed_pair_5 type; Chris@16: }; Chris@16: }; Chris@16: Chris@16: template Chris@16: struct compressed_pair_traits Chris@16: { Chris@16: private: Chris@16: typedef compressed_pair_chooser::value, is_empty::value, is_same::value> chooser; Chris@16: typedef typename chooser::template rebind bound_type; Chris@16: public: Chris@16: typedef typename bound_type::type type; Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: Chris@16: template Chris@16: class compressed_pair : public detail::compressed_pair_traits::type Chris@16: { Chris@16: private: Chris@16: typedef typename detail::compressed_pair_traits::type base_type; 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_type() {} Chris@16: compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {} Chris@16: template Chris@16: explicit compressed_pair(const A& x) : base_type(x){} Chris@16: Chris@16: first_reference first() { return base_type::first(); } Chris@16: first_const_reference first() const { return base_type::first(); } Chris@16: Chris@16: second_reference second() { return base_type::second(); } Chris@16: second_const_reference second() const { return base_type::second(); } Chris@16: }; Chris@16: Chris@16: template Chris@16: inline void swap(compressed_pair& x, compressed_pair& y) Chris@16: { Chris@16: x.swap(y); Chris@16: } Chris@16: Chris@16: #else Chris@16: // no partial specialisation, no member templates: Chris@16: Chris@16: template Chris@16: class compressed_pair Chris@16: { Chris@16: private: Chris@16: T1 _first; Chris@16: T2 _second; 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() : _first(), _second() {} Chris@16: compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {} Chris@16: explicit compressed_pair(first_param_type x) : _first(x), _second() {} Chris@16: // can't define this in case T1 == T2: Chris@16: // explicit compressed_pair(second_param_type y) : _first(), _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(compressed_pair& y) Chris@16: { Chris@16: using std::swap; Chris@16: swap(_first, y._first); Chris@16: swap(_second, y._second); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: inline void swap(compressed_pair& x, compressed_pair& y) Chris@16: { Chris@16: x.swap(y); Chris@16: } Chris@16: Chris@16: #endif Chris@16: Chris@16: } // boost Chris@16: Chris@16: #endif // BOOST_OB_COMPRESSED_PAIR_HPP Chris@16: Chris@16: Chris@16: