tuples/tuple1.hpp

The following code example is taken from the book
C++ Templates - The Complete Guide
by David Vandevoorde and Nicolai M. Josuttis, Addison-Wesley, 2002
© Copyright David Vandevoorde and Nicolai M. Josuttis 2002


#include "duo1.hpp"
#include "duo2.hpp"
#include "duo3.hpp"
#include "duo4.hpp"
#include "duo5.hpp"
#include "duo6.hpp"
#include "typeop.hpp"

// type that represents unused type parameters
class NullT {
};

// Tuple<> in general derives from Tuple<> with one more NullT
template <typename P1,
          typename P2 = NullT,
          typename P3 = NullT,
          typename P4 = NullT,
          typename P5 = NullT>
class Tuple
 : public Duo<P1, typename Tuple<P2,P3,P4,P5,NullT>::BaseT> {
  public:
    typedef Duo<P1, typename Tuple<P2,P3,P4,P5,NullT>::BaseT>
            BaseT;

    // constructors:
    Tuple() {}
    Tuple(typename TypeOp<P1>::RefConstT a1,
          typename TypeOp<P2>::RefConstT a2,
          typename TypeOp<P3>::RefConstT a3 = NullT(),
          typename TypeOp<P4>::RefConstT a4 = NullT(),
          typename TypeOp<P5>::RefConstT a5 = NullT())
     : BaseT(a1, Tuple<P2,P3,P4,P5,NullT>(a2,a3,a4,a5)) {
    }
};

// specialization to end deriving recursion
template <typename P1, typename P2>
class Tuple<P1,P2,NullT,NullT,NullT> : public Duo<P1,P2> {
  public:
    typedef Duo<P1,P2> BaseT;
    Tuple() {}
    Tuple(typename TypeOp<P1>::RefConstT a1,
          typename TypeOp<P2>::RefConstT a2,
          typename TypeOp<NullT>::RefConstT = NullT(),
          typename TypeOp<NullT>::RefConstT = NullT(),
          typename TypeOp<NullT>::RefConstT = NullT())
     : BaseT(a1, a2) {
    }
};

// specialization for singletons
template <typename P1>
class Tuple<P1,NullT,NullT,NullT,NullT> : public Duo<P1,void> {
  public:
    typedef Duo<P1,void> BaseT;
    Tuple() {}
    Tuple(typename TypeOp<P1>::RefConstT a1,
          typename TypeOp<NullT>::RefConstT = NullT(),
          typename TypeOp<NullT>::RefConstT = NullT(),
          typename TypeOp<NullT>::RefConstT = NullT(),
          typename TypeOp<NullT>::RefConstT = NullT())
     : BaseT(a1) {
    }
};

// convenience function for 1 argument
template <typename T1>
inline
Tuple<T1> make_tuple(T1 const &a1)
{
    return Tuple<T1>(a1);
}

// convenience function for 2 arguments
template <typename T1, typename T2>
inline
Tuple<T1,T2> make_tuple(T1 const &a1, T2 const &a2)
{
    return Tuple<T1,T2>(a1,a2);
}

// convenience function for 3 arguments
template <typename T1, typename T2, typename T3>
inline
Tuple<T1,T2,T3> make_tuple(T1 const &a1, T2 const &a2,
                           T3 const &a3)
{
    return Tuple<T1,T2,T3>(a1,a2,a3);
}

// convenience function for 4 arguments
template <typename T1, typename T2, typename T3, typename T4>
inline
Tuple<T1,T2,T3,T4> make_tuple(T1 const &a1, T2 const &a2, 
                              T3 const &a3, T4 const &a4)
{
    return Tuple<T1,T2,T3,T4>(a1,a2,a3,a4);
}

// convenience function for 5 arguments
template <typename T1, typename T2, typename T3,
          typename T4, typename T5>
inline
Tuple<T1,T2,T3,T4,T5> make_tuple(T1 const &a1, T2 const &a2,
                                 T3 const &a3, T4 const &a4,
                                 T5 const &a5)
{
    return Tuple<T1,T2,T3,T4,T5>(a1,a2,a3,a4,a5);
}