第三章(TypedefList>

书中部分代码不准确,以代码实例为准



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



Loki库的学习:
Loki中有另外一种方法代替宏TYPELIST_1。用来迭代的方式去实现
template
        <
            typename T1  = NullType, typename T2  = int, typename T3  = NullType,
            typename T4  = NullType, typename T5  = NullType, typename T6  = NullType,
            typename T7  = NullType, typename T8  = NullType, typename T9  = NullType,
            typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
            typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
            typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
        >
        struct MakeTypelist
        {
        private:
            typedef typename MakeTypelist
            <
                T2 , T3 , T4 ,
                T5 , T6 , T7 ,
                T8 , T9 , T10,
                T11, T12, T13,
                T14, T15, T16,
                T17, T18
            >
            ::Result TailResult;
        public:
            typedef Typelist<T1, TailResult> Result;
        };

        // 模板特化,如果指定的模板参数符合默认参数,即没有指定任何参数的情况下或则是指定的参数与默认参数一致。MakeTypeList<NullType> aa会进入到下面这个特例化中,而不是进入到上面。
        template<>
        struct MakeTypelist<>
        {
            typedef NullType Result;
        };

       // 去除TypeList中重复元素的方法
template <class TList> struct NoDuplicates;
       
        template <> struct NoDuplicates<NullType>
        {
            typedef NullType Result;
        };
        template <class Head, class Tail>
        struct NoDuplicates< Typelist<Head, Tail> >
        {
        private:
            typedef typename NoDuplicates<Tail>::Result L1;
           // 通过编译器删除重复的类型。在L1列表中删除Head.L1即后面的列表,即<T1,T2,T3,T4>.从<T2,T3,T4>中删除T1。如果T2,T3,T4中有T1则刚好删除重复的了
           // 多么简单清晰的逻辑
            typedef typename Erase<L1, Head>::Result L2;
        public:
            typedef Typelist<Head, L2> Result;
        };


       另外也列举下erase的实现说明实现递归三个重要的特例化。
template <class TList, class T> struct Erase;
       
  // 一般都有三个特例化实现。
  // NullType情况下的实现,解决最后递归结束标记。如果查找失败的话
        template <class T>                         // Specialization 1
        struct Erase<NullType, T>
        {
            typedef NullType Result;
        };
  // 满足条件情况下的实现。刚好碰到T的情况。如果能找到符合条件规则,会先到这个里面,然后就结束了递归。NullType和这个特例化只会进入一个
        template <class T, class Tail>             // Specialization 2
        struct Erase<Typelist<T, Tail>, T>
        {
            typedef Tail Result;
        };
  // 非满足条件下的下一次递归
        template <class Head, class Tail, class T> // Specialization 3
        struct Erase<Typelist<Head, Tail>, T>
        {
            typedef Typelist<Head,
                    typename Erase<Tail, T>::Result>
                Result;
        };

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值