typedeflist里面可以存放各种类型,是类型,不是值哦,值是通过下面Holder和CTypeListApply来实现的,代码充分利用了递归的方法
C++在编译器编程的工具:模板,整数计算,typedef
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typelist.h
#pragma once
#include "../Techniques/TypeTraits.h"
template<typename T, typename U>
struct TypeList
{
typedef T Head;
typedef U Tail;
};
// 我们约定TypeList必须以NullType结束
typedef TypeList<char, TypeList<signed char, TypeList<unsigned char, NullType> > > AllCharTyes;
#define TYPELIST_1(T1) TypeList<T1, NullType>
#define TYPELIST_2(T1, T2) TypeList<T1, TYPELIST_1(T2)>
#define TYPELIST_3(T1, T2, T3) TypeList<T1, TYPELIST_2(T2, T3) >
#define TYPELIST_4(T1, T2, T3, T4) TypeList<T1, TYPELIST_3(T2, T3, T4) >
#define TYPELIST_5(T1, T2, T3, T4, T5) TypeList<T1, TYPELIST_4(T2, T3, T4, T5) >
typedef TYPELIST_2(int, int) Test;
typedef TYPELIST_4(signed char, short int ,int, long int) SignedIntegrals;
//计算Typelist的长度
template<typename TList>
struct Length;
template<>
struct Length<NullType>
{
enum{value = 0};
};
template<class T, class U>
struct Length<TypeList<T, U> >
{
enum{value = 1 + Length<U>::value};
};
// 访问里面索引的值
template<class TList, unsigned int i>
struct TypeAt;
template<class Head, class Tail>
struct TypeAt<TypeList<Head, Tail> , 0>
{
typedef Head Result;
};
template<typename Head, typename Tail, unsigned int i>
struct TypeAt<TypeList<Head, Tail> , i>
{
typedef typename TypeAt<Tail, i - 1>::Result Result;
};
// 获取类型的索引
template<class TList, class U>
struct IndexOf;
template<class T>
struct IndexOf<NullType, T>
{
enum {value = -1};
};
template<class Tail, class T>
struct IndexOf<TypeList<T, Tail>, T>
{
enum {value = 0};
};
template<class Head, class Tail ,class T>
struct IndexOf<TypeList<Head, Tail>, T>
{
private:
enum {temp = IndexOf<Tail, T>::value}; // T可能会找不到,为-1,需要考虑到
public:
enum {value = temp == -1 ? -1 : 1 + temp};
};
// 添加元素
template<typename TList, class T>
struct Append;
template<>
struct Append<NullType, NullType>
{
typedef NullType Result;
};
template<typename TList>
struct Append<NullType, TList>
{
typedef TypeList<TList, NullType> Result;
};
template<typename Head, typename Tail>
struct Append<NullType, TypeList<Head, Tail> >
{
typedef TypeList<Head, Tail> Result;
};
template<typename Head, typename Tail, class T>
struct Append<TypeList<Head, Tail>, T>
{
typedef TypeList<Head, typename Append<Tail, T>::Result> Result;
};
// 删除元素
// 移除重复元素
// 替换元素
// 调换里面元素顺序位置
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MyTuple.h
#pragma once
#include "TypeList.h"
// 此TypeListApply继承关系比较复杂,会重复继承,如果对大小要求比较高,不适合适用。可以换为TypeListLinearApply线性继承
template<typename TList, template<class> class Unit>
class CMyTuple;
//template<class T1, class T2, template<class> class Unit>
//class CMyTuple<TYPELIST_2(T1, T2), Unit>
// : public CMyTuple<T1, Unit>,
// public CMyTuple<TypeList<T2, NullType>, Unit>
//{
//
//};
template<class T1, class T2, template<class> class Unit>
class CMyTuple<TypeList<T1, T2>, Unit>
: public CMyTuple<T1, Unit>,
public CMyTuple<T2, Unit>
{
};
template<class NoTList, template<class> class Unit>
class CMyTuple: public Unit<NoTList>
{
};
template<template<class> class Unit>
class CMyTuple<NullType, Unit>
{
};
template<typename T>
struct Holder
{
Holder()
:value_(T())
{
}
T value_;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FieldHelper.h
#pragma once
#include "../Techniques/Int2Type.h"
#include "MyTuple.h"
template<class TList, template<class> class Unit>
typename TList::Head& FieldHelper(CMyTuple<TList, Unit>& obj, Int2Type<0>)
{
CMyTuple<TList::Head, Unit>& leftBase = obj;
return leftBase.value_;
}
template<int i, class TList, template<class> class Unit>
typename TypeAt<TList, i>::Result& FieldHelper(CMyTuple<TList, Unit>& obj, Int2Type<i>)
{
CMyTuple<TList::Tail, Unit>& rightBase = obj;
return FieldHelper(rightBase, Int2Type<i - 1>());
}
// 通过类型获取Field,如果出现重复类型就无能为力了
template<class T, class TList, template<class> class Unit>
T& Field(CMyTuple<TList, Unit>& obj)
{
Unit<T>& tmp = static_cast<Unit<T> &>(obj);// 直接使用编译器的默认转换即可,子类转换为某一个基类
return tmp.value_;
}
// 重新实现Field,适用索引访问
template<int i, class TList, template<class> class Unit>
typename TypeAt<TList, i>::Result& Field(CMyTuple<TList, Unit>& obj)
{
return FieldHelper(obj, Int2Type<i>());
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MyLinearTuple.h
线性关系的Tuple
#pragma once
#include "TypeList.h"
#include "../Techniques/TypeTraits.h"
template<class TList, template<class U, class T>class Unit, class Root = EmptyType>
class CMyLinearTuple;
template<typename T1, typename T2, template<class, class> class Unit, class Root>
class CMyLinearTuple<TypeList<T1, T2> , Unit, Root>
: public Unit<T1, CMyLinearTuple<T2, Unit, Root> >
{
};
template<class T, template<class, class>class Unit, class Root>
class CMyLinearTuple<TYPELIST_1(T), Unit, Root>
: public Unit<T, Root>
{
};
template<typename T, typename Base>
struct LinearHolder: public Base
{
LinearHolder()
:value_(T())
{
}
T value_;
};
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
TestTypeList.cpp
使用示例
// TestTypeList继承自Holder<int>, Holder<string>, Holder<char>,
// 即内部包含了这三种类型的数据,即有点像实现了tuple。但是也出现了较多空类
typedef CMyTuple<TYPELIST_3(int, string, char), Holder> TypeList3Holder;
typedef CMyTuple<TYPELIST_3(int, string, int), Holder> TypeListSameHolder;
void CTestTypelist::TestTuple()
{
TypeList3Holder obj;
Holder<int> obj_int = static_cast<Holder<int>&>(obj);
int i1 = obj_int.value_;
Holder<string> obj_string = static_cast<Holder<string>&>(obj);
string str2 = obj_string.value_;
Holder<char> obj_char = static_cast<Holder<char>&>(obj);
char c3 = obj_char.value_;
TypeAt<TYPELIST_3(int, string, char), 0>::Result i = 10;
}
void CTestTypelist::TestField()
{
TypeList3Holder obj;
int h2 = Field<int>(obj);
Field<int>(obj) = 200;
h2 = Field<int>(obj);
TypeListSameHolder objSameType;
int h1 = Field<0>(objSameType);
Field<0>(objSameType) = 100;
h1 = Field<0>(objSameType);
}
void CTestTypelist::TestLinearTuple()
{
// 线性类。CMyLinearTuple继承自LinearHolder<int>,LinearHolder<int>又继承自LinearHolder<char>,LinearHolder<char>又继承LinearHolder<string>最后都继承自
// EmptyType。是一个线性的继承关系,与CMyTuple是有差别的,两者类的拓扑图不同。
typedef CMyLinearTuple<TYPELIST_3(int, char, string), LinearHolder, EmptyType> TupleLinearHolder;
TupleLinearHolder obj;
//int i = Field<0>(obj);
}
20150630
当访问索引不存在时,但是外面使用又需要访问到。如果按照以前的TypeAt会编译不通过(比如仿函数中的参数不知道typelist的参数列表)。
此时可以提供一个,访问索引不存在就返回一个默认类型。可以在仿函数的实现中看到使用
// 访问里面的索引,如果索引不存在,则返回DefaultResult
template<class TList, unsigned int i, class DefaultType = EmptyType>
struct TypeAtNonStrict
{
typedef DefaultType Result;
};
template <class Head, class Tail, typename DefaultType>
struct TypeAtNonStrict<TypeList<Head, Tail>, 0, DefaultType>
{
typedef Head Result;
};
template <class Head, class Tail, unsigned int i, typename DefaultType>
struct TypeAtNonStrict<TypeList<Head, Tail>, i, DefaultType>
{
typedef typename TypeAtNonStrict<Tail, i - 1, DefaultType>::Result Result;
};