forked from boostorg/utility
Compare commits
1 Commits
svn-branch
...
svn-branch
Author | SHA1 | Date | |
---|---|---|---|
|
8f583902a5 |
@@ -1,155 +0,0 @@
|
||||
// (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.
|
||||
|
||||
// call_traits: defines typedefs for function usage
|
||||
// (see libs/utility/call_traits.htm)
|
||||
|
||||
/* Release notes:
|
||||
23rd July 2000:
|
||||
Fixed array specialization. (JM)
|
||||
Added Borland specific fixes for reference types
|
||||
(issue raised by Steve Cleary).
|
||||
*/
|
||||
|
||||
#ifndef BOOST_DETAIL_CALL_TRAITS_HPP
|
||||
#define BOOST_DETAIL_CALL_TRAITS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
#include <cstddef>
|
||||
|
||||
#include <boost/type_traits/is_arithmetic.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
|
||||
namespace boost{
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <typename T, bool small_>
|
||||
struct ct_imp2
|
||||
{
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ct_imp2<T, true>
|
||||
{
|
||||
typedef const T param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool isp, bool b1>
|
||||
struct ct_imp
|
||||
{
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool isp>
|
||||
struct ct_imp<T, isp, true>
|
||||
{
|
||||
typedef typename ct_imp2<T, sizeof(T) <= sizeof(void*)>::param_type param_type;
|
||||
};
|
||||
|
||||
template <typename T, bool b1>
|
||||
struct ct_imp<T, true, b1>
|
||||
{
|
||||
typedef T const param_type;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct call_traits
|
||||
{
|
||||
public:
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
//
|
||||
// C++ Builder workaround: we should be able to define a compile time
|
||||
// constant and pass that as a single template parameter to ct_imp<T,bool>,
|
||||
// however compiler bugs prevent this - instead pass three bool's to
|
||||
// ct_imp<T,bool,bool,bool> and add an extra partial specialisation
|
||||
// of ct_imp to handle the logic. (JM)
|
||||
typedef typename boost::detail::ct_imp<
|
||||
T,
|
||||
::boost::is_pointer<T>::value,
|
||||
::boost::is_arithmetic<T>::value
|
||||
>::param_type param_type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct call_traits<T&>
|
||||
{
|
||||
typedef T& value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x570 ) )
|
||||
// these are illegal specialisations; cv-qualifies applied to
|
||||
// references have no effect according to [8.3.2p1],
|
||||
// C++ Builder requires them though as it treats cv-qualified
|
||||
// references as distinct types...
|
||||
template <typename T>
|
||||
struct call_traits<T&const>
|
||||
{
|
||||
typedef T& value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
template <typename T>
|
||||
struct call_traits<T&volatile>
|
||||
{
|
||||
typedef T& value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
template <typename T>
|
||||
struct call_traits<T&const volatile>
|
||||
{
|
||||
typedef T& value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef T& param_type; // hh removed const
|
||||
};
|
||||
#endif
|
||||
#if !defined(BOOST_NO_ARRAY_TYPE_SPECIALIZATIONS)
|
||||
template <typename T, std::size_t N>
|
||||
struct call_traits<T [N]>
|
||||
{
|
||||
private:
|
||||
typedef T array_type[N];
|
||||
public:
|
||||
// degrades array to pointer:
|
||||
typedef const T* value_type;
|
||||
typedef array_type& reference;
|
||||
typedef const array_type& const_reference;
|
||||
typedef const T* const param_type;
|
||||
};
|
||||
|
||||
template <typename T, std::size_t N>
|
||||
struct call_traits<const T [N]>
|
||||
{
|
||||
private:
|
||||
typedef const T array_type[N];
|
||||
public:
|
||||
// degrades array to pointer:
|
||||
typedef const T* value_type;
|
||||
typedef array_type& reference;
|
||||
typedef const array_type& const_reference;
|
||||
typedef const T* const param_type;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_DETAIL_CALL_TRAITS_HPP
|
@@ -1,432 +0,0 @@
|
||||
// (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>
|
||||
|
||||
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>
|
||||
: private ::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>
|
||||
: private ::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>
|
||||
: private ::boost::remove_cv<T1>::type,
|
||||
private ::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
|
||||
// Note does not actually store an instance of T2 at all -
|
||||
// but reuses T1 base class for both first() and second().
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_imp<T1, T2, 4>
|
||||
: private ::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
|
||||
|
||||
#endif // BOOST_DETAIL_COMPRESSED_PAIR_HPP
|
||||
|
@@ -1,168 +0,0 @@
|
||||
// (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.
|
||||
//
|
||||
// Crippled version for crippled compilers:
|
||||
// see libs/utility/call_traits.htm
|
||||
//
|
||||
|
||||
/* Release notes:
|
||||
01st October 2000:
|
||||
Fixed call_traits on VC6, using "poor man's partial specialisation",
|
||||
using ideas taken from "Generative programming" by Krzysztof Czarnecki
|
||||
& Ulrich Eisenecker.
|
||||
*/
|
||||
|
||||
#ifndef BOOST_OB_CALL_TRAITS_HPP
|
||||
#define BOOST_OB_CALL_TRAITS_HPP
|
||||
|
||||
#ifndef BOOST_CONFIG_HPP
|
||||
#include <boost/config.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_ARITHMETIC_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/arithmetic_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_COMPOSITE_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/composite_traits.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost{
|
||||
|
||||
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
//
|
||||
// use member templates to emulate
|
||||
// partial specialisation:
|
||||
//
|
||||
namespace detail{
|
||||
|
||||
template <class T>
|
||||
struct standard_call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T& param_type;
|
||||
};
|
||||
template <class T>
|
||||
struct simple_call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T param_type;
|
||||
};
|
||||
template <class T>
|
||||
struct reference_call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T reference;
|
||||
typedef T const_reference;
|
||||
typedef T param_type;
|
||||
};
|
||||
|
||||
template <bool pointer, bool arithmetic, bool reference>
|
||||
struct call_traits_chooser
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
typedef standard_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_traits_chooser<true, false, false>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
typedef simple_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_traits_chooser<false, false, true>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
typedef reference_call_traits<T> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <bool size_is_small>
|
||||
struct call_traits_sizeof_chooser2
|
||||
{
|
||||
template <class T>
|
||||
struct small_rebind
|
||||
{
|
||||
typedef simple_call_traits<T> small_type;
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct call_traits_sizeof_chooser2<false>
|
||||
{
|
||||
template <class T>
|
||||
struct small_rebind
|
||||
{
|
||||
typedef standard_call_traits<T> small_type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct call_traits_chooser<false, true, false>
|
||||
{
|
||||
template <class T>
|
||||
struct rebind
|
||||
{
|
||||
enum { sizeof_choice = (sizeof(T) <= sizeof(void*)) };
|
||||
typedef call_traits_sizeof_chooser2<(sizeof(T) <= sizeof(void*))> chooser;
|
||||
typedef typename chooser::template small_rebind<T> bound_type;
|
||||
typedef typename bound_type::small_type type;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
template <typename T>
|
||||
struct call_traits
|
||||
{
|
||||
private:
|
||||
typedef detail::call_traits_chooser<
|
||||
::boost::is_pointer<T>::value,
|
||||
::boost::is_arithmetic<T>::value,
|
||||
::boost::is_reference<T>::value
|
||||
> chooser;
|
||||
typedef typename chooser::template rebind<T> bound_type;
|
||||
typedef typename bound_type::type call_traits_type;
|
||||
public:
|
||||
typedef typename call_traits_type::value_type value_type;
|
||||
typedef typename call_traits_type::reference reference;
|
||||
typedef typename call_traits_type::const_reference const_reference;
|
||||
typedef typename call_traits_type::param_type param_type;
|
||||
};
|
||||
|
||||
#else
|
||||
//
|
||||
// sorry call_traits is completely non-functional
|
||||
// blame your broken compiler:
|
||||
//
|
||||
|
||||
template <typename T>
|
||||
struct call_traits
|
||||
{
|
||||
typedef T value_type;
|
||||
typedef T& reference;
|
||||
typedef const T& const_reference;
|
||||
typedef const T& param_type;
|
||||
};
|
||||
|
||||
#endif // member templates
|
||||
|
||||
}
|
||||
|
||||
#endif // BOOST_OB_CALL_TRAITS_HPP
|
@@ -1,510 +0,0 @@
|
||||
// (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.
|
||||
// see libs/utility/compressed_pair.hpp
|
||||
//
|
||||
/* Release notes:
|
||||
20 Jan 2001:
|
||||
Fixed obvious bugs (David Abrahams)
|
||||
07 Oct 2000:
|
||||
Added better single argument constructor support.
|
||||
03 Oct 2000:
|
||||
Added VC6 support (JM).
|
||||
23rd July 2000:
|
||||
Additional comments added. (JM)
|
||||
Jan 2000:
|
||||
Original version: this version crippled for use with crippled compilers
|
||||
- John Maddock Jan 2000.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
#define BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#ifndef BOOST_OBJECT_TYPE_TRAITS_HPP
|
||||
#include <boost/type_traits/object_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_SAME_TRAITS_HPP
|
||||
#include <boost/type_traits/same_traits.hpp>
|
||||
#endif
|
||||
#ifndef BOOST_CALL_TRAITS_HPP
|
||||
#include <boost/call_traits.hpp>
|
||||
#endif
|
||||
|
||||
namespace boost
|
||||
{
|
||||
#ifdef BOOST_MSVC6_MEMBER_TEMPLATES
|
||||
//
|
||||
// use member templates to emulate
|
||||
// partial specialisation. Note that due to
|
||||
// problems with overload resolution with VC6
|
||||
// each of the compressed_pair versions that follow
|
||||
// have one template single-argument constructor
|
||||
// in place of two specific constructors:
|
||||
//
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair;
|
||||
|
||||
namespace detail{
|
||||
|
||||
template <class A, class T1, class T2>
|
||||
struct best_conversion_traits
|
||||
{
|
||||
typedef char one;
|
||||
typedef char (&two)[2];
|
||||
static A a;
|
||||
static one test(T1);
|
||||
static two test(T2);
|
||||
|
||||
enum { value = sizeof(test(a)) };
|
||||
};
|
||||
|
||||
template <int>
|
||||
struct init_one;
|
||||
|
||||
template <>
|
||||
struct init_one<1>
|
||||
{
|
||||
template <class A, class T1, class T2>
|
||||
static void init(const A& a, T1* p1, T2*)
|
||||
{
|
||||
*p1 = a;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct init_one<2>
|
||||
{
|
||||
template <class A, class T1, class T2>
|
||||
static void init(const A& a, T1*, T2* p2)
|
||||
{
|
||||
*p2 = a;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// T1 != T2, both non-empty
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_0
|
||||
{
|
||||
private:
|
||||
T1 _first;
|
||||
T2 _second;
|
||||
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_0() : _first(), _second() {}
|
||||
compressed_pair_0(first_param_type x, second_param_type y) : _first(x), _second(y) {}
|
||||
template <class A>
|
||||
explicit compressed_pair_0(const A& val)
|
||||
{
|
||||
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, &_second);
|
||||
}
|
||||
compressed_pair_0(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: _first(x.first()), _second(x.second()) {}
|
||||
|
||||
#if 0
|
||||
compressed_pair_0& operator=(const compressed_pair_0& x) {
|
||||
cout << "assigning compressed pair 0" << endl;
|
||||
_first = x._first;
|
||||
_second = x._second;
|
||||
cout << "finished assigning compressed pair 0" << endl;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
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(compressed_pair_0& y)
|
||||
{
|
||||
using std::swap;
|
||||
swap(_first, y._first);
|
||||
swap(_second, y._second);
|
||||
}
|
||||
};
|
||||
|
||||
// T1 != T2, T2 empty
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_1 : T2
|
||||
{
|
||||
private:
|
||||
T1 _first;
|
||||
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_1() : T2(), _first() {}
|
||||
compressed_pair_1(first_param_type x, second_param_type y) : T2(y), _first(x) {}
|
||||
|
||||
template <class A>
|
||||
explicit compressed_pair_1(const A& val)
|
||||
{
|
||||
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, &_first, static_cast<T2*>(this));
|
||||
}
|
||||
|
||||
compressed_pair_1(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T2(x.second()), _first(x.first()) {}
|
||||
|
||||
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
|
||||
// Total weirdness. If the assignment to _first is moved after
|
||||
// the call to the inherited operator=, then this breaks graph/test/graph.cpp
|
||||
// by way of iterator_adaptor.
|
||||
compressed_pair_1& operator=(const compressed_pair_1& x) {
|
||||
_first = x._first;
|
||||
T2::operator=(x);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
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(compressed_pair_1& y)
|
||||
{
|
||||
// no need to swap empty base class:
|
||||
using std::swap;
|
||||
swap(_first, y._first);
|
||||
}
|
||||
};
|
||||
|
||||
// T1 != T2, T1 empty
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_2 : T1
|
||||
{
|
||||
private:
|
||||
T2 _second;
|
||||
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_2() : T1(), _second() {}
|
||||
compressed_pair_2(first_param_type x, second_param_type y) : T1(x), _second(y) {}
|
||||
template <class A>
|
||||
explicit compressed_pair_2(const A& val)
|
||||
{
|
||||
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), &_second);
|
||||
}
|
||||
compressed_pair_2(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T1(x.first()), _second(x.second()) {}
|
||||
|
||||
#if 0
|
||||
compressed_pair_2& operator=(const compressed_pair_2& x) {
|
||||
cout << "assigning compressed pair 2" << endl;
|
||||
T1::operator=(x);
|
||||
_second = x._second;
|
||||
cout << "finished assigning compressed pair 2" << endl;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
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(compressed_pair_2& y)
|
||||
{
|
||||
// no need to swap empty base class:
|
||||
using std::swap;
|
||||
swap(_second, y._second);
|
||||
}
|
||||
};
|
||||
|
||||
// T1 != T2, both empty
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_3 : T1, T2
|
||||
{
|
||||
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_3() : T1(), T2() {}
|
||||
compressed_pair_3(first_param_type x, second_param_type y) : T1(x), T2(y) {}
|
||||
template <class A>
|
||||
explicit compressed_pair_3(const A& val)
|
||||
{
|
||||
init_one<best_conversion_traits<A, T1, T2>::value>::init(val, static_cast<T1*>(this), static_cast<T2*>(this));
|
||||
}
|
||||
compressed_pair_3(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T1(x.first()), T2(x.second()) {}
|
||||
|
||||
first_reference first() { return *this; }
|
||||
first_const_reference first() const { return *this; }
|
||||
|
||||
second_reference second() { return *this; }
|
||||
second_const_reference second() const { return *this; }
|
||||
|
||||
void swap(compressed_pair_3& y)
|
||||
{
|
||||
// no need to swap empty base classes:
|
||||
}
|
||||
};
|
||||
|
||||
// T1 == T2, and empty
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_4 : T1
|
||||
{
|
||||
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_4() : T1() {}
|
||||
compressed_pair_4(first_param_type x, second_param_type y) : T1(x), m_second(y) {}
|
||||
// only one single argument constructor since T1 == T2
|
||||
explicit compressed_pair_4(first_param_type x) : T1(x), m_second(x) {}
|
||||
compressed_pair_4(const ::boost::compressed_pair<T1,T2>& x)
|
||||
: T1(x.first()), m_second(x.second()) {}
|
||||
|
||||
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(compressed_pair_4& y)
|
||||
{
|
||||
// no need to swap empty base classes:
|
||||
}
|
||||
private:
|
||||
T2 m_second;
|
||||
};
|
||||
|
||||
// T1 == T2, not empty
|
||||
template <class T1, class T2>
|
||||
class compressed_pair_5
|
||||
{
|
||||
private:
|
||||
T1 _first;
|
||||
T2 _second;
|
||||
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_5() : _first(), _second() {}
|
||||
compressed_pair_5(first_param_type x, second_param_type y) : _first(x), _second(y) {}
|
||||
// only one single argument constructor since T1 == T2
|
||||
explicit compressed_pair_5(first_param_type x) : _first(x), _second(x) {}
|
||||
compressed_pair_5(const ::boost::compressed_pair<T1,T2>& c)
|
||||
: _first(c.first()), _second(c.second()) {}
|
||||
|
||||
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(compressed_pair_5& y)
|
||||
{
|
||||
using std::swap;
|
||||
swap(_first, y._first);
|
||||
swap(_second, y._second);
|
||||
}
|
||||
};
|
||||
|
||||
template <bool e1, bool e2, bool same>
|
||||
struct compressed_pair_chooser
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef compressed_pair_0<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct compressed_pair_chooser<false, true, false>
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef compressed_pair_1<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct compressed_pair_chooser<true, false, false>
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef compressed_pair_2<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct compressed_pair_chooser<true, true, false>
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef compressed_pair_3<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct compressed_pair_chooser<true, true, true>
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef compressed_pair_4<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
struct compressed_pair_chooser<false, false, true>
|
||||
{
|
||||
template <class T1, class T2>
|
||||
struct rebind
|
||||
{
|
||||
typedef compressed_pair_5<T1, T2> type;
|
||||
};
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
struct compressed_pair_traits
|
||||
{
|
||||
private:
|
||||
typedef compressed_pair_chooser<is_empty<T1>::value, is_empty<T2>::value, is_same<T1,T2>::value> chooser;
|
||||
typedef typename chooser::template rebind<T1, T2> bound_type;
|
||||
public:
|
||||
typedef typename bound_type::type type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair : public detail::compressed_pair_traits<T1, T2>::type
|
||||
{
|
||||
private:
|
||||
typedef typename detail::compressed_pair_traits<T1, T2>::type base_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() : base_type() {}
|
||||
compressed_pair(first_param_type x, second_param_type y) : base_type(x, y) {}
|
||||
template <class A>
|
||||
explicit compressed_pair(const A& x) : base_type(x){}
|
||||
|
||||
first_reference first() { return base_type::first(); }
|
||||
first_const_reference first() const { return base_type::first(); }
|
||||
|
||||
second_reference second() { return base_type::second(); }
|
||||
second_const_reference second() const { return base_type::second(); }
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
#else
|
||||
// no partial specialisation, no member templates:
|
||||
|
||||
template <class T1, class T2>
|
||||
class compressed_pair
|
||||
{
|
||||
private:
|
||||
T1 _first;
|
||||
T2 _second;
|
||||
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() : _first(), _second() {}
|
||||
compressed_pair(first_param_type x, second_param_type y) : _first(x), _second(y) {}
|
||||
explicit compressed_pair(first_param_type x) : _first(x), _second() {}
|
||||
// can't define this in case T1 == T2:
|
||||
// explicit compressed_pair(second_param_type y) : _first(), _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(compressed_pair& y)
|
||||
{
|
||||
using std::swap;
|
||||
swap(_first, y._first);
|
||||
swap(_second, y._second);
|
||||
}
|
||||
};
|
||||
|
||||
template <class T1, class T2>
|
||||
inline void swap(compressed_pair<T1, T2>& x, compressed_pair<T1, T2>& y)
|
||||
{
|
||||
x.swap(y);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_OB_COMPRESSED_PAIR_HPP
|
||||
|
||||
|
||||
|
443
indirect_iterator.htm
Normal file
443
indirect_iterator.htm
Normal file
@@ -0,0 +1,443 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<meta name="generator" content="HTML Tidy, see www.w3.org">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
|
||||
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
|
||||
<meta name="ProgId" content="FrontPage.Editor.Document">
|
||||
|
||||
<title>Indirect Iterator Adaptor Documentation</title>
|
||||
</head>
|
||||
|
||||
<body bgcolor="#FFFFFF" text="#000000">
|
||||
|
||||
<img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" align=
|
||||
"center" width="277" height="86">
|
||||
|
||||
<h1>Indirect Iterator Adaptor</h1>
|
||||
Defined in header <a href=
|
||||
"../../boost/iterator_adaptors.hpp">boost/iterator_adaptors.hpp</a>
|
||||
|
||||
<p>The indirect iterator adaptor augments an iterator by applying an
|
||||
<b>extra</b> dereference inside of <tt>operator*()</tt>. For example, this
|
||||
iterator makes it possible to view a container of pointers or
|
||||
smart-pointers (e.g. <tt>std::list<boost::shared_ptr<foo>
|
||||
></tt>) as if it were a container of the pointed-to type. The following
|
||||
<b>pseudo-code</b> shows the basic idea of the indirect iterator:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
// inside a hypothetical indirect_iterator class...
|
||||
typedef std::iterator_traits<BaseIterator>::value_type Pointer;
|
||||
typedef std::iterator_traits<Pointer>::reference reference;
|
||||
|
||||
reference indirect_iterator::operator*() const {
|
||||
return **this->base_iterator;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h2>Synopsis</h2>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
namespace boost {
|
||||
template <class BaseIterator,
|
||||
class Value, class Reference, class Category, class Pointer>
|
||||
struct indirect_iterator_generator;
|
||||
|
||||
template <class BaseIterator,
|
||||
class Value, class Reference, class ConstReference,
|
||||
class Category, class Pointer, class ConstPointer>
|
||||
struct indirect_iterator_pair_generator;
|
||||
|
||||
template <class BaseIterator>
|
||||
typename indirect_iterator_generator<BaseIterator>::type
|
||||
make_indirect_iterator(BaseIterator base)
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<h2><a name="indirect_iterator_generator">The Indirect Iterator Type
|
||||
Generator</a></h2>
|
||||
The <tt>indirect_iterator_generator</tt> template is a <a href=
|
||||
"../../more/generic_programming.html#type_generator">generator</a> of
|
||||
indirect iterator types. The main template parameter for this class is the
|
||||
<tt>BaseIterator</tt> type that is being wrapped. In most cases the type of
|
||||
the elements being pointed to can be deduced using
|
||||
<tt>std::iterator_traits</tt>, but in some situations the user may want to
|
||||
override this type, so there are also template parameters that allow a user
|
||||
to control the <tt>value_type</tt>, <tt>pointer</tt>, and
|
||||
<tt>reference</tt> types of the resulting iterators.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class BaseIterator,
|
||||
class Value, class Reference, class Pointer>
|
||||
class indirect_iterator_generator
|
||||
{
|
||||
public:
|
||||
typedef <tt><a href=
|
||||
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> type; // the resulting indirect iterator type
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Example</h3>
|
||||
This example uses the <tt>indirect_iterator_generator</tt> to create
|
||||
indirect iterators which dereference the pointers stored in the
|
||||
<tt>pointers_to_chars</tt> array to access the <tt>char</tt>s in the
|
||||
<tt>characters</tt> array.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
#include <boost/config.hpp>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <boost/iterator_adaptors.hpp>
|
||||
|
||||
int main(int, char*[])
|
||||
{
|
||||
char characters[] = "abcdefg";
|
||||
const int N = sizeof(characters)/sizeof(char) - 1; // -1 since characters has a null char
|
||||
char* pointers_to_chars[N]; // at the end.
|
||||
for (int i = 0; i < N; ++i)
|
||||
pointers_to_chars[i] = &characters[i];
|
||||
|
||||
boost::indirect_iterator_generator<char**, char>::type
|
||||
indirect_first(pointers_to_chars), indirect_last(pointers_to_chars + N);
|
||||
|
||||
std::copy(indirect_first, indirect_last, std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
// to be continued...
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<table border>
|
||||
<tr>
|
||||
<th>Parameter
|
||||
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td><tt>BaseIterator</tt>
|
||||
|
||||
<td>The iterator type being wrapped. The <tt>value_type</tt>
|
||||
of the base iterator should itself be dereferenceable.
|
||||
The return type of the <tt>operator*</tt> for the
|
||||
<tt>value_type</tt> should match the <tt>Reference</tt> type.
|
||||
|
||||
<tr>
|
||||
<td><tt>Value</tt>
|
||||
|
||||
<td>The <tt>value_type</tt> of the resulting iterator, unless const. If
|
||||
Value is <tt>const X</tt>, a conforming compiler makes the
|
||||
<tt>value_type</tt> <tt><i>non-</i>const X</tt><a href=
|
||||
"iterator_adaptors.htm#1">[1]</a>. Note that if the default
|
||||
is used for <tt>Value</tt>, then there must be a valid specialization
|
||||
of <tt>iterator_traits</tt> for the value type of the base iterator.
|
||||
<br>
|
||||
<b>Default:</b> <tt>std::iterator_traits<<br>
|
||||
<20> std::iterator_traits<BaseIterator>::value_type
|
||||
>::value_type</tt><a href="#2">[2]</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>Reference</tt>
|
||||
|
||||
<td>The <tt>reference</tt> type of the resulting iterator, and in
|
||||
particular, the result type of <tt>operator*()</tt>.<br>
|
||||
<b>Default:</b> <tt>Value&</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>Pointer</tt>
|
||||
|
||||
<td>The <tt>pointer</tt> type of the resulting iterator, and in
|
||||
particular, the result type of <tt>operator->()</tt>.<br>
|
||||
<b>Default:</b> <tt>Value*</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>Category</tt>
|
||||
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<BaseIterator>::iterator_category</tt>
|
||||
|
||||
</table>
|
||||
|
||||
<h3>Concept Model</h3>
|
||||
The indirect iterator will model whichever <a href=
|
||||
"http://www.sgi.com/tech/stl/Iterators.html">standard iterator
|
||||
concept category</a> is modeled by the base iterator. Thus, if the
|
||||
base iterator is a model of <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a> then so is the resulting indirect iterator. If
|
||||
the base iterator models a more restrictive concept, the resulting
|
||||
indirect iterator will model the same concept <a href="#3">[3]</a>.
|
||||
|
||||
<h3>Members</h3>
|
||||
The indirect iterator type implements the member functions and operators
|
||||
required of the <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
|
||||
Iterator</a> concept. In addition it has the following constructor:
|
||||
<pre>
|
||||
explicit indirect_iterator_generator::type(const BaseIterator& it)
|
||||
</pre>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
|
||||
<h2><a name="indirect_iterator_pair_generator">The Indirect Iterator Pair
|
||||
Generator</a></h2>
|
||||
Sometimes a pair of <tt>const</tt>/non-<tt>const</tt> pair of iterators is
|
||||
needed, such as when implementing a container. The
|
||||
<tt>indirect_iterator_pair_generator</tt> class makes it more convenient to
|
||||
create this pair of iterator types.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class BaseIterator,
|
||||
class Value, class Pointer, class Reference,
|
||||
class ConstPointer, class ConstReference>
|
||||
class indirect_iterator_pair_generator
|
||||
{
|
||||
public:
|
||||
typedef <tt><a href=
|
||||
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> iterator; // the mutable indirect iterator type
|
||||
typedef <tt><a href=
|
||||
"./iterator_adaptors.htm#iterator_adaptor">iterator_adaptor</a><...></tt> const_iterator; // the immutable indirect iterator type
|
||||
};
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Example</h3>
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
// continuing from the last example...
|
||||
|
||||
typedef boost::indirect_iterator_pair_generator<char**,
|
||||
char, char*, char&, const char*, const char&> PairGen;
|
||||
|
||||
char mutable_characters[N];
|
||||
char* pointers_to_mutable_chars[N];
|
||||
for (int i = 0; i < N; ++i)
|
||||
pointers_to_mutable_chars[i] = &mutable_characters[i];
|
||||
|
||||
PairGen::iterator mutable_indirect_first(pointers_to_mutable_chars),
|
||||
mutable_indirect_last(pointers_to_mutable_chars + N);
|
||||
PairGen::const_iterator const_indirect_first(pointers_to_chars),
|
||||
const_indirect_last(pointers_to_chars + N);
|
||||
|
||||
std::transform(const_indirect_first, const_indirect_last,
|
||||
mutable_indirect_first, std::bind1st(std::plus<char>(), 1));
|
||||
|
||||
std::copy(mutable_indirect_first, mutable_indirect_last,
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
// to be continued...
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>The output is:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
b,c,d,e,f,g,h,
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Template Parameters</h3>
|
||||
|
||||
<table border>
|
||||
<tr>
|
||||
<th>Parameter
|
||||
|
||||
<th>Description
|
||||
|
||||
<tr>
|
||||
<td><tt>BaseIterator</tt>
|
||||
|
||||
<td>The iterator type being wrapped. The <tt>value_type</tt> of the
|
||||
base iterator should itself be dereferenceable.
|
||||
The return type of the <tt>operator*</tt> for the
|
||||
<tt>value_type</tt> should match the <tt>Reference</tt> type.
|
||||
|
||||
<tr>
|
||||
<td><tt>Value</tt>
|
||||
|
||||
<td>The <tt>value_type</tt> of the resulting iterators.
|
||||
If Value is <tt>const X</tt>, a conforming compiler makes the
|
||||
<tt>value_type</tt> <tt><i>non-</i>const X</tt><a href=
|
||||
"iterator_adaptors.htm#1">[1]</a>. Note that if the default
|
||||
is used for <tt>Value</tt>, then there must be a valid
|
||||
specialization of <tt>iterator_traits</tt> for the value type
|
||||
of the base iterator.<br>
|
||||
|
||||
<b>Default:</b> <tt>std::iterator_traits<<br>
|
||||
<20> std::iterator_traits<BaseIterator>::value_type
|
||||
>::value_type</tt><a href="#2">[2]</a>
|
||||
|
||||
<tr>
|
||||
<td><tt>Reference</tt>
|
||||
|
||||
<td>The <tt>reference</tt> type of the resulting <tt>iterator</tt>, and
|
||||
in particular, the result type of its <tt>operator*()</tt>.<br>
|
||||
<b>Default:</b> <tt>Value&</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>Pointer</tt>
|
||||
|
||||
<td>The <tt>pointer</tt> type of the resulting <tt>iterator</tt>, and
|
||||
in particular, the result type of its <tt>operator->()</tt>.<br>
|
||||
<b>Default:</b> <tt>Value*</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>ConstReference</tt>
|
||||
|
||||
<td>The <tt>reference</tt> type of the resulting
|
||||
<tt>const_iterator</tt>, and in particular, the result type of its
|
||||
<tt>operator*()</tt>.<br>
|
||||
<b>Default:</b> <tt>const Value&</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>ConstPointer</tt>
|
||||
|
||||
<td>The <tt>pointer</tt> type of the resulting <tt>const_iterator</tt>,
|
||||
and in particular, the result type of its <tt>operator->()</tt>.<br>
|
||||
<b>Default:</b> <tt>const Value*</tt>
|
||||
|
||||
<tr>
|
||||
<td><tt>Category</tt>
|
||||
<td>The <tt>iterator_category</tt> type for the resulting iterator.<br>
|
||||
<b>Default:</b>
|
||||
<tt>std::iterator_traits<BaseIterator>::iterator_category</tt>
|
||||
</table>
|
||||
|
||||
<h3>Concept Model</h3>
|
||||
|
||||
The indirect iterators will model whichever <a href=
|
||||
"http://www.sgi.com/tech/stl/Iterators.html">standard iterator
|
||||
concept category</a> is modeled by the base iterator. Thus, if the
|
||||
base iterator is a model of <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a> then so are the resulting indirect
|
||||
iterators. If the base iterator models a more restrictive concept,
|
||||
the resulting indirect iterators will model the same concept <a
|
||||
href="#3">[3]</a>.
|
||||
|
||||
|
||||
<h3>Members</h3>
|
||||
The resulting <tt>iterator</tt> and <tt>const_iterator</tt> types implement
|
||||
the member functions and operators required of the <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random Access
|
||||
Iterator</a> concept. In addition they support the following constructors:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
explicit indirect_iterator_pair_generator::iterator(const BaseIterator& it)
|
||||
explicit indirect_iterator_pair_generator::const_iterator(const BaseIterator& it)
|
||||
</pre>
|
||||
</blockquote>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>
|
||||
|
||||
<h2><a name="make_indirect_iterator">The Indirect Iterator Object
|
||||
Generator</a></h2>
|
||||
The <tt>make_indirect_iterator()</tt> function provides a more convenient
|
||||
way to create indirect iterator objects. The function saves the user the
|
||||
trouble of explicitly writing out the iterator types.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
template <class BaseIterator>
|
||||
typename indirect_iterator_generator<BaseIterator>::type
|
||||
make_indirect_iterator(BaseIterator base)
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<h3>Example</h3>
|
||||
Here we again print the <tt>char</tt>s from the array <tt>characters</tt>
|
||||
by accessing them through the array of pointers <tt>pointer_to_chars</tt>,
|
||||
but this time we use the <tt>make_indirect_iterator()</tt> function which
|
||||
saves us some typing.
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
// continuing from the last example...
|
||||
|
||||
std::copy(boost::make_indirect_iterator(pointers_to_chars),
|
||||
boost::make_indirect_iterator(pointers_to_chars + N),
|
||||
std::ostream_iterator<char>(std::cout, ","));
|
||||
std::cout << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
</blockquote>
|
||||
The output is:
|
||||
|
||||
<blockquote>
|
||||
<pre>
|
||||
a,b,c,d,e,f,g,
|
||||
</pre>
|
||||
</blockquote>
|
||||
<hr>
|
||||
|
||||
<h3>Notes</h3>
|
||||
|
||||
<p>
|
||||
|
||||
<p><a name="2">[2]</a> If your compiler does not support partial
|
||||
specialization and the base iterator or its <tt>value_type</tt> is a
|
||||
builtin pointer type, you will not be able to use the default for
|
||||
<tt>Value</tt> and will need to specify this type explicitly.
|
||||
|
||||
<p><a name="3">[3]</a>There is a caveat to which concept the
|
||||
indirect iterator can model. If the return type of the
|
||||
<tt>operator*</tt> for the base iterator's value type is not a
|
||||
true reference, then strickly speaking, the indirect iterator can
|
||||
not be a model of <a href=
|
||||
"http://www.sgi.com/tech/stl/ForwardIterator.html">Forward
|
||||
Iterator</a> or any of the concepts that refine it. In this case
|
||||
the <tt>Category</tt> for the indirect iterator should be
|
||||
specified as <tt>std::input_iterator_tag</tt>. However, even in
|
||||
this case, if the base iterator is a random access iterator, the
|
||||
resulting indirect iterator will still satisfy most of the
|
||||
requirements for <a href=
|
||||
"http://www.sgi.com/tech/stl/RandomAccessIterator.html">Random
|
||||
Access Iterator</a>.
|
||||
|
||||
<hr>
|
||||
|
||||
<p>Revised
|
||||
<!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %b %Y" startspan -->18 Feb 2001<!--webbot bot="Timestamp" endspan i-checksum="14389" -->
|
||||
|
||||
|
||||
<p>© Copyright Jeremy Siek and David Abrahams 2001. Permission to
|
||||
copy, use, modify, sell and distribute this document is granted provided
|
||||
this copyright notice appears in all copies. This document is provided "as
|
||||
is" without express or implied warranty, and with no claim as to its
|
||||
suitability for any purpose.
|
||||
<!-- LocalWords: html charset alt gif hpp BaseIterator const namespace struct
|
||||
-->
|
||||
|
||||
<!-- LocalWords: ConstPointer ConstReference typename iostream int abcdefg
|
||||
-->
|
||||
<!-- LocalWords: sizeof PairGen pre Jeremy Siek David Abrahams
|
||||
-->
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user