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;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
作者:许强1. 本博客中的文章均是个人在学习和项目开发中总结。其中难免存在不足之处 ,欢迎留言指正。 2. 本文版权归作者和博客园共有,转载时,请保留本文链接。