// (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/compressed_pair.htm) | |
// | |
// 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 | |