Cpper
C/C++高级工程师 Android高级软件工程师 IT集成工程师 音频工程师 熟悉c,c++,java,c#,py,js,asp等多种语言 程序猿
Loki中的TypeList这块是Loki中比较基础的部分
其主要涉及类型链表(TypeList)
相关功能有
1.模板化得类型链表-最打提供18个类型参数
2.获取类型链表的长度
3.获取给定索引位置的参数类型
4.当索引越界时获取设定的参数类型
5.类型链表的类型增加和剔除
6.其他

下面是makeTypeList的代码
 1       template
 2         <
 3             typename T1  = NullType, typename T2  = NullType, typename T3  = NullType,
 4             typename T4  = NullType, typename T5  = NullType, typename T6  = NullType,
 5             typename T7  = NullType, typename T8  = NullType, typename T9  = NullType,
 6             typename T10 = NullType, typename T11 = NullType, typename T12 = NullType,
 7             typename T13 = NullType, typename T14 = NullType, typename T15 = NullType,
 8             typename T16 = NullType, typename T17 = NullType, typename T18 = NullType
 9         > 
10         struct MakeTypelist
11         {
12         private:
13             typedef typename MakeTypelist
14             <
15                 T2 , T3 , T4 , 
16                 T5 , T6 , T7 , 
17                 T8 , T9 , T10, 
18                 T11, T12, T13,
19                 T14, T15, T16, 
20                 T17, T18
21             >
22             ::Result TailResult;
23 
24         public:
25             typedef Typelist<T1, TailResult> Result;
26         };
27 
28         template<>
29         struct MakeTypelist<>
30         {
31             typedef NullType Result;
32         };
她的作用是构建一个模板参数不超过18个的类型链表
其中NullType是一种PlaceHolder
当定义TypeList的模板参数不超过18个的时候 那么其余参数会被自动设置为NullType
这里提供了一个泛型版本和一个特化版本
当使用MakeTypeList<>的时候就意味着模板参数是NullTYpe

构建除了一个类型链表接下来就需要获取类型链表的参数个数
如下所示:
 1 ////////////////////////////////////////////////////////////////////////////////
 2 // class template Length
 3 // Computes the length of a typelist
 4 // Invocation (TList is a typelist):
 5 // Length<TList>::value
 6 // returns a compile-time constant containing the length of TList, not counting
 7 //     the end terminator (which by convention is NullType)
 8 ////////////////////////////////////////////////////////////////////////////////
 9 
10         template <class TList> struct Length;
11         template <> struct Length<NullType>
12         {
13             enum { value = 0 };
14         };
15         
16         template <class T, class U>
17         struct Length< Typelist<T, U> >
18         {
19             enum { value = 1 + Length<U>::value };
20         };
21 
这里使用了典型的模板元递归
首先设置空的类型链表长度为0
然后获取指定的类型链表长度

而TypeAt得功能是获取类型链表中给定位置的元素类型
 1 ////////////////////////////////////////////////////////////////////////////////
 2 // class template TypeAt
 3 // Finds the type at a given index in a typelist
 4 // Invocation (TList is a typelist and index is a compile-time integral 
 5 //     constant):
 6 // TypeAt<TList, index>::Result
 7 // returns the type in position 'index' in TList
 8 // If you pass an out-of-bounds index, the result is a compile-time error
 9 ////////////////////////////////////////////////////////////////////////////////
10 
11         template <class TList, unsigned int index> struct TypeAt;
12         
13         template <class Head, class Tail>
14         struct TypeAt<Typelist<Head, Tail>0>
15         {
16             typedef Head Result;
17         };
18 
19         template <class Head, class Tail, unsigned int i>
20         struct TypeAt<Typelist<Head, Tail>, i>
21         {
22             typedef typename TypeAt<Tail, i - 1>::Result Result;
23         };

注意这里给定的索引不能超出类型链表的参数个数范围
在这里首先给出当索引为0时对应的参数类型为参数链表中第一个元素类型(在这里就是Head)
然后获取索引位置为i的参数类型的方法是把参数链表的头位置向前退一位 这样就可以在上一步的基础上继续调用其模板特化形式了

而模板家族TypeAtNonStrict所要做的就是在TypeAt基础上所作的当索引越界时对应的参数类型问题
如下所说:
 1 ////////////////////////////////////////////////////////////////////////////////
 2 // class template TypeAtNonStrict
 3 // Finds the type at a given index in a typelist
 4 // Invocations (TList is a typelist and index is a compile-time integral 
 5 //     constant):
 6 // a) TypeAt<TList, index>::Result
 7 // returns the type in position 'index' in TList, or NullType if index is 
 8 //     out-of-bounds
 9 // b) TypeAt<TList, index, D>::Result
10 // returns the type in position 'index' in TList, or D if index is out-of-bounds
11 ////////////////////////////////////////////////////////////////////////////////
代码为:
 1         template <class TList, unsigned int index,
 2             typename DefaultType = NullType>
 3         struct TypeAtNonStrict
 4         {
 5             typedef DefaultType Result;
 6         };
 7         
 8         template <class Head, class Tail, typename DefaultType>
 9         struct TypeAtNonStrict<Typelist<Head, Tail>0, DefaultType>
10         {
11             typedef Head Result;
12         };
13         
14         template <class Head, class Tail, unsigned int i, typename DefaultType>
15         struct TypeAtNonStrict<Typelist<Head, Tail>, i, DefaultType>
16         {
17             typedef typename 
18                 TypeAtNonStrict<Tail, i - 1, DefaultType>::Result Result;
19         };

 这里有三个版本分别为获取越界时的参数类型
获取头参数类型
第三个是获取给定位置的参数类型

接下来的模板类IndexOf的作用是获取给定类型在类型链表中首次出现的位置

1 ////////////////////////////////////////////////////////////////////////////////
2 // class template IndexOf
3 // Finds the index of a type in a typelist
4 // Invocation (TList is a typelist and T is a type):
5 // IndexOf<TList, T>::value
6 // returns the position of T in TList, or NullType if T is not found in TList
7 ////////////////////////////////////////////////////////////////////////////////
具体代码为:
 1        template <class TList, class T> struct IndexOf;
 2         
 3         template <class T>
 4         struct IndexOf<NullType, T>
 5         {
 6             enum { value = -1 };
 7         };
 8         
 9         template <class T, class Tail>
10         struct IndexOf<Typelist<T, Tail>, T>
11         {
12             enum { value = 0 };
13         };
14         
15         template <class Head, class Tail, class T>
16         struct IndexOf<Typelist<Head, Tail>, T>
17         {
18         private:
19             enum { temp = IndexOf<Tail, T>::value };
20         public:
21             enum { value = (temp == -1 ? -1 : 1 + temp) };
22         };
需要说明的在TypeList这里(也许更多的是在其他地方)
对这种TypeList的操作基本上都是采用的在类型链表基础之上生成新的类型链表
这样就可以保证新的参数链表头结点为上次迭代链表的第2个节点这是这类操作的基础

下面一个是对参数链表的参数附加
 1 ////////////////////////////////////////////////////////////////////////////////
 2 // class template Append
 3 // Appends a type or a typelist to another
 4 // Invocation (TList is a typelist and T is either a type or a typelist):
 5 // Append<TList, T>::Result
 6 // returns a typelist that is TList followed by T and NullType-terminated
 7 ////////////////////////////////////////////////////////////////////////////////
 8 
 9         template <class TList, class T> struct Append;
10         
11         template <> struct Append<NullType, NullType>
12         {
13             typedef NullType Result;
14         };
15         
16         template <class T> struct Append<NullType, T>
17         {
18             typedef Typelist<T,NullType> Result;
19         };
20 
21         template <class Head, class Tail>
22         struct Append<NullType, Typelist<Head, Tail> >
23         {
24             typedef Typelist<Head, Tail> Result;
25         };
26         
27         template <class Head, class Tail, class T>
28         struct Append<Typelist<Head, Tail>, T>
29         {
30             typedef Typelist<Head, 
31                     typename Append<Tail, T>::Result>
32                 Result;
33         };
在这里可以把一个新的类型或者一个类型链表附加到另外一个类型链表中去
那么后者的参数个数数相会变为2者之和
这里的代码表明如何把一个类型(链表)附加到一个NUllType上去
那么结果就是原有的类型链表
1         template <class T> struct Append<NullType, T>
2         {
3             typedef Typelist<T,NullType> Result;
4         };
如果附加前后的类型都为NUllType
则结果不发生变化-代码段为第一个模板
而第三个模板表明其附加的手法是对新加入的类型链表中的参数类型逐个加入的

下面是相关的测试代码:
 1 
 2 #include <iostream>
 3 #include <string>
 4 #include <Loki/TypeList.h>
 5 
 6 typedef int Type;
 7 typedef Loki::TL::MakeTypelist<Type,
 8                                char,
 9                                long,
10                                bool,
11                                std::string,
12                                double,
13                                unsigned int,
14                                long long> MyList;
15 class Class{};                               
16 
17 int main()
18 {
19     MyList::Result hlist;
20     std::cout <<"MyList length "<<Loki::TL::Length<MyList::Result>::value<<std::endl; 
21     Loki::TL::TypeAt<MyList::Result,1>::Result result;
22     std::cout<<"the type in indexo of 1: "<<result<<std::endl; 
23     Loki::TL::TypeAtNonStrict<MyList::Result,0>::Result _type; 
24     std::cout<<"default value in index of 0:" <<_type<<std::endl;
25     std::cout<<Loki::TL::IndexOf<MyList::Result,long>::value<<std::endl; 
26     typedef Loki::TL::Append<MyList::Result,Class>::Result NewType;
27     std::cout <<"get length of NewType: "<< Loki::TL::Length<NewType>::value<<std::endl; 
28     
29     system("PAUSE");
30     return EXIT_SUCCESS;
31 }

当然Typelist还有其他一些操作比如类型删除等等
以后再说吧
posted on 2010-04-10 12:25 ccsdu2009 阅读(1921) 评论(1)  编辑 收藏 引用
Comments
  • # re: Loki技法3-Typelist(1)
    ccsdu2009
    Posted @ 2010-04-10 12:36
    TypeList是Loki工厂等其他几个模块的基础
    虽然这里还没有看出其实际的用途  回复  更多评论   

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理