/*=============================================================================
    Phoenix v1.2
    Copyright (c) 2001-2002 Joel de Guzman

    Use, modification and distribution is 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)
==============================================================================*/
#ifndef PHOENIX_TUPLES_HPP
#define PHOENIX_TUPLES_HPP

///////////////////////////////////////////////////////////////////////////////
//
//  Phoenix predefined maximum limit. This limit defines the maximum
//  number of elements a tuple can hold. This number defaults to 3. The
//  actual maximum is rounded up in multiples of 3. Thus, if this value
//  is 4, the actual limit is 6. The ultimate maximum limit in this
//  implementation is 15.
//
///////////////////////////////////////////////////////////////////////////////
#ifndef PHOENIX_LIMIT
#define PHOENIX_LIMIT 3
#endif

#if defined(__BORLANDC__) && (__BORLANDC__ <= 0x561)
namespace phoenix { namespace borland_only
{
    namespace ftors
    {
        //  We define these dummy template functions. Borland complains when
        //  a template class has the same name as a template function,
        //  regardless if they are in different namespaces.

        template <typename T> void if_(T) {}
        template <typename T> void for_(T) {}
        template <typename T> void while_(T) {}
        template <typename T> void do_(T) {}
    }

    namespace tmpls
    {
        //  We define these dummy template functions. Borland complains when
        //  a template class has the same name as a template function,
        //  regardless if they are in different namespaces.

        template <typename T> struct if_ {};
        template <typename T> struct for_ {};
        template <typename T> struct while_ {};
        template <typename T> struct do_ {};
    }

}} // namespace phoenix::borland_only
#endif

///////////////////////////////////////////////////////////////////////////////
#include <boost/static_assert.hpp>
#include <boost/call_traits.hpp>
#include <boost/type_traits/remove_reference.hpp>

///////////////////////////////////////////////////////////////////////////////
namespace phoenix {

///////////////////////////////////////////////////////////////////////////////
//
//  tuple
//
//      Tuples hold heterogeneous types up to a predefined maximum. Only
//      the most basic functionality needed is provided. Unlike other
//      recursive list-like tuple implementations, this tuple
//      implementation uses simple structs similar to std::pair with
//      specialization for 0 to N tuple elements.
//
//          1)  Construction
//              Here are examples on how to construct tuples:
//
//                  typedef tuple<int, char> t1_t;
//                  typedef tuple<int, std::string, double> t2_t;
//
//                  // this tuple has an int and char members
//                  t1_t t1(3, 'c');
//
//                  // this tuple has an int, std::string and double members
//                  t2_t t2(3, "hello", 3.14);
//
//              Tuples can also be constructed from other tuples. The
//              source and destination tuples need not have exactly the
//              same element types. The only requirement is that the
//              source tuple have the same number of elements as the
//              destination and that each element slot in the
//              destination can be copy constructed from the source
//              element. For example:
//
//                  tuple<double, double> t3(t1); // OK. Compatible tuples
//                  tuple<double, double> t4(t2); // Error! Incompatible tuples
//
//          2)  Member access
//                  A member in a tuple can be accessed using the
//                  tuple's [] operator by specifying the Nth
//                  tuple_index. Here are some examples:
//
//                      tuple_index<0> ix0; // 0th index == 1st item
//                      tuple_index<1> ix1; // 1st index == 2nd item
//                      tuple_index<2> ix2; // 2nd index == 3rd item
//
//                      t1[ix0] = 33;  // sets the int member of the tuple t1
//                      t2[ix2] = 6e6; // sets the double member of the tuple t2
//                      t1[ix1] = 'a'; // sets the char member of the tuple t1
//
//                  There are some predefined names are provided in sub-
//                  namespace tuple_index_names:
//
//                      tuple_index<0> _1;
//                      tuple_index<1> _2;
//                      ...
//                      tuple_index<N> _N;
//
//                  These indexes may be used by 'using' namespace
//                  phoenix::tuple_index_names.
//
//                  Access to out of bound indexes returns a nil_t value.
//
//          3)  Member type inquiry
//                  The type of an individual member can be queried.
//                  Example:
//
//                      tuple_element<1, t2_t>::type
//
//                  Refers to the type of the second member (note zero based,
//                  thus 0 = 1st item, 1 = 2nd item) of the tuple.
//
//                  Aside from tuple_element<N, T>::type, there are two
//                  more types that tuple_element provides: rtype and
//                  crtype. While 'type' is the plain underlying type,
//                  'rtype' is the reference type, or type& and 'crtype'
//                  is the constant reference type or type const&. The
//                  latter two are provided to make it easy for the
//                  client in dealing with the possibility of reference
//                  to reference when type is already a reference, which
//                  is illegal in C++.
//
//                  Access to out of bound indexes returns a nil_t type.
//
//          4)  Tuple length
//                  The number of elements in a tuple can be queried.
//                  Example:
//
//                      int n = t1.length;
//
//                  gets the number of elements in tuple t1.
//
//                  length is a static constant. Thus, TupleT::length
//                  also works. Example:
//
//                      int n = t1_t::length;
//
///////////////////////////////////////////////////////////////////////////////
struct nil_t {};
using boost::remove_reference;
using boost::call_traits;

//////////////////////////////////
namespace impl {

    template <typename T>
    struct access {

        typedef const T& ctype;
        typedef T& type;
    };

    template <typename T>
    struct access<T&> {

        typedef T& ctype;
        typedef T& type;
    };
}

///////////////////////////////////////////////////////////////////////////////
//
//  tuple_element
//
//      A query class that gets the Nth element inside a tuple.
//      Examples:
//
//          tuple_element<1, tuple<int, char, void*> >::type    //  plain
//          tuple_element<1, tuple<int, char, void*> >::rtype   //  ref
//          tuple_element<1, tuple<int, char, void*> >::crtype  //  const ref
//
//      Has type char which is the 2nd type in the tuple
//      (note zero based, thus 0 = 1st item, 1 = 2nd item).
//
//          Given a tuple object, the static function tuple_element<N,
//          TupleT>::get(tuple) gets the Nth element in the tuple. The
//          tuple class' tuple::operator[] uses this to get its Nth
//          element.
//
///////////////////////////////////////////////////////////////////////////////
template <int N, typename TupleT>
struct tuple_element
{
    typedef nil_t type;
    typedef nil_t& rtype;
    typedef nil_t const& crtype;

    static nil_t    get(TupleT const& t)    { return nil_t(); }
};

//////////////////////////////////
template <typename TupleT>
struct tuple_element<0, TupleT>
{
    typedef typename TupleT::a_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.a; }
    static crtype   get(TupleT const& t)    { return t.a; }
};

//////////////////////////////////
template <typename TupleT>
struct tuple_element<1, TupleT>
{
    typedef typename TupleT::b_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.b; }
    static crtype   get(TupleT const& t)    { return t.b; }
};

//////////////////////////////////
template <typename TupleT>
struct tuple_element<2, TupleT>
{
    typedef typename TupleT::c_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.c; }
    static crtype   get(TupleT const& t)    { return t.c; }
};

#if PHOENIX_LIMIT > 3
//////////////////////////////////
template <typename TupleT>
struct tuple_element<3, TupleT>
{
    typedef typename TupleT::d_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.d; }
    static crtype   get(TupleT const& t)    { return t.d; }
};

//////////////////////////////////
template <typename TupleT>
struct tuple_element<4, TupleT>
{
    typedef typename TupleT::e_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.e; }
    static crtype   get(TupleT const& t)    { return t.e; }
};

//////////////////////////////////
template <typename TupleT>
struct tuple_element<5, TupleT>
{
    typedef typename TupleT::f_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.f; }
    static crtype   get(TupleT const& t)    { return t.f; }
};

#if PHOENIX_LIMIT > 6
//////////////////////////////////
template <typename TupleT>
struct tuple_element<6, TupleT>
{
    typedef typename TupleT::g_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.g; }
    static crtype   get(TupleT const& t)    { return t.g; }
};

//////////////////////////////////
template <typename TupleT>
struct tuple_element<7, TupleT>
{
    typedef typename TupleT::h_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.h; }
    static crtype   get(TupleT const& t)    { return t.h; }
};

//////////////////////////////////
template <typename TupleT>
struct tuple_element<8, TupleT>
{
    typedef typename TupleT::i_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.i; }
    static crtype   get(TupleT const& t)    { return t.i; }
};

#if PHOENIX_LIMIT > 9
//////////////////////////////////
template <typename TupleT>
struct tuple_element<9, TupleT>
{
    typedef typename TupleT::j_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.j; }
    static crtype   get(TupleT const& t)    { return t.j; }
};

//////////////////////////////////
template <typename TupleT>
struct tuple_element<10, TupleT>
{
    typedef typename TupleT::k_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.k; }
    static crtype   get(TupleT const& t)    { return t.k; }
};

//////////////////////////////////
template <typename TupleT>
struct tuple_element<11, TupleT>
{
    typedef typename TupleT::l_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.l; }
    static crtype   get(TupleT const& t)    { return t.l; }
};

#if PHOENIX_LIMIT > 12
//////////////////////////////////
template <typename TupleT>
struct tuple_element<12, TupleT>
{
    typedef typename TupleT::m_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.m; }
    static crtype   get(TupleT const& t)    { return t.m; }
};

//////////////////////////////////
template <typename TupleT>
struct tuple_element<13, TupleT>
{
    typedef typename TupleT::n_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.n; }
    static crtype   get(TupleT const& t)    { return t.n; }
};

//////////////////////////////////
template <typename TupleT>
struct tuple_element<14, TupleT>
{
    typedef typename TupleT::o_type type;
    typedef typename impl::access<type>::type rtype;
    typedef typename impl::access<type>::ctype crtype;

    static rtype    get(TupleT& t)          { return t.o; }
    static crtype   get(TupleT const& t)    { return t.o; }
};

#endif
#endif
#endif
#endif

///////////////////////////////////////////////////////////////////////////////
//
//  tuple forward declaration.
//
///////////////////////////////////////////////////////////////////////////////
template <
        typename A = nil_t
    ,   typename B = nil_t
    ,   typename C = nil_t

#if PHOENIX_LIMIT > 3
    ,   typename D = nil_t
    ,   typename E = nil_t
    ,   typename F = nil_t

#if PHOENIX_LIMIT > 6
    ,   typename G = nil_t
    ,   typename H = nil_t
    ,   typename I = nil_t

#if PHOENIX_LIMIT > 9
    ,   typename J = nil_t
    ,   typename K = nil_t
    ,   typename L = nil_t

#if PHOENIX_LIMIT > 12
    ,   typename M = nil_t
    ,   typename N = nil_t
    ,   typename O = nil_t

#endif
#endif
#endif
#endif

    ,   typename NU = nil_t  // Not used
>
struct tuple;

///////////////////////////////////////////////////////////////////////////////
//
//  tuple_index
//
//      This class wraps an integer in a type to be used for indexing
//      the Nth element in a tuple. See tuple operator[]. Some
//      predefined names are provided in sub-namespace
//      tuple_index_names.
//
///////////////////////////////////////////////////////////////////////////////
template <int N>
struct tuple_index {};

//////////////////////////////////
namespace tuple_index_names {

    tuple_index<0> const _1 = tuple_index<0>();
    tuple_index<1> const _2 = tuple_index<1>();
    tuple_index<2> const _3 = tuple_index<2>();

#if PHOENIX_LIMIT > 3
    tuple_index<3> const _4 = tuple_index<3>();
    tuple_index<4> const _5 = tuple_index<4>();
    tuple_index<5> const _6 = tuple_index<5>();

#if PHOENIX_LIMIT > 6
    tuple_index<6> const _7 = tuple_index<6>();
    tuple_index<7> const _8 = tuple_index<7>();
    tuple_index<8> const _9 = tuple_index<8>();

#if PHOENIX_LIMIT > 9
    tuple_index<9> const _10 = tuple_index<9>();
    tuple_index<10> const _11 = tuple_index<10>();
    tuple_index<11> const _12 = tuple_index<11>();

#if PHOENIX_LIMIT > 12
    tuple_index<12> const _13 = tuple_index<12>();
    tuple_index<13> const _14 = tuple_index<13>();
    tuple_index<14> const _15 = tuple_index<14>();

#endif
#endif
#endif
#endif
}

///////////////////////////////////////////////////////////////////////////////
//
//  tuple_common class
//
///////////////////////////////////////////////////////////////////////////////
template <typename DerivedT>
struct tuple_base {

    typedef nil_t   a_type;
    typedef nil_t   b_type;
    typedef nil_t   c_type;

#if PHOENIX_LIMIT > 3
    typedef nil_t   d_type;
    typedef nil_t   e_type;
    typedef nil_t   f_type;

#if PHOENIX_LIMIT > 6
    typedef nil_t   g_type;
    typedef nil_t   h_type;
    typedef nil_t   i_type;

#if PHOENIX_LIMIT > 9
    typedef nil_t   j_type;
    typedef nil_t   k_type;
    typedef nil_t   l_type;

#if PHOENIX_LIMIT > 12
    typedef nil_t   m_type;
    typedef nil_t   n_type;
    typedef nil_t   o_type;

#endif
#endif
#endif
#endif

    template <int N>
    typename tuple_element<N, DerivedT>::crtype
    operator[](tuple_index<N>) const
    {
        return tuple_element<N, DerivedT>
            ::get(*static_cast<DerivedT const*>(this));
    }

    template <int N>
    typename tuple_element<N, DerivedT>::rtype
    operator[](tuple_index<N>)
    {
        return tuple_element<N, DerivedT>
            ::get(*static_cast<DerivedT*>(this));
    }
};

///////////////////////////////////////////////////////////////////////////////
//
//  tuple <0 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <>
struct tuple<>
:   public tuple_base<tuple<> > {

    BOOST_STATIC_CONSTANT(int, length = 0);
};

///////////////////////////////////////////////////////////////////////////////
//
//  tuple <1 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <typename A>
struct tuple<A, nil_t, nil_t,
#if PHOENIX_LIMIT > 3
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 6
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 9
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 12
    nil_t, nil_t, nil_t,
#endif
#endif
#endif
#endif
    nil_t   //  Unused
>
:   public tuple_base<tuple<A> > {

    BOOST_STATIC_CONSTANT(int, length = 1);
    typedef A a_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_
    ):  a(a_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a;
};

///////////////////////////////////////////////////////////////////////////////
//
//  tuple <2 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <typename A, typename B>
struct tuple<A, B, nil_t,
#if PHOENIX_LIMIT > 3
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 6
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 9
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 12
    nil_t, nil_t, nil_t,
#endif
#endif
#endif
#endif
    nil_t   //  Unused
>
:   public tuple_base<tuple<A, B> > {

    BOOST_STATIC_CONSTANT(int, length = 2);
    typedef A a_type; typedef B b_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_
    ):  a(a_), b(b_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b;
};

///////////////////////////////////////////////////////////////////////////////
//
//  tuple <3 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <typename A, typename B, typename C>
struct tuple<A, B, C,
#if PHOENIX_LIMIT > 3
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 6
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 9
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 12
    nil_t, nil_t, nil_t,
#endif
#endif
#endif
#endif
    nil_t   //  Unused
>
:   public tuple_base<tuple<A, B, C> > {

    BOOST_STATIC_CONSTANT(int, length = 3);
    typedef A a_type; typedef B b_type;
    typedef C c_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_
    ):  a(a_), b(b_), c(c_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c;
};

#if PHOENIX_LIMIT > 3
///////////////////////////////////////////////////////////////////////////////
//
//  tuple <4 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <typename A, typename B, typename C, typename D>
struct tuple<A, B, C, D, nil_t, nil_t,
#if PHOENIX_LIMIT > 6
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 9
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 12
    nil_t, nil_t, nil_t,
#endif
#endif
#endif
    nil_t   //  Unused
>
:   public tuple_base<tuple<A, B, C, D> > {

    BOOST_STATIC_CONSTANT(int, length = 4);
    typedef A a_type; typedef B b_type;
    typedef C c_type; typedef D d_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_,
        typename call_traits<D>::param_type d_
    ):  a(a_), b(b_), c(c_), d(d_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()]), d(init[tuple_index<3>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c; D d;
};

///////////////////////////////////////////////////////////////////////////////
//
//  tuple <5 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <typename A, typename B, typename C, typename D, typename E>
struct tuple<A, B, C, D, E, nil_t,
#if PHOENIX_LIMIT > 6
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 9
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 12
    nil_t, nil_t, nil_t,
#endif
#endif
#endif
    nil_t   //  Unused
>
:   public tuple_base<tuple<A, B, C, D, E> > {

    BOOST_STATIC_CONSTANT(int, length = 5);
    typedef A a_type; typedef B b_type;
    typedef C c_type; typedef D d_type;
    typedef E e_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_,
        typename call_traits<D>::param_type d_,
        typename call_traits<E>::param_type e_
    ):  a(a_), b(b_), c(c_), d(d_), e(e_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()]), d(init[tuple_index<3>()]),
        e(init[tuple_index<4>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c; D d; E e;
};

///////////////////////////////////////////////////////////////////////////////
//
//  tuple <6 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <
    typename A, typename B, typename C, typename D, typename E,
    typename F>
struct tuple<A, B, C, D, E, F,
#if PHOENIX_LIMIT > 6
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 9
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 12
    nil_t, nil_t, nil_t,
#endif
#endif
#endif
    nil_t   //  Unused
>
:   public tuple_base<tuple<A, B, C, D, E, F> > {

    BOOST_STATIC_CONSTANT(int, length = 6);
    typedef A a_type; typedef B b_type;
    typedef C c_type; typedef D d_type;
    typedef E e_type; typedef F f_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_,
        typename call_traits<D>::param_type d_,
        typename call_traits<E>::param_type e_,
        typename call_traits<F>::param_type f_
    ):  a(a_), b(b_), c(c_), d(d_), e(e_),
        f(f_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()]), d(init[tuple_index<3>()]),
        e(init[tuple_index<4>()]), f(init[tuple_index<5>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c; D d; E e;
    F f;
};

#if PHOENIX_LIMIT > 6
///////////////////////////////////////////////////////////////////////////////
//
//  tuple <7 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <
    typename A, typename B, typename C, typename D, typename E,
    typename F, typename G>
struct tuple<A, B, C, D, E, F, G, nil_t, nil_t,
#if PHOENIX_LIMIT > 9
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 12
    nil_t, nil_t, nil_t,
#endif
#endif
    nil_t   //  Unused
>
:   public tuple_base<tuple<A, B, C, D, E, F, G> > {

    BOOST_STATIC_CONSTANT(int, length = 7);
    typedef A a_type; typedef B b_type;
    typedef C c_type; typedef D d_type;
    typedef E e_type; typedef F f_type;
    typedef G g_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_,
        typename call_traits<D>::param_type d_,
        typename call_traits<E>::param_type e_,
        typename call_traits<F>::param_type f_,
        typename call_traits<G>::param_type g_
    ):  a(a_), b(b_), c(c_), d(d_), e(e_),
        f(f_), g(g_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()]), d(init[tuple_index<3>()]),
        e(init[tuple_index<4>()]), f(init[tuple_index<5>()]),
        g(init[tuple_index<6>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c; D d; E e;
    F f; G g;
};

///////////////////////////////////////////////////////////////////////////////
//
//  tuple <8 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <
    typename A, typename B, typename C, typename D, typename E,
    typename F, typename G, typename H>
struct tuple<A, B, C, D, E, F, G, H, nil_t,
#if PHOENIX_LIMIT > 9
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 12
    nil_t, nil_t, nil_t,
#endif
#endif
    nil_t   //  Unused
>
:   public tuple_base<tuple<A, B, C, D, E, F, G, H> > {

    BOOST_STATIC_CONSTANT(int, length = 8);
    typedef A a_type; typedef B b_type;
    typedef C c_type; typedef D d_type;
    typedef E e_type; typedef F f_type;
    typedef G g_type; typedef H h_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_,
        typename call_traits<D>::param_type d_,
        typename call_traits<E>::param_type e_,
        typename call_traits<F>::param_type f_,
        typename call_traits<G>::param_type g_,
        typename call_traits<H>::param_type h_
    ):  a(a_), b(b_), c(c_), d(d_), e(e_),
        f(f_), g(g_), h(h_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()]), d(init[tuple_index<3>()]),
        e(init[tuple_index<4>()]), f(init[tuple_index<5>()]),
        g(init[tuple_index<6>()]), h(init[tuple_index<7>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c; D d; E e;
    F f; G g; H h;
};

///////////////////////////////////////////////////////////////////////////////
//
//  tuple <9 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <
    typename A, typename B, typename C, typename D, typename E,
    typename F, typename G, typename H, typename I>
struct tuple<A, B, C, D, E, F, G, H, I,
#if PHOENIX_LIMIT > 9
    nil_t, nil_t, nil_t,
#if PHOENIX_LIMIT > 12
    nil_t, nil_t, nil_t,
#endif
#endif
    nil_t   //  Unused
>
:   public tuple_base<tuple<A, B, C, D, E, F, G, H, I> > {

    BOOST_STATIC_CONSTANT(int, length = 9);
    typedef A a_type; typedef B b_type;
    typedef C c_type; typedef D d_type;
    typedef E e_type; typedef F f_type;
    typedef G g_type; typedef H h_type;
    typedef I i_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_,
        typename call_traits<D>::param_type d_,
        typename call_traits<E>::param_type e_,
        typename call_traits<F>::param_type f_,
        typename call_traits<G>::param_type g_,
        typename call_traits<H>::param_type h_,
        typename call_traits<I>::param_type i_
    ):  a(a_), b(b_), c(c_), d(d_), e(e_),
        f(f_), g(g_), h(h_), i(i_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()]), d(init[tuple_index<3>()]),
        e(init[tuple_index<4>()]), f(init[tuple_index<5>()]),
        g(init[tuple_index<6>()]), h(init[tuple_index<7>()]),
        i(init[tuple_index<8>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c; D d; E e;
    F f; G g; H h; I i;
};

#if PHOENIX_LIMIT > 9
///////////////////////////////////////////////////////////////////////////////
//
//  tuple <10 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <
    typename A, typename B, typename C, typename D, typename E,
    typename F, typename G, typename H, typename I, typename J>
struct tuple<A, B, C, D, E, F, G, H, I, J, nil_t, nil_t,
#if PHOENIX_LIMIT > 12
    nil_t, nil_t, nil_t,
#endif
    nil_t   //  Unused
>
:   public tuple_base<tuple<A, B, C, D, E, F, G, H, I, J> > {

    BOOST_STATIC_CONSTANT(int, length = 10);
    typedef A a_type; typedef B b_type;
    typedef C c_type; typedef D d_type;
    typedef E e_type; typedef F f_type;
    typedef G g_type; typedef H h_type;
    typedef I i_type; typedef J j_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_,
        typename call_traits<D>::param_type d_,
        typename call_traits<E>::param_type e_,
        typename call_traits<F>::param_type f_,
        typename call_traits<G>::param_type g_,
        typename call_traits<H>::param_type h_,
        typename call_traits<I>::param_type i_,
        typename call_traits<J>::param_type j_
    ):  a(a_), b(b_), c(c_), d(d_), e(e_),
        f(f_), g(g_), h(h_), i(i_), j(j_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()]), d(init[tuple_index<3>()]),
        e(init[tuple_index<4>()]), f(init[tuple_index<5>()]),
        g(init[tuple_index<6>()]), h(init[tuple_index<7>()]),
        i(init[tuple_index<8>()]), j(init[tuple_index<9>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c; D d; E e;
    F f; G g; H h; I i; J j;
};

///////////////////////////////////////////////////////////////////////////////
//
//  tuple <11 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <
    typename A, typename B, typename C, typename D, typename E,
    typename F, typename G, typename H, typename I, typename J,
    typename K>
struct tuple<A, B, C, D, E, F, G, H, I, J, K, nil_t,
#if PHOENIX_LIMIT > 12
    nil_t, nil_t, nil_t,
#endif
    nil_t   //  Unused
>
:   public tuple_base<tuple<A, B, C, D, E, F, G, H, I, J, K> > {

    BOOST_STATIC_CONSTANT(int, length = 11);
    typedef A a_type; typedef B b_type;
    typedef C c_type; typedef D d_type;
    typedef E e_type; typedef F f_type;
    typedef G g_type; typedef H h_type;
    typedef I i_type; typedef J j_type;
    typedef K k_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_,
        typename call_traits<D>::param_type d_,
        typename call_traits<E>::param_type e_,
        typename call_traits<F>::param_type f_,
        typename call_traits<G>::param_type g_,
        typename call_traits<H>::param_type h_,
        typename call_traits<I>::param_type i_,
        typename call_traits<J>::param_type j_,
        typename call_traits<K>::param_type k_
    ):  a(a_), b(b_), c(c_), d(d_), e(e_),
        f(f_), g(g_), h(h_), i(i_), j(j_),
        k(k_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()]), d(init[tuple_index<3>()]),
        e(init[tuple_index<4>()]), f(init[tuple_index<5>()]),
        g(init[tuple_index<6>()]), h(init[tuple_index<7>()]),
        i(init[tuple_index<8>()]), j(init[tuple_index<9>()]),
        k(init[tuple_index<10>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c; D d; E e;
    F f; G g; H h; I i; J j;
    K k;
};

///////////////////////////////////////////////////////////////////////////////
//
//  tuple <12 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <
    typename A, typename B, typename C, typename D, typename E,
    typename F, typename G, typename H, typename I, typename J,
    typename K, typename L>
struct tuple<A, B, C, D, E, F, G, H, I, J, K, L,
#if PHOENIX_LIMIT > 12
    nil_t, nil_t, nil_t,
#endif
    nil_t   //  Unused
>
:   public tuple_base<tuple<A, B, C, D, E, F, G, H, I, J, K, L> > {

    BOOST_STATIC_CONSTANT(int, length = 12);
    typedef A a_type; typedef B b_type;
    typedef C c_type; typedef D d_type;
    typedef E e_type; typedef F f_type;
    typedef G g_type; typedef H h_type;
    typedef I i_type; typedef J j_type;
    typedef K k_type; typedef L l_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_,
        typename call_traits<D>::param_type d_,
        typename call_traits<E>::param_type e_,
        typename call_traits<F>::param_type f_,
        typename call_traits<G>::param_type g_,
        typename call_traits<H>::param_type h_,
        typename call_traits<I>::param_type i_,
        typename call_traits<J>::param_type j_,
        typename call_traits<K>::param_type k_,
        typename call_traits<L>::param_type l_
    ):  a(a_), b(b_), c(c_), d(d_), e(e_),
        f(f_), g(g_), h(h_), i(i_), j(j_),
        k(k_), l(l_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()]), d(init[tuple_index<3>()]),
        e(init[tuple_index<4>()]), f(init[tuple_index<5>()]),
        g(init[tuple_index<6>()]), h(init[tuple_index<7>()]),
        i(init[tuple_index<8>()]), j(init[tuple_index<9>()]),
        k(init[tuple_index<10>()]), l(init[tuple_index<11>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c; D d; E e;
    F f; G g; H h; I i; J j;
    K k; L l;
};

#if PHOENIX_LIMIT > 12
///////////////////////////////////////////////////////////////////////////////
//
//  tuple <13 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <
    typename A, typename B, typename C, typename D, typename E,
    typename F, typename G, typename H, typename I, typename J,
    typename K, typename L, typename M>
struct tuple<A, B, C, D, E, F, G, H, I, J, K, L, M, nil_t, nil_t, nil_t>
:   public tuple_base<
        tuple<A, B, C, D, E, F, G, H, I, J, K, L, M> > {

    BOOST_STATIC_CONSTANT(int, length = 13);
    typedef A a_type; typedef B b_type;
    typedef C c_type; typedef D d_type;
    typedef E e_type; typedef F f_type;
    typedef G g_type; typedef H h_type;
    typedef I i_type; typedef J j_type;
    typedef K k_type; typedef L l_type;
    typedef M m_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_,
        typename call_traits<D>::param_type d_,
        typename call_traits<E>::param_type e_,
        typename call_traits<F>::param_type f_,
        typename call_traits<G>::param_type g_,
        typename call_traits<H>::param_type h_,
        typename call_traits<I>::param_type i_,
        typename call_traits<J>::param_type j_,
        typename call_traits<K>::param_type k_,
        typename call_traits<L>::param_type l_,
        typename call_traits<M>::param_type m_
    ):  a(a_), b(b_), c(c_), d(d_), e(e_),
        f(f_), g(g_), h(h_), i(i_), j(j_),
        k(k_), l(l_), m(m_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()]), d(init[tuple_index<3>()]),
        e(init[tuple_index<4>()]), f(init[tuple_index<5>()]),
        g(init[tuple_index<6>()]), h(init[tuple_index<7>()]),
        i(init[tuple_index<8>()]), j(init[tuple_index<9>()]),
        k(init[tuple_index<10>()]), l(init[tuple_index<11>()]),
        m(init[tuple_index<12>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c; D d; E e;
    F f; G g; H h; I i; J j;
    K k; L l; M m;
};

///////////////////////////////////////////////////////////////////////////////
//
//  tuple <14 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <
    typename A, typename B, typename C, typename D, typename E,
    typename F, typename G, typename H, typename I, typename J,
    typename K, typename L, typename M, typename N>
struct tuple<A, B, C, D, E, F, G, H, I, J, K, L, M, N, nil_t, nil_t>
:   public tuple_base<
        tuple<A, B, C, D, E, F, G, H, I, J, K, L, M, N> > {

    BOOST_STATIC_CONSTANT(int, length = 14);
    typedef A a_type; typedef B b_type;
    typedef C c_type; typedef D d_type;
    typedef E e_type; typedef F f_type;
    typedef G g_type; typedef H h_type;
    typedef I i_type; typedef J j_type;
    typedef K k_type; typedef L l_type;
    typedef M m_type; typedef N n_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_,
        typename call_traits<D>::param_type d_,
        typename call_traits<E>::param_type e_,
        typename call_traits<F>::param_type f_,
        typename call_traits<G>::param_type g_,
        typename call_traits<H>::param_type h_,
        typename call_traits<I>::param_type i_,
        typename call_traits<J>::param_type j_,
        typename call_traits<K>::param_type k_,
        typename call_traits<L>::param_type l_,
        typename call_traits<M>::param_type m_,
        typename call_traits<N>::param_type n_
    ):  a(a_), b(b_), c(c_), d(d_), e(e_),
        f(f_), g(g_), h(h_), i(i_), j(j_),
        k(k_), l(l_), m(m_), n(n_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()]), d(init[tuple_index<3>()]),
        e(init[tuple_index<4>()]), f(init[tuple_index<5>()]),
        g(init[tuple_index<6>()]), h(init[tuple_index<7>()]),
        i(init[tuple_index<8>()]), j(init[tuple_index<9>()]),
        k(init[tuple_index<10>()]), l(init[tuple_index<11>()]),
        m(init[tuple_index<12>()]), n(init[tuple_index<13>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c; D d; E e;
    F f; G g; H h; I i; J j;
    K k; L l; M m; N n;
};

///////////////////////////////////////////////////////////////////////////////
//
//  tuple <15 member> class
//
///////////////////////////////////////////////////////////////////////////////
template <
    typename A, typename B, typename C, typename D, typename E,
    typename F, typename G, typename H, typename I, typename J,
    typename K, typename L, typename M, typename N, typename O>
struct tuple<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, nil_t>
:   public tuple_base<
        tuple<A, B, C, D, E, F, G, H, I, J, K, L, M, N, O> > {

    BOOST_STATIC_CONSTANT(int, length = 15);
    typedef A a_type; typedef B b_type;
    typedef C c_type; typedef D d_type;
    typedef E e_type; typedef F f_type;
    typedef G g_type; typedef H h_type;
    typedef I i_type; typedef J j_type;
    typedef K k_type; typedef L l_type;
    typedef M m_type; typedef N n_type;
    typedef O o_type;

    tuple() {}

    tuple(
        typename call_traits<A>::param_type a_,
        typename call_traits<B>::param_type b_,
        typename call_traits<C>::param_type c_,
        typename call_traits<D>::param_type d_,
        typename call_traits<E>::param_type e_,
        typename call_traits<F>::param_type f_,
        typename call_traits<G>::param_type g_,
        typename call_traits<H>::param_type h_,
        typename call_traits<I>::param_type i_,
        typename call_traits<J>::param_type j_,
        typename call_traits<K>::param_type k_,
        typename call_traits<L>::param_type l_,
        typename call_traits<M>::param_type m_,
        typename call_traits<N>::param_type n_,
        typename call_traits<O>::param_type o_
    ):  a(a_), b(b_), c(c_), d(d_), e(e_),
        f(f_), g(g_), h(h_), i(i_), j(j_),
        k(k_), l(l_), m(m_), n(n_), o(o_) {}

    template <typename TupleT>
    tuple(TupleT const& init)
    :   a(init[tuple_index<0>()]), b(init[tuple_index<1>()]),
        c(init[tuple_index<2>()]), d(init[tuple_index<3>()]),
        e(init[tuple_index<4>()]), f(init[tuple_index<5>()]),
        g(init[tuple_index<6>()]), h(init[tuple_index<7>()]),
        i(init[tuple_index<8>()]), j(init[tuple_index<9>()]),
        k(init[tuple_index<10>()]), l(init[tuple_index<11>()]),
        m(init[tuple_index<12>()]), n(init[tuple_index<13>()]),
        o(init[tuple_index<14>()])
    { BOOST_STATIC_ASSERT(TupleT::length == length); }

    A a; B b; C c; D d; E e;
    F f; G g; H h; I i; J j;
    K k; L l; M m; N n; O o;
};

#endif
#endif
#endif
#endif

///////////////////////////////////////////////////////////////////////////////
}   //  namespace phoenix

#endif
