/* Metrowerks Standard Library
 * Copyright  1995-2004 Metrowerks Corporation.  All rights reserved.
 *
 * $Date: 2004/07/30 15:39:13 $
 * $Revision: 1.7.2.6 $
 */

// tuple

#ifndef _TUPLE
#define _TUPLE

/*  tuple synopsis

namespace std
{
namespace tr1
{

}  // tr1
}  // std
*/

#include <mslconfig>

#include <iosfwd>
#include <stringfwd>
#include <utility>
#include <functional>
#include <msl_utility>
#include <array>

#ifndef RC_INVOKED

#ifdef __MWERKS__
#pragma options align=native
#endif

#ifdef _MSL_FORCE_ENUMS_ALWAYS_INT
	#if _MSL_FORCE_ENUMS_ALWAYS_INT
		#pragma enumsalwaysint on
	#else
		#pragma enumsalwaysint off
	#endif
#endif  // _MSL_FORCE_ENUMS_ALWAYS_INT

#ifdef _MSL_FORCE_ENABLE_BOOL_SUPPORT
	#if _MSL_FORCE_ENABLE_BOOL_SUPPORT
		#pragma bool on
	#else
		#pragma bool off
	#endif
#endif  // _MSL_FORCE_ENABLE_BOOL_SUPPORT

_MSL_START_TR1_NAMESPACE

namespace detail
{

template <class T>
struct stored_type
{
	typedef typename Metrowerks::select
	<
		Metrowerks::is_function<T>::value,
		nat,
		typename Metrowerks::select
		<
			Metrowerks::is_void<T>::value,
			nat,
			T
		>::type
	>::type type;
};

template <class T>
struct param
{
	typedef const T& type;
};

template <class T>
struct param<T&>
{
	typedef T& type;
};

template <unsigned int N, class P>
struct get_helper;

}  // detail

template <class T0, class T1, class T2, class T3, class T4,
          class T5, class T6, class T7, class T8, class T9>
class tuple
{
public:
	tuple() {}
	tuple(typename detail::param<T0>::type t0,
	      typename detail::param<T1>::type t1,
	      typename detail::param<T2>::type t2,
	      typename detail::param<T3>::type t3,
	      typename detail::param<T4>::type t4,
	      typename detail::param<T5>::type t5,
	      typename detail::param<T6>::type t6,
	      typename detail::param<T7>::type t7,
	      typename detail::param<T8>::type t8,
	      typename detail::param<T9>::type t9)
	      : data0_(t0), data1_(t1), data2_(t2), data3_(t3), data4_(t4),
	        data5_(t5), data6_(t6), data7_(t7), data8_(t8), data9_(t9) {}

	template <class P>
	tuple(const P& p, typename Metrowerks::restrict_to<__tuple_convertible<P, tuple>::value>::type* = 0);

	template <class P>
	tuple&
	operator=(const P& p) {return assign(*this, p);}
private:
	typename detail::stored_type<T0>::type data0_;
	typename detail::stored_type<T1>::type data1_;
	typename detail::stored_type<T2>::type data2_;
	typename detail::stored_type<T3>::type data3_;
	typename detail::stored_type<T4>::type data4_;
	typename detail::stored_type<T5>::type data5_;
	typename detail::stored_type<T6>::type data6_;
	typename detail::stored_type<T7>::type data7_;
	typename detail::stored_type<T8>::type data8_;
	typename detail::stored_type<T9>::type data9_;

	friend struct detail::get_helper<0, tuple>;
	friend struct detail::get_helper<1, tuple>;
	friend struct detail::get_helper<2, tuple>;
	friend struct detail::get_helper<3, tuple>;
	friend struct detail::get_helper<4, tuple>;
	friend struct detail::get_helper<5, tuple>;
	friend struct detail::get_helper<6, tuple>;
	friend struct detail::get_helper<7, tuple>;
	friend struct detail::get_helper<8, tuple>;
	friend struct detail::get_helper<9, tuple>;
};

template <>
class tuple<nat, nat, nat, nat, nat, nat, nat, nat, nat, nat>
{
public:
	template <class charT, class traits>
	static const charT* open(basic_ios<charT, traits>& s);

	template <class charT, class traits>
	static const charT* close(basic_ios<charT, traits>& s);

	template <class charT, class traits>
	static const charT* delimiter(basic_ios<charT, traits>& s);

	template <class charT>
	static void set_open(ios_base& s, const charT* c);

	template <class charT>
	static void set_close(ios_base& s, const charT* c);

	template <class charT>
	static void set_delimiter(ios_base& s, const charT* c);
private:

	template <class charT>
	static basic_string<charT>& open_storage(ios_base& s);

	template <class charT>
	static basic_string<charT>& close_storage(ios_base& s);

	template <class charT>
	static basic_string<charT>& delimiter_storage(ios_base& s);
};

template <class T0>
class tuple<T0, nat, nat, nat, nat, nat, nat, nat, nat, nat>
{
public:
	tuple() {}
	explicit tuple(typename detail::param<T0>::type t0)
	      : data0_(t0) {}

	template <class P>
	tuple(const P& p, typename Metrowerks::restrict_to<__tuple_convertible<P, tuple>::value>::type* = 0);

	template <class P>
	tuple&
	operator=(const P& p) {return assign(*this, p);}
private:
	typename detail::stored_type<T0>::type data0_;

	friend struct detail::get_helper<0, tuple>;
};

template <class T0, class T1>
class tuple<T0, T1, nat, nat, nat, nat, nat, nat, nat, nat>
{
public:
	tuple() {}
	tuple(typename detail::param<T0>::type t0,
	      typename detail::param<T1>::type t1)
	      : data0_(t0), data1_(t1) {}

	template <class P>
	tuple(const P& p, typename Metrowerks::restrict_to<__tuple_convertible<P, tuple>::value>::type* = 0);

	template <class P>
	tuple&
	operator=(const P& p) {return assign(*this, p);}
private:
	typename detail::stored_type<T0>::type data0_;
	typename detail::stored_type<T1>::type data1_;

	friend struct detail::get_helper<0, tuple>;
	friend struct detail::get_helper<1, tuple>;
};

template <class T0, class T1, class T2>
class tuple<T0, T1, T2, nat, nat, nat, nat, nat, nat, nat>
{
public:
	tuple() {}
	tuple(typename detail::param<T0>::type t0,
	      typename detail::param<T1>::type t1,
	      typename detail::param<T2>::type t2)
	      : data0_(t0), data1_(t1), data2_(t2) {}

	template <class P>
	tuple(const P& p, typename Metrowerks::restrict_to<__tuple_convertible<P, tuple>::value>::type* = 0);
	
	template <class P>
	tuple&
	operator=(const P& p) {return assign(*this, p);}
private:
	typename detail::stored_type<T0>::type data0_;
	typename detail::stored_type<T1>::type data1_;
	typename detail::stored_type<T2>::type data2_;

	friend struct detail::get_helper<0, tuple>;
	friend struct detail::get_helper<1, tuple>;
	friend struct detail::get_helper<2, tuple>;
};

template <class T0, class T1, class T2, class T3>
class tuple<T0, T1, T2, T3, nat, nat, nat, nat, nat, nat>
{
public:
	tuple() {}
	tuple(typename detail::param<T0>::type t0,
	      typename detail::param<T1>::type t1,
	      typename detail::param<T2>::type t2,
	      typename detail::param<T3>::type t3)
	      : data0_(t0), data1_(t1), data2_(t2), data3_(t3) {}

	template <class P>
	tuple(const P& p, typename Metrowerks::restrict_to<__tuple_convertible<P, tuple>::value>::type* = 0);

	template <class P>
	tuple&
	operator=(const P& p) {return assign(*this, p);}
private:
	typename detail::stored_type<T0>::type data0_;
	typename detail::stored_type<T1>::type data1_;
	typename detail::stored_type<T2>::type data2_;
	typename detail::stored_type<T3>::type data3_;

	friend struct detail::get_helper<0, tuple>;
	friend struct detail::get_helper<1, tuple>;
	friend struct detail::get_helper<2, tuple>;
	friend struct detail::get_helper<3, tuple>;
};

template <class T0, class T1, class T2, class T3, class T4>
class tuple<T0, T1, T2, T3, T4, nat, nat, nat, nat, nat>
{
public:
	tuple() {}
	tuple(typename detail::param<T0>::type t0,
	      typename detail::param<T1>::type t1,
	      typename detail::param<T2>::type t2,
	      typename detail::param<T3>::type t3,
	      typename detail::param<T4>::type t4)
	      : data0_(t0), data1_(t1), data2_(t2), data3_(t3), data4_(t4) {}

	template <class P>
	tuple(const P& p, typename Metrowerks::restrict_to<__tuple_convertible<P, tuple>::value>::type* = 0);

	template <class P>
	tuple&
	operator=(const P& p) {return assign(*this, p);}
private:
	typename detail::stored_type<T0>::type data0_;
	typename detail::stored_type<T1>::type data1_;
	typename detail::stored_type<T2>::type data2_;
	typename detail::stored_type<T3>::type data3_;
	typename detail::stored_type<T4>::type data4_;

	friend struct detail::get_helper<0, tuple>;
	friend struct detail::get_helper<1, tuple>;
	friend struct detail::get_helper<2, tuple>;
	friend struct detail::get_helper<3, tuple>;
	friend struct detail::get_helper<4, tuple>;
};

template <class T0, class T1, class T2, class T3, class T4,
          class T5>
class tuple<T0, T1, T2, T3, T4, T5, nat, nat, nat, nat>
{
public:
	tuple() {}
	tuple(typename detail::param<T0>::type t0,
	      typename detail::param<T1>::type t1,
	      typename detail::param<T2>::type t2,
	      typename detail::param<T3>::type t3,
	      typename detail::param<T4>::type t4,
	      typename detail::param<T5>::type t5)
	      : data0_(t0), data1_(t1), data2_(t2), data3_(t3), data4_(t4),
	        data5_(t5) {}

	template <class P>
	tuple(const P& p, typename Metrowerks::restrict_to<__tuple_convertible<P, tuple>::value>::type* = 0);

	template <class P>
	tuple&
	operator=(const P& p) {return assign(*this, p);}
private:
	typename detail::stored_type<T0>::type data0_;
	typename detail::stored_type<T1>::type data1_;
	typename detail::stored_type<T2>::type data2_;
	typename detail::stored_type<T3>::type data3_;
	typename detail::stored_type<T4>::type data4_;
	typename detail::stored_type<T5>::type data5_;

	friend struct detail::get_helper<0, tuple>;
	friend struct detail::get_helper<1, tuple>;
	friend struct detail::get_helper<2, tuple>;
	friend struct detail::get_helper<3, tuple>;
	friend struct detail::get_helper<4, tuple>;
	friend struct detail::get_helper<5, tuple>;
};

template <class T0, class T1, class T2, class T3, class T4,
          class T5, class T6>
class tuple<T0, T1, T2, T3, T4, T5, T6, nat, nat, nat>
{
public:
	tuple() {}
	tuple(typename detail::param<T0>::type t0,
	      typename detail::param<T1>::type t1,
	      typename detail::param<T2>::type t2,
	      typename detail::param<T3>::type t3,
	      typename detail::param<T4>::type t4,
	      typename detail::param<T5>::type t5,
	      typename detail::param<T6>::type t6)
	      : data0_(t0), data1_(t1), data2_(t2), data3_(t3), data4_(t4),
	        data5_(t5), data6_(t6) {}

	template <class P>
	tuple(const P& p, typename Metrowerks::restrict_to<__tuple_convertible<P, tuple>::value>::type* = 0);

	template <class P>
	tuple&
	operator=(const P& p) {return assign(*this, p);}
private:
	typename detail::stored_type<T0>::type data0_;
	typename detail::stored_type<T1>::type data1_;
	typename detail::stored_type<T2>::type data2_;
	typename detail::stored_type<T3>::type data3_;
	typename detail::stored_type<T4>::type data4_;
	typename detail::stored_type<T5>::type data5_;
	typename detail::stored_type<T6>::type data6_;

	friend struct detail::get_helper<0, tuple>;
	friend struct detail::get_helper<1, tuple>;
	friend struct detail::get_helper<2, tuple>;
	friend struct detail::get_helper<3, tuple>;
	friend struct detail::get_helper<4, tuple>;
	friend struct detail::get_helper<5, tuple>;
	friend struct detail::get_helper<6, tuple>;
};

template <class T0, class T1, class T2, class T3, class T4,
          class T5, class T6, class T7>
class tuple<T0, T1, T2, T3, T4, T5, T6, T7, nat, nat>
{
public:
	tuple() {}
	tuple(typename detail::param<T0>::type t0,
	      typename detail::param<T1>::type t1,
	      typename detail::param<T2>::type t2,
	      typename detail::param<T3>::type t3,
	      typename detail::param<T4>::type t4,
	      typename detail::param<T5>::type t5,
	      typename detail::param<T6>::type t6,
	      typename detail::param<T7>::type t7)
	      : data0_(t0), data1_(t1), data2_(t2), data3_(t3), data4_(t4),
	        data5_(t5), data6_(t6), data7_(t7) {}

	template <class P>
	tuple(const P& p, typename Metrowerks::restrict_to<__tuple_convertible<P, tuple>::value>::type* = 0);

	template <class P>
	tuple&
	operator=(const P& p) {return assign(*this, p);}
private:
	typename detail::stored_type<T0>::type data0_;
	typename detail::stored_type<T1>::type data1_;
	typename detail::stored_type<T2>::type data2_;
	typename detail::stored_type<T3>::type data3_;
	typename detail::stored_type<T4>::type data4_;
	typename detail::stored_type<T5>::type data5_;
	typename detail::stored_type<T6>::type data6_;
	typename detail::stored_type<T7>::type data7_;

	friend struct detail::get_helper<0, tuple>;
	friend struct detail::get_helper<1, tuple>;
	friend struct detail::get_helper<2, tuple>;
	friend struct detail::get_helper<3, tuple>;
	friend struct detail::get_helper<4, tuple>;
	friend struct detail::get_helper<5, tuple>;
	friend struct detail::get_helper<6, tuple>;
	friend struct detail::get_helper<7, tuple>;
};

template <class T0, class T1, class T2, class T3, class T4,
          class T5, class T6, class T7, class T8>
class tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, nat>
{
public:
	tuple() {}
	tuple(typename detail::param<T0>::type t0,
	      typename detail::param<T1>::type t1,
	      typename detail::param<T2>::type t2,
	      typename detail::param<T3>::type t3,
	      typename detail::param<T4>::type t4,
	      typename detail::param<T5>::type t5,
	      typename detail::param<T6>::type t6,
	      typename detail::param<T7>::type t7,
	      typename detail::param<T8>::type t8)
	      : data0_(t0), data1_(t1), data2_(t2), data3_(t3), data4_(t4),
	        data5_(t5), data6_(t6), data7_(t7), data8_(t8) {}

	template <class P>
	tuple(const P& p, typename Metrowerks::restrict_to<__tuple_convertible<P, tuple>::value>::type* = 0);

	template <class P>
	tuple&
	operator=(const P& p) {return assign(*this, p);}
private:
	typename detail::stored_type<T0>::type data0_;
	typename detail::stored_type<T1>::type data1_;
	typename detail::stored_type<T2>::type data2_;
	typename detail::stored_type<T3>::type data3_;
	typename detail::stored_type<T4>::type data4_;
	typename detail::stored_type<T5>::type data5_;
	typename detail::stored_type<T6>::type data6_;
	typename detail::stored_type<T7>::type data7_;
	typename detail::stored_type<T8>::type data8_;

	friend struct detail::get_helper<0, tuple>;
	friend struct detail::get_helper<1, tuple>;
	friend struct detail::get_helper<2, tuple>;
	friend struct detail::get_helper<3, tuple>;
	friend struct detail::get_helper<4, tuple>;
	friend struct detail::get_helper<5, tuple>;
	friend struct detail::get_helper<6, tuple>;
	friend struct detail::get_helper<7, tuple>;
	friend struct detail::get_helper<8, tuple>;
};

template <class T, size_t N>
struct is_tuple_like<array<T, N> >
{
	static const bool value = true;
};

template <class T, size_t N>
struct tuple_element<0, array<T, N> >
{
private:
	static const size_t range_error = sizeof(Metrowerks::compile_assert<0 < N>);
public:
	typedef typename T type;
};

template <unsigned I, class T, size_t N>
struct tuple_element<I, array<T, N> >
{
private:
	static const size_t range_error = sizeof(Metrowerks::compile_assert<I < N>);
public:
	typedef typename T type;
};

// get

namespace detail
{

template <class P>
struct get_helper<0, P>
{
	explicit get_helper(P& p) : p_(p) {}
	typename Metrowerks::add_reference<typename tuple_element<0, P>::type>::type
	operator()()
	{
		return p_.data0_;
	}
private:
	P& p_;
};

template <class P>
struct get_helper<1, P>
{
	explicit get_helper(P& p) : p_(p) {}
	typename Metrowerks::add_reference<typename tuple_element<1, P>::type>::type
	operator()()
	{
		return p_.data1_;
	}
private:
	P& p_;
};

template <class P>
struct get_helper<2, P>
{
	explicit get_helper(P& p) : p_(p) {}
	typename Metrowerks::add_reference<typename tuple_element<2, P>::type>::type
	operator()()
	{
		return p_.data2_;
	}
private:
	P& p_;
};

template <class P>
struct get_helper<3, P>
{
	explicit get_helper(P& p) : p_(p) {}
	typename Metrowerks::add_reference<typename tuple_element<3, P>::type>::type
	operator()()
	{
		return p_.data3_;
	}
private:
	P& p_;
};

template <class P>
struct get_helper<4, P>
{
	explicit get_helper(P& p) : p_(p) {}
	typename Metrowerks::add_reference<typename tuple_element<4, P>::type>::type
	operator()()
	{
		return p_.data4_;
	}
private:
	P& p_;
};

template <class P>
struct get_helper<5, P>
{
	explicit get_helper(P& p) : p_(p) {}
	typename Metrowerks::add_reference<typename tuple_element<5, P>::type>::type
	operator()()
	{
		return p_.data5_;
	}
private:
	P& p_;
};

template <class P>
struct get_helper<6, P>
{
	explicit get_helper(P& p) : p_(p) {}
	typename Metrowerks::add_reference<typename tuple_element<6, P>::type>::type
	operator()()
	{
		return p_.data6_;
	}
private:
	P& p_;
};

template <class P>
struct get_helper<7, P>
{
	explicit get_helper(P& p) : p_(p) {}
	typename Metrowerks::add_reference<typename tuple_element<7, P>::type>::type
	operator()()
	{
		return p_.data7_;
	}
private:
	P& p_;
};

template <class P>
struct get_helper<8, P>
{
	explicit get_helper(P& p) : p_(p) {}
	typename Metrowerks::add_reference<typename tuple_element<8, P>::type>::type
	operator()()
	{
		return p_.data8_;
	}
private:
	P& p_;
};

template <class P>
struct get_helper<9, P>
{
	explicit get_helper(P& p) : p_(p) {}
	typename Metrowerks::add_reference<typename tuple_element<9, P>::type>::type
	operator()()
	{
		return p_.data9_;
	}
private:
	P& p_;
};

template <class T0, class T1>
struct get_helper<0, pair<T0, T1> >
{
	explicit get_helper(pair<T0, T1>& p) : p_(p) {}
	T0& operator()() {return p_.first;}
private:
	pair<T0, T1>& p_;
};

template <class T0, class T1>
struct get_helper<1, pair<T0, T1> >
{
	explicit get_helper(pair<T0, T1>& p) : p_(p) {}
	T1& operator()() {return p_.second;}
private:
	pair<T0, T1>& p_;
};

template <class T, size_t N>
struct get_helper<0, array<T, N> >
{
	explicit get_helper(array<T, N>& p) : p_(p) {}
	T& operator()() {return p_.__data_[0];}
private:
	array<T, N>& p_;

	static const size_t range_error = sizeof(Metrowerks::compile_assert<0 < N>);
};

template <class T, size_t N>
struct get_helper<1, array<T, N> >
{
	explicit get_helper(array<T, N>& p) : p_(p) {}
	T& operator()() {return p_.__data_[1];}
private:
	array<T, N>& p_;

	static const size_t range_error = sizeof(Metrowerks::compile_assert<1 < N>);
};

template <class T, size_t N>
struct get_helper<2, array<T, N> >
{
	explicit get_helper(array<T, N>& p) : p_(p) {}
	T& operator()() {return p_.__data_[2];}
private:
	array<T, N>& p_;

	static const size_t range_error = sizeof(Metrowerks::compile_assert<2 < N>);
};

template <class T, size_t N>
struct get_helper<3, array<T, N> >
{
	explicit get_helper(array<T, N>& p) : p_(p) {}
	T& operator()() {return p_.__data_[3];}
private:
	array<T, N>& p_;

	static const size_t range_error = sizeof(Metrowerks::compile_assert<3 < N>);
};

template <class T, size_t N>
struct get_helper<4, array<T, N> >
{
	explicit get_helper(array<T, N>& p) : p_(p) {}
	T& operator()() {return p_.__data_[4];}
private:
	array<T, N>& p_;

	static const size_t range_error = sizeof(Metrowerks::compile_assert<4 < N>);
};

template <class T, size_t N>
struct get_helper<5, array<T, N> >
{
	explicit get_helper(array<T, N>& p) : p_(p) {}
	T& operator()() {return p_.__data_[5];}
private:
	array<T, N>& p_;

	static const size_t range_error = sizeof(Metrowerks::compile_assert<5 < N>);
};

template <class T, size_t N>
struct get_helper<6, array<T, N> >
{
	explicit get_helper(array<T, N>& p) : p_(p) {}
	T& operator()() {return p_.__data_[6];}
private:
	array<T, N>& p_;

	static const size_t range_error = sizeof(Metrowerks::compile_assert<6 < N>);
};

template <class T, size_t N>
struct get_helper<7, array<T, N> >
{
	explicit get_helper(array<T, N>& p) : p_(p) {}
	T& operator()() {return p_.__data_[7];}
private:
	array<T, N>& p_;

	static const size_t range_error = sizeof(Metrowerks::compile_assert<7 < N>);
};

template <class T, size_t N>
struct get_helper<8, array<T, N> >
{
	explicit get_helper(array<T, N>& p) : p_(p) {}
	T& operator()() {return p_.__data_[8];}
private:
	array<T, N>& p_;

	static const size_t range_error = sizeof(Metrowerks::compile_assert<8 < N>);
};

template <class T, size_t N>
struct get_helper<9, array<T, N> >
{
	explicit get_helper(array<T, N>& p) : p_(p) {}
	T& operator()() {return p_.__data_[9];}
private:
	array<T, N>& p_;

	static const size_t range_error = sizeof(Metrowerks::compile_assert<9 < N>);
};

template <unsigned I, class T, size_t N>
struct get_helper<I, array<T, N> >
{
	explicit get_helper(array<T, N>& p) : p_(p) {}
	T& operator()() {return p_.__data_[I];}
private:
	array<T, N>& p_;

	static const size_t range_error = sizeof(Metrowerks::compile_assert<I < N>);
};

}  // detail

template <unsigned int N, class P>
inline
typename Metrowerks::restrict_to
<
	is_tuple_like<P>::value,
	typename Metrowerks::add_reference<typename tuple_element<N, P>::type>::type
>::type
get(P& p)
{
	return detail::get_helper<N, P>(p)();
}

template <unsigned int N, class P>
inline
typename Metrowerks::restrict_to
<
	is_tuple_like<P>::value,
	typename Metrowerks::add_reference<const typename tuple_element<N, P>::type>::type
>::type
get(const P& p)
{
	return detail::get_helper<N, P>(const_cast<P&>(p))();
}

template <class T, size_t N>
struct tuple_size<array<T, N> >
{
	static const int value = (int)N;
};

// tuple copy constructors

template <class T0>
template <class P>
inline
tuple<T0, nat, nat, nat>::tuple(const P& p,
	                           typename Metrowerks::restrict_to
	                           <
	                               __tuple_convertible<P, tuple>::value
	                           >::type*
	                           )
	: data0_(get<0>(p))
{
}

template <class T0, class T1>
template <class P>
inline
tuple<T0, T1, nat, nat>::tuple(const P& p,
	                         typename Metrowerks::restrict_to
	                         <
	                             __tuple_convertible<P, tuple>::value
	                         >::type*
	                        )
	: data0_(get<0>(p)),
	  data1_(get<1>(p))
{
}

template <class T0, class T1, class T2>
template <class P>
inline
tuple<T0, T1, T2, nat>::tuple(const P& p,
	                         typename Metrowerks::restrict_to
	                         <
	                             __tuple_convertible<P, tuple>::value
	                         >::type*
	                        )
	: data0_(get<0>(p)),
	  data1_(get<1>(p)),
	  data2_(get<2>(p))
{
}

template <class T0, class T1, class T2, class T3>
template <class P>
inline
tuple<T0, T1, T2, T3>::tuple(const P& p,
	                         typename Metrowerks::restrict_to
	                         <
	                             __tuple_convertible<P, tuple>::value
	                         >::type*
	                        )
	: data0_(get<0>(p)),
	  data1_(get<1>(p)),
	  data2_(get<2>(p)),
	  data3_(get<3>(p))
{
}

template <class T0, class T1, class T2, class T3, class T4>
template <class P>
inline
tuple<T0, T1, T2, T3, T4>::tuple(const P& p,
	                         typename Metrowerks::restrict_to
	                         <
	                             __tuple_convertible<P, tuple>::value
	                         >::type*
	                        )
	: data0_(get<0>(p)),
	  data1_(get<1>(p)),
	  data2_(get<2>(p)),
	  data3_(get<3>(p)),
	  data4_(get<4>(p))
{
}

template <class T0, class T1, class T2, class T3, class T4,
          class T5>
template <class P>
inline
tuple<T0, T1, T2, T3, T4, T5>::tuple(const P& p,
	                         typename Metrowerks::restrict_to
	                         <
	                             __tuple_convertible<P, tuple>::value
	                         >::type*
	                        )
	: data0_(get<0>(p)),
	  data1_(get<1>(p)),
	  data2_(get<2>(p)),
	  data3_(get<3>(p)),
	  data4_(get<4>(p)),
	  data5_(get<5>(p))
{
}

template <class T0, class T1, class T2, class T3, class T4,
          class T5, class T6>
template <class P>
inline
tuple<T0, T1, T2, T3, T4, T5, T6>::tuple(const P& p,
	                         typename Metrowerks::restrict_to
	                         <
	                             __tuple_convertible<P, tuple>::value
	                         >::type*
	                        )
	: data0_(get<0>(p)),
	  data1_(get<1>(p)),
	  data2_(get<2>(p)),
	  data3_(get<3>(p)),
	  data4_(get<4>(p)),
	  data5_(get<5>(p)),
	  data6_(get<6>(p))
{
}

template <class T0, class T1, class T2, class T3, class T4,
          class T5, class T6, class T7>
template <class P>
inline
tuple<T0, T1, T2, T3, T4, T5, T6, T7>::tuple(const P& p,
	                         typename Metrowerks::restrict_to
	                         <
	                             __tuple_convertible<P, tuple>::value
	                         >::type*
	                        )
	: data0_(get<0>(p)),
	  data1_(get<1>(p)),
	  data2_(get<2>(p)),
	  data3_(get<3>(p)),
	  data4_(get<4>(p)),
	  data5_(get<5>(p)),
	  data6_(get<6>(p)),
	  data7_(get<7>(p))
{
}

template <class T0, class T1, class T2, class T3, class T4,
          class T5, class T6, class T7, class T8>
template <class P>
inline
tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8>::tuple(const P& p,
	                         typename Metrowerks::restrict_to
	                         <
	                             __tuple_convertible<P, tuple>::value
	                         >::type*
	                        )
	: data0_(get<0>(p)),
	  data1_(get<1>(p)),
	  data2_(get<2>(p)),
	  data3_(get<3>(p)),
	  data4_(get<4>(p)),
	  data5_(get<5>(p)),
	  data6_(get<6>(p)),
	  data7_(get<7>(p)),
	  data8_(get<8>(p))
{
}

template <class T0, class T1, class T2, class T3, class T4,
          class T5, class T6, class T7, class T8, class T9>
template <class P>
inline
tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::tuple(const P& p,
	                         typename Metrowerks::restrict_to
	                         <
	                             __tuple_convertible<P, tuple>::value
	                         >::type*
	                        )
	: data0_(get<0>(p)),
	  data1_(get<1>(p)),
	  data2_(get<2>(p)),
	  data3_(get<3>(p)),
	  data4_(get<4>(p)),
	  data5_(get<5>(p)),
	  data6_(get<6>(p)),
	  data7_(get<7>(p)),
	  data8_(get<8>(p)),
	  data9_(get<9>(p))
{
}

// tuple assign

namespace detail
{

template <class P1,
          class P2,
          unsigned int I = minus1<tuple_size<P1>::value>::value,
          unsigned int S1 = tuple_size<P1>::value,
          unsigned int S2 = tuple_size<P2>::value
         >
struct tuple_assign;

template <class P1, class P2, unsigned int S>
struct tuple_assign<P1, P2, 0, 0, 0>
{
	P1& operator()(P1& p1, const P2&) const
		{return p1;}
};

template <class P1, class P2, unsigned int S>
struct tuple_assign<P1, P2, 0, S, S>
{
	P1& operator()(P1& p1, const P2& p2) const
		{
			get<0>(p1) = get<0>(p2);
			return p1;
		}
};

template <class P1, class P2, unsigned int I, unsigned int S>
struct tuple_assign<P1, P2, I, S, S>
{
	P1& operator()(P1& p1, const P2& p2) const
		{
			tuple_assign<P1, P2, I-1>()(p1, p2);
			get<I>(p1) = get<I>(p2);
			return p1;
		}
};

}  // detail

template <class P1, class P2>
typename Metrowerks::restrict_to
<
	is_tuple_like<P1>::value && is_tuple_like<P2>::value,
	P1&
>::type
assign(P1& x, const P2& y)
{
	detail::tuple_assign<P1, P2>()(x, y);
	return x;
}

// make_tuple

template <class T>
struct mt_map
{
	typedef T type;
};

template <class T>
struct mt_map<reference_wrapper<T> >
{
	typedef T& type;
};

template<class V0>
inline
tuple<typename mt_map<V0>::type>
make_tuple(const V0& v0)
{
	return tuple<typename mt_map<V0>::type>(v0);
}

template<class V0, class V1>
inline
tuple<typename mt_map<V0>::type,
      typename mt_map<V1>::type
     >
make_tuple(const V0& v0, const V1& v1)
{
	return tuple<typename mt_map<V0>::type,
	             typename mt_map<V1>::type
	            >(v0, v1);
}

template<class V0, class V1, class V2>
inline
tuple<typename mt_map<V0>::type,
      typename mt_map<V1>::type,
      typename mt_map<V2>::type
     >
make_tuple(const V0& v0, const V1& v1, const V2& v2)
{
	return tuple<typename mt_map<V0>::type,
	             typename mt_map<V1>::type,
	             typename mt_map<V2>::type
	            >(v0, v1, v2);
}

template<class V0, class V1, class V2, class V3>
inline
tuple<typename mt_map<V0>::type,
      typename mt_map<V1>::type,
      typename mt_map<V2>::type,
      typename mt_map<V3>::type
     >
make_tuple(const V0& v0, const V1& v1, const V2& v2, const V3& v3)
{
	return tuple<typename mt_map<V0>::type,
	             typename mt_map<V1>::type,
	             typename mt_map<V2>::type,
	             typename mt_map<V3>::type
	            >(v0, v1, v2, v3);
}

template<class V0, class V1, class V2, class V3, class V4>
inline
tuple<typename mt_map<V0>::type,
      typename mt_map<V1>::type,
      typename mt_map<V2>::type,
      typename mt_map<V3>::type,
      typename mt_map<V4>::type
     >
make_tuple(const V0& v0, const V1& v1, const V2& v2, const V3& v3, const V4& v4)
{
	return tuple<typename mt_map<V0>::type,
	             typename mt_map<V1>::type,
	             typename mt_map<V2>::type,
	             typename mt_map<V3>::type,
	             typename mt_map<V4>::type
	            >(v0, v1, v2, v3, v4);
}

template<class V0, class V1, class V2, class V3, class V4,
         class V5>
inline
tuple<typename mt_map<V0>::type,
      typename mt_map<V1>::type,
      typename mt_map<V2>::type,
      typename mt_map<V3>::type,
      typename mt_map<V4>::type,
      typename mt_map<V5>::type
     >
make_tuple(const V0& v0, const V1& v1, const V2& v2, const V3& v3, const V4& v4,
           const V5& v5)
{
	return tuple<typename mt_map<V0>::type,
	             typename mt_map<V1>::type,
	             typename mt_map<V2>::type,
	             typename mt_map<V3>::type,
	             typename mt_map<V4>::type,
	             typename mt_map<V5>::type
	            >(v0, v1, v2, v3, v4, v5);
}

template<class V0, class V1, class V2, class V3, class V4,
         class V5, class V6>
inline
tuple<typename mt_map<V0>::type,
      typename mt_map<V1>::type,
      typename mt_map<V2>::type,
      typename mt_map<V3>::type,
      typename mt_map<V4>::type,
      typename mt_map<V5>::type,
      typename mt_map<V6>::type
     >
make_tuple(const V0& v0, const V1& v1, const V2& v2, const V3& v3, const V4& v4,
           const V5& v5, const V6& v6)
{
	return tuple<typename mt_map<V0>::type,
	             typename mt_map<V1>::type,
	             typename mt_map<V2>::type,
	             typename mt_map<V3>::type,
	             typename mt_map<V4>::type,
	             typename mt_map<V5>::type,
	             typename mt_map<V6>::type
	            >(v0, v1, v2, v3, v4, v5, v6);
}

template<class V0, class V1, class V2, class V3, class V4,
         class V5, class V6, class V7>
inline
tuple<typename mt_map<V0>::type,
      typename mt_map<V1>::type,
      typename mt_map<V2>::type,
      typename mt_map<V3>::type,
      typename mt_map<V4>::type,
      typename mt_map<V5>::type,
      typename mt_map<V6>::type,
      typename mt_map<V7>::type
     >
make_tuple(const V0& v0, const V1& v1, const V2& v2, const V3& v3, const V4& v4,
           const V5& v5, const V6& v6, const V7& v7)
{
	return tuple<typename mt_map<V0>::type,
	             typename mt_map<V1>::type,
	             typename mt_map<V2>::type,
	             typename mt_map<V3>::type,
	             typename mt_map<V4>::type,
	             typename mt_map<V5>::type,
	             typename mt_map<V6>::type,
	             typename mt_map<V7>::type
	            >(v0, v1, v2, v3, v4, v5, v6, v7);
}

template<class V0, class V1, class V2, class V3, class V4,
         class V5, class V6, class V7, class V8>
inline
tuple<typename mt_map<V0>::type,
      typename mt_map<V1>::type,
      typename mt_map<V2>::type,
      typename mt_map<V3>::type,
      typename mt_map<V4>::type,
      typename mt_map<V5>::type,
      typename mt_map<V6>::type,
      typename mt_map<V7>::type,
      typename mt_map<V8>::type
     >
make_tuple(const V0& v0, const V1& v1, const V2& v2, const V3& v3, const V4& v4,
           const V5& v5, const V6& v6, const V7& v7, const V8& v8)
{
	return tuple<typename mt_map<V0>::type,
	             typename mt_map<V1>::type,
	             typename mt_map<V2>::type,
	             typename mt_map<V3>::type,
	             typename mt_map<V4>::type,
	             typename mt_map<V5>::type,
	             typename mt_map<V6>::type,
	             typename mt_map<V7>::type,
	             typename mt_map<V8>::type
	            >(v0, v1, v2, v3, v4, v5, v6, v7, v8);
}

template<class V0, class V1, class V2, class V3, class V4,
         class V5, class V6, class V7, class V8, class V9>
inline
tuple<typename mt_map<V0>::type,
      typename mt_map<V1>::type,
      typename mt_map<V2>::type,
      typename mt_map<V3>::type,
      typename mt_map<V4>::type,
      typename mt_map<V5>::type,
      typename mt_map<V6>::type,
      typename mt_map<V7>::type,
      typename mt_map<V8>::type,
      typename mt_map<V9>::type
     >
make_tuple(const V0& v0, const V1& v1, const V2& v2, const V3& v3, const V4& v4,
           const V5& v5, const V6& v6, const V7& v7, const V8& v8, const V9& v9)
{
	return tuple<typename mt_map<V0>::type,
	             typename mt_map<V1>::type,
	             typename mt_map<V2>::type,
	             typename mt_map<V3>::type,
	             typename mt_map<V4>::type,
	             typename mt_map<V5>::type,
	             typename mt_map<V6>::type,
	             typename mt_map<V7>::type,
	             typename mt_map<V8>::type,
	             typename mt_map<V9>::type
	            >(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
}

// tie

template<class T0>
inline
tuple<T0&>
tie(T0& t0)
{
	return tuple<T0&>(t0);
}

template<class T0, class T1>
inline
tuple<T0&, T1&>
tie(T0& t0, T1& t1)
{
	return tuple<T0&, T1&>(t0, t1);
}

template<class T0, class T1, class T2>
inline
tuple<T0&, T1&, T2&>
tie(T0& t0, T1& t1, T2& t2)
{
	return tuple<T0&, T1&, T2&>(t0, t1, t2);
}

template<class T0, class T1, class T2, class T3>
inline
tuple<T0&, T1&, T2&, T3&>
tie(T0& t0, T1& t1, T2& t2, T3& t3)
{
	return tuple<T0&, T1&, T2&, T3&>(t0, t1, t2, t3);
}

template<class T0, class T1, class T2, class T3, class T4>
inline
tuple<T0&, T1&, T2&, T3&, T4&>
tie(T0& t0, T1& t1, T2& t2, T3& t3, T4& t4)
{
	return tuple<T0&, T1&, T2&, T3&, T4&>(t0, t1, t2, t3, t4);
}

template<class T0, class T1, class T2, class T3, class T4,
         class T5>
inline
tuple<T0&, T1&, T2&, T3&, T4&, T5&>
tie(T0& t0, T1& t1, T2& t2, T3& t3, T4& t4, T5& t5)
{
	return tuple<T0&, T1&, T2&, T3&, T4&, T5&>
	            (t0, t1, t2, t3, t4, t5);
}

template<class T0, class T1, class T2, class T3, class T4,
         class T5, class T6>
inline
tuple<T0&, T1&, T2&, T3&, T4&, T5&, T6&>
tie(T0& t0, T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6)
{
	return tuple<T0&, T1&, T2&, T3&, T4&, T5&, T6&>
	            (t0, t1, t2, t3, t4, t5, t6);
}

template<class T0, class T1, class T2, class T3, class T4,
         class T5, class T6, class T7>
inline
tuple<T0&, T1&, T2&, T3&, T4&, T5&, T6&, T7&>
tie(T0& t0, T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7)
{
	return tuple<T0&, T1&, T2&, T3&, T4&, T5&, T6&, T7&>
	            (t0, t1, t2, t3, t4, t5, t6, t7);
}

template<class T0, class T1, class T2, class T3, class T4,
         class T5, class T6, class T7, class T8>
inline
tuple<T0&, T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&>
tie(T0& t0, T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8)
{
	return tuple<T0&, T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&>
	            (t0, t1, t2, t3, t4, t5, t6, t7, t8);
}

template<class T0, class T1, class T2, class T3, class T4,
         class T5, class T6, class T7, class T8, class T9>
inline
tuple<T0&, T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&, T9&>
tie(T0& t0, T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, T9& t9)
{
	return tuple<T0&, T1&, T2&, T3&, T4&, T5&, T6&, T7&, T8&, T9&>
	            (t0, t1, t2, t3, t4, t5, t6, t7, t8, t9);
}

struct swallow_assign
{
	template <class T>
	swallow_assign& operator=(const T&) { return *this; }
};

namespace {swallow_assign ignore;}

// operator ==

namespace detail
{

template <class P1,
          class P2,
          unsigned int I = 0,
          bool S1 = I < tuple_size<P1>::value,
          bool S2 = I < tuple_size<P2>::value
         >
struct tuple_equal
{
	bool operator()(const P1&, const P2&) const
		{return true;}
};

template <class P1, class P2, unsigned int I>
struct tuple_equal<P1, P2, I, true, true>
{
	bool operator()(const P1& p1, const P2& p2) const
		{return get<I>(p1) == get<I>(p2) && tuple_equal<P1, P2, I+1>()(p1, p2);}
};

template <class P1, class P2, unsigned int I>
struct tuple_equal<P1, P2, I, true, false>
{
	bool operator()(const P1&, const P2&) const
		{return false;}
};

template <class P1, class P2, unsigned int I>
struct tuple_equal<P1, P2, I, false, true>
{
	bool operator()(const P1&, const P2&) const
		{return false;}
};

}  // detail

template <class P1, class P2>
inline
typename Metrowerks::restrict_to
<
	is_tuple_like<P1>::value && is_tuple_like<P2>::value,
	bool
>::type
operator==(const P1& x, const P2& y)
{
	return detail::tuple_equal<P1, P2>()(x, y);
}

// operator !=

template <class P1, class P2>
inline
typename Metrowerks::restrict_to
<
	is_tuple_like<P1>::value && is_tuple_like<P2>::value,
	bool
>::type
operator!=(const P1& x, const P2& y)
{
	return !(x == y);
}

// operator <

namespace detail
{

template <class P1,
          class P2,
          unsigned int I = minus1<tuple_size<P1>::value < tuple_size<P2>::value ? tuple_size<P1>::value : tuple_size<P2>::value>::value,
          unsigned int S = tuple_size<P1>::value < tuple_size<P2>::value ? tuple_size<P1>::value : tuple_size<P2>::value
         >
struct tuple_compare
{
	int operator()(const P1& p1, const P2& p2) const
		{
			const int i = tuple_compare<P1, P2, I-1>()(p1, p2);
			return i != 0 ? i : (get<I>(p1) < get<I>(p2) ? -1 : (get<I>(p2) < get<I>(p1) ? 1 : 0));
		}
};

template <class P1, class P2>
struct tuple_compare<P1, P2, 0, 0>
{
	int operator()(const P1&, const P2&) const
		{return 0;}
};

template <class P1, class P2, unsigned int S>
struct tuple_compare<P1, P2, 0, S>
{
	int operator()(const P1& p1, const P2& p2) const
		{return get<0>(p1) < get<0>(p2) ? -1 : (get<0>(p2) < get<0>(p1) ? 1 : 0);}
};

}  // detail

template <class P1, class P2>
inline
typename Metrowerks::restrict_to
<
	is_tuple_like<P1>::value && is_tuple_like<P2>::value,
	bool
>::type
operator<(const P1& x, const P2& y)
{
	const int i = detail::tuple_compare<P1, P2>()(x, y);
	return i != 0 ? i == -1 : tuple_size<P1>::value < tuple_size<P2>::value;
}

// other relationals

template <class P1, class P2>
inline
typename Metrowerks::restrict_to
<
	is_tuple_like<P1>::value && is_tuple_like<P2>::value,
	bool
>::type
operator>(const P1& x, const P2& y)
{
	return y < x;
}

template <class P1, class P2>
inline
typename Metrowerks::restrict_to
<
	is_tuple_like<P1>::value && is_tuple_like<P2>::value,
	bool
>::type
operator<=(const P1& x, const P2& y)
{
	return !(y < x);
}

template <class P1, class P2>
inline
typename Metrowerks::restrict_to
<
	is_tuple_like<P1>::value && is_tuple_like<P2>::value,
	bool
>::type
operator>=(const P1& x, const P2& y)
{
	return !(x < y);
}

// swap

namespace detail
{

template <class P,
          unsigned int I = minus1<tuple_size<P>::value>::value,
          unsigned int S = tuple_size<P>::value
         >
struct tuple_swap
{
	void operator()(P& x, P& y) const
	{
		tuple_swap<P, I-1>()(x, y);
		using std::swap;
		swap(get<I>(x), get<I>(y));
	}
};

template <class P>
struct tuple_swap<P, 0, 0>
{
	void operator()(P&, P&) const
	{
	}
};

template <class P, unsigned int S>
struct tuple_swap<P, 0, S>
{
	void operator()(P& x, P& y) const
	{
		using std::swap;
		swap(get<0>(x), get<0>(y));
	}
};

}

template <class T0, class T1, class T2, class T3, class T4,
          class T5, class T6, class T7, class T8, class T9>
inline
void
swap(tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& x,
     tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>& y)
{
	detail::tuple_swap<tuple<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >()(x, y);
}

_MSL_END_TR1_NAMESPACE

#ifndef _MSL_NO_CPP_NAMESPACE
	namespace std {
#endif

#if !defined(__MWERKS__) || (defined(__MWERKS__) && __MWERKS__ >= 0x3200)

template <class T1, class T2>
template <class P>
inline
pair<T1, T2>::pair(const P& p,
                       typename Metrowerks::restrict_to
                       <
                           _TR1::__tuple_convertible<P, pair>::value
                       >::type*
                   )
	:	first (_TR1::get<0>(p)),
		second(_TR1::get<1>(p))
{
}

#endif

template <class T1, class T2>
template <class P>
inline
pair<T1, T2>&
pair<T1, T2>::operator=(const P& p)
{
	first = _TR1::get<0>(p);
	second = _TR1::get<1>(p);
	return *this;
}

#ifndef _MSL_NO_CPP_NAMESPACE
	} // std
#endif

#ifdef _MSL_FORCE_ENUMS_ALWAYS_INT
	#pragma enumsalwaysint reset
#endif

#ifdef _MSL_FORCE_ENABLE_BOOL_SUPPORT
	#pragma bool reset
#endif

#ifdef __MWERKS__
#pragma options align=reset
#endif

#endif // RC_INVOKED

#if (defined(_ISTREAM) || defined(_OSTREAM)) && !defined(_TUPLEIO)
	#include <tupleio>
#endif

#endif // _TUPLE

// hh 030303 Created
