Tuple实现源代码

//////////////////////////////////////////////////////////////////////////

// TUPLE COMPLETE CORRECT

//////////////////////////////////////////////////////////////////////////

/**************************************************************************

TypeOperator Definition

***************************************************************************/

/************************************************************************/

/*

template<class T> class TypeOperator

template<class T> class TypeOperator<T const>

template<class T> class TypeOperator<T&>

template<> class TypeOperator<void>

*/

/************************************************************************/

template<class T>

class TypeOperator{

public:

typedef T AgrT;

typedef T BareT;

typedef const T ConstT;

typedef T& RefT;

typedef T& RefBareT;

typedef T const& RefConstT;

};

template<class T>

class TypeOperator<T const> {

public:

typedef T const ArgT;

typedef T BareT;

typedef T const ConstT;

typedef T const& RefT;

typedef T& RefBareT;

typedef T const & RefConstT;

};

template<class T>

class TypeOperator<T&> {

public:

typedef T& ArgT;

typedef typename TypeOperator<T>::BareT BareT;

typedef T const ConstT;

typedef T& RefT;

typedef typename TypeOperator<T>::BareT& RefBareT;

typedef T const & RefConstT;

};

template<>

class TypeOperator<void> {

public:

typedef void ArgT;

typedef void BareT;

typedef void const ConstT;

typedef void RefT;

typedef void RefBareT;

typedef void RefConstT;

};

/**************************************************************************

Duo

**************************************************************************/

/************************************************************************/

/*

template<class T1, class T2> struct Duo 

template<class A> class Duo<A, void> 

*/

/************************************************************************/

//A duo is the assembly of two objects into a single type. This is similar

//to the std::pair class template in the standard library, but because we

//will add slightly different functionality to this very basic utility,

template<class T1, class T2>

struct Duo {

typedef T1 Type1; //type of first field

typedef T2 Type2; //type of second field

enum { N = 2 }; //number of fields

T1 value1;

T2 value2;

//constructor

Duo() : value1(), value2() {

};

Duo(const T1& a, const T2& b) : value1(a), value2(b) {

};

//copy constructor

template<class U1, class U2>

Duo(Duo<U1, U2> const& d) : value1(d.v1()), value2(d.v2()) {

};

template<class U1,class U2>

Duo<T1, T2>& operator=(Duo<U1, U2> const& d) {

value1 = d.value1;

value2 = d.value2;

return *this;

};

//field access

T1& v1() {

return value1;

};

T2& v2() {

return value2;

};

};

//comparison operators (allow mixed types):

template<class T1, class T2, class U1, class U2>

inline

bool operator==(Duo<T1, T2> const& d1, Duo<U1, U2> const& d2) {

return d1.v1() == d2.v1() && d1.v2() == d2.v2();

};

template<class T1, class T2, class U1, class U2>

inline

bool operator!=(Duo<T1, T2> const& d1, Duo<U1, U2> const& d2) {

return !(d1 == d2);

}

//To avoid the need for explicit type parameters, we can further add a function

//so that the field types can be deduced

template<class T1, class T2>

inline

Duo<T1, T2> make_duo(const T1& a, const T2& b) {

return Duo<T1, T2>(a, b);

}

template<class A, class B, class C>

class Duo<A, Duo<B, C> > {

public:

typedef A T1;

typedef Duo<B, C> T2;

enum { N = Duo<B, C>::N + 1 };

private:

T1 value1;

T2 value2;

public:

//the other public members are unchanged

//constructor

Duo() : value1(), value2() {

};

Duo(const T1& a, const T2& b) : value1(a), value2(b) {

};

//copy constructor

template<class D, class E, class F>

Duo(Duo<D, Duo<E, F> > const& d) {

value1 = d.v1();

value2 = d.v2();

};

template<class D,class E, class F>

Duo<T1, T2>& operator=(Duo<D, Duo<E, F> > const& d) {

value1 = d.value1;

value2 = d.value2;

return *this;

};

//field access

T1& v1() {

return value1;

};

T2& v2() {

return value2;

};

};

//partial specialization for Duo<> with only one field

template<class A>

class Duo<A, void> {

public:

typedef A T1;

typedef void T2;

enum { N = 1 };

private:

T1 value1;

public:

//constructor

Duo() : value1() {

};

Duo(T1 const& a) : value1(a) {

};

//field access

T1& v1() {

return value1;

};

/*********************************************************************

a void type can not reach

T2& v2() const {

return value2;

};

**********************************************************************/

};

/**************************************************************************

DuoT

***************************************************************************/

/************************************************************************/

/*

template<int N, class T> class DuoT 

template<class A, class B> class DuoT<1, Duo<A, B> >

template<class A, class B>class DuoT<2, Duo<A, B> >  

template<int N, class A, class B, class C> class DuoT<N, Duo<A, Duo<B, C> > >

template<class A, class B, class C> class DuoT<1, Duo<A, Duo<B, C> > >

template<class A, class B, class C> class DuoT<2, Duo<A, Duo<B, C> > >

*/

/************************************************************************/

template<int N, class T>

class DuoT {

public:

typedef void ResultT; //in general, the result type is void

//but it is usually can not be used

//ensures that the result type is void 

//for non-Duos

};

//Fairly simple partial specializations take care of retrieving the 

//types from nonrecursive Duos:

//-------------------------------------------------------------------------

template<class A, class B>

class DuoT<1, Duo<A, B> > {

public:

typedef A ResultT;

};

template<class A, class B>

class DuoT<2, Duo<A, B> > {

public:

typedef B ResultT;

};

//-------------------------------------------------------------------------

//With this in place, the nth type of a recursive duo, in general, is the 

//(n-1)th type of the second field

//-------------------------------------------------------------------------

template<int N, class A, class B, class C>

class DuoT<N, Duo<A, Duo<B, C> > > {

public:

typedef typename DuoT<N - 1, Duo<B, C> >::ResultT ResultT;

};

//-------------------------------------------------------------------------

//-------------------------------------------------------------------------

//however, the request for the first type of a recurssion duo ends the recursion

template<class A, class B, class C>

class DuoT<1, Duo<A, Duo<B, C> > > {

public:

typedef A ResultT;

};

//note that the case for the second type of recursive duo also needs a partial

//specialization to avooidambiguity with the nonrecursive case

template<class A, class B, class C>

class DuoT<2, Duo<A, Duo<B, C> > > {

public:

typedef B ResultT;

};

//-------------------------------------------------------------------------

/**************************************************************************

DuoValue

***************************************************************************/

//primary template for value of Nth field of (duo) T

template<int N, class T>

class DuoValue {

public:

static void get(T&) {

};

static void get(T const&) {

};

};

//specialization for 1st field of a plain duo

template<class A, class B>

class DuoValue<1, Duo<A, B> > {

public:

static A& get(Duo<A, B>& d) {

return d.v1();

};

static A const& get(Duo<A, B> const& d) {

return d.v1();

};

};

//specialization for 2nd field of a plain duo

template<class A, class B>

class DuoValue<2, Duo<A, B> > {

public:

static B& get(Duo<A, B>& d) {

return d.v2();

};

static B const& get(Duo<A, B> const& d) {

return d.v2();

};

};

// specialization for Nth field of recursive duo

template<int N, class A, class B, class C>

class DuoValue<N, Duo<A, Duo<B, C> > > {

public:

static

typename TypeOperator<typename DuoT<N - 1, Duo <B, C> >::ResultT>::RefT

get(Duo<A, Duo<B, C> >& d) {

return DuoValue<N - 1, Duo<B, C> >::get(d.v2());

};

static

typename TypeOperator<typename DuoT<N - 1, Duo<B, C> >::ResultT>::RefConstT

get(Duo<A, Duo<B, C> > const& d) {

return DuoValue<N - 1, Duo<B, C> >::get(d.v2());

};

};

// specialization for 1st field of recursive duo

template<class A, class B, class C>

class DuoValue<1, Duo<A, Duo<B, C> > > {

public:

static A& get(Duo<A, Duo<B, C> >& d) {

return d.v1();

};

static A const& get(Duo<A, Duo<B, C> > const& d) {

return d.v1();

};

};

// specialization for 2nd field of recursive duo

template<class A, class B, class C>

class DuoValue<2, Duo<A, Duo<B, C> > > {

public:

static B& get(Duo<A, Duo<B, C> >& d) {

return d.v2().v1();

};

static B const& get(Duo<A, Duo<B, C> > const& d) {

return d.v2().v1();

};

};

/*************************************************************************

Val

***************************************************************************/

template<int N, class A, class B>

inline

typename TypeOperator<typename DuoT<N, Duo<A, B> >::ResultT >::RefT

val(Duo<A, B>& d) {

return DuoValue<N, Duo<A, B> >::get(d);

}

template<int N, class A, class B>

inline

typename TypeOperator<typename DuoT<N, Duo<A, B> >::ResultT >::RefConstT

val(Duo<A, B> const& d) {

return DuoValue<N, Duo<A, B> >::get(d);

}

/***************************************************************************

Tuple

****************************************************************************/

//type that represents unused type parameters

class NullT {

};

//Tuple<> in general derives from Tuple<> with one more NullT

template<

class P1,

class P2 = NullT,

class P3 = NullT,

class P4 = NullT,

class 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;

//constructor

Tuple() { };

Tuple(typename TypeOperator<P1>::RefConstT a1,

typename TypeOperator<P2>::RefConstT a2,

typename TypeOperator<P3>::RefConstT a3 = NullT(),

typename TypeOperator<P4>::RefConstT a4 = NullT(),

typename TypeOperator<P5>::RefConstT a5 = NullT()

)

: BaseT(a1, Tuple<P2, P3, P4, P5, NullT>(a2, a3, a4, a5)) {

};

};

//We need a partial specialization to end this recursion with the derivation

//from a nonrecursive duo:

template<class P1, class P2>

class Tuple<P1, P2, NullT, NullT, NullT> : public Duo<P1, P2> {

public:

typedef Duo<P1, P2> BaseT;

//constructor

Tuple() { };

Tuple(

typename TypeOperator<P1>::RefConstT a1,

typename TypeOperator<P2>::RefConstT a2,

typename TypeOperator<NullT>::RefConstT = NullT(),

typename TypeOperator<NullT>::RefConstT = NullT(),

typename TypeOperator<NullT>::RefConstT = NullT()

) : BaseT(a1, a2) {

};

};

//specialization for singletons

template<class P1>

class Tuple<P1, NullT, NullT, NullT, NullT> : public Duo<P1, void> {

public:

typedef Duo<P1, void> BaseT;

//constructor

Tuple() { };

Tuple(

typename TypeOperator<P1>::RefConstT a1,

typename TypeOperator<NullT>::RefConstT = NullT(),

typename TypeOperator<NullT>::RefConstT = NullT(),

typename TypeOperator<NullT>::RefConstT = NullT(),

typename TypeOperator<NullT>::RefConstT = NullT()

) : BaseT(a1) {

};

};

/**************************************************************************

MAKE_TUPLE

***************************************************************************/

// convenience function for 1 argument

template<class T1>

inline

Tuple<T1> make_tuple(const T1& a1) {

return Tuple<T1>(a1);

}

// convenience function for 2 arguments

template<class T1, class T2>

inline

Tuple<T1, T2> make_tuple(const T1& a1, const T2& a2) {

return Tuple<T1, T2> (a1, a2);

}

// convenience function for 3 arguments

template<class T1, class T2, class T3>

inline

Tuple<T1, T2, T3> make_tuple(const T1& a1, const T2& a2, const T3& a3) {

return Tuple<T1, T2, T3>(a1, a2, a3);

}

// convenience function for 4 arguments

template<class T1, class T2, class T3, class T4>

inline

Tuple<T1, T2, T3, T4> make_tuple(const T1& a1, const T2& a2,

const T3& a3, const T4& a4) {

return Tuple<T1, T2, T3, T4>(a1, a2, a3, a4);

}

// convenience function for 5 arguments

template<class T1, class T2, class T3, class T4, class T5>

inline

Tuple<T1, T2, T3, T4, T5> make_tuple(const T1& a1, const T2& a2,

const T3& a3, const T4& a4,

const T5& a5)

{

return Tuple<T1, T2, T3, T4, T5> (a1, a2, a3, a4, a5);

}

/**************************************************************************

DRIVER

**************************************************************************/

#include <iostream>

//DRIVER---2

int main() {

// create and use tuple with only one field

Tuple<int> t1;

val<1>(t1) += 42;

std::cout << t1.v1() << std::endl;

//creat and use duo

std::cout << "test duo" << std::endl;

Tuple<bool, int> t2;

std::cout << val<1>(t2) << " , ";

std::cout << t2.v1() << std::endl;

//creat and use triple

std::cout << "test triple" << std::endl;

Tuple<bool, int, double> t3;

val<1>(t3) = true;

val<2>(t3) = 42;

val<3>(t3) = 0.2;

std::cout << val<1>(t3) << ", ";

std::cout << val<2>(t3) << ", ";

std::cout << val<3>(t3) << std::endl;

t3 = make_tuple(false, 23, 13.13);

std::cout << val<1>(t3) << ", ";

std::cout << val<2>(t3) << ", ";

std::cout << val<3>(t3) << std::endl;

// create and use quadruple

std::cout << "quadruple" << std::endl;

Tuple<bool,int,float,double> t4(true, 42, 13, 1.95583);

std::cout << val<4>(t4) << std::endl;

std::cout << t4.v2().v2().v2() << std::endl;

return 0;

}

//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////

posted @ 2009-12-23 21:47  qiang.xu  阅读(377)  评论(0编辑  收藏  举报