Typelists

.2 定义Typelists

namespace TL  //而TL位于Loki名字空间
{
 template <class T, class U>
 struct Typelist
 {
  typedef T Head;
  typedef U Tail;
 };
}

Typelist的定义就是这些. 在使用的时候如一个整数类型的typelist为:

typedef Typelist<signed char,
  Typelist<short int,
   Typelist<int,
    Typelist<long int , NullType> > > >
 SignedIntegrals;  //整数类型的typelist

注意上边定义时, 最后一个类型是NullType, 这种安排是一种惯例, 就像'{fckeditor}'结束字符串一样.

不过, 上面这种定义Typelist时的写法一层套一层,太麻烦了.Loki在内部定义了一些宏做这件事:

#define TYPELIST_1(T1) Typelist<T1, NullType>
#define TYPELIST_2(T1, T2) Typelist<T1, Typelist<T2, NullType> >
#define TYPELIST_3(T1, T2, T3) //等等 Loki中一直写到 TYPELIST_50

借助这些宏, 我们把上边SignedIntegrals的定义可以写为:

typedef TYPELIST_4( signed char, short int, int, long int) SignedIntegrals;


3.4 计算长度

计算Typelist的长度的代码是通过template递归:

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

有了上边的Length, 在编译期计算 SignedIntegrals 的长度就可以写为:

Length<SignedIntegrals>::value ;


3.6 索引式访问

类似求list的第n个元素. 我们也可以用 TypeAt 取得Typelist的第n个元素:

template<class Head, class Tail>
struct TypeAt<Typelist<head, tail>, 0 > {
 typedef Head Result;
};

template<class Head, class Tail, unsigned int i>
struct TypeAt<Typelist<Head, Tail> , i> {
 typedef typename TypeAt<Tail, i-1>::Result Result;
};

例如取SignedIntegrals 的第三个类型用:
TypeAt<SignedIntegrals, 3>::Result
如果给出的数字超过了其长度.产生编译错误.如:TypeAt<SignedIntegrals, 5>::Result
//Loki库另外还实现了一个TypeAtNonStrict . 它和TypeAt功能类似. 但超过长度后返回
//NullType而不是产生编译错误.


3.7 查找Typelists

IndexOf可以计算Typelist内某类型的位置,若找不到返回-1;实现如下:

template <class Tlist, class T> struct IndexOf;

template <clss 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 };
public:
 enum { value = (temp == -1) ? -1 : 1+temp };
};


3.8 附加元素到Typelists

编译期的所有东西都是"常量", 是不可修改的. 这里是用Append附加后返回一个新的Typelist.
下边是Append的实现.可以用它来附加一个元素或一个Typelist到某一Typelist.

template<class Tlist, class T> struct Append;

template<> struct Append<NullType, NullType>{
 typedef NullType Result;
};

template<class T> struct Append<NullType, T>{
 typedef TYPELIST_1(T) Result;
};

template<class Head, class Tail>
struct Append<NullTYpe, Typelist<Head, Tail> > {
 typedef Typelist<Head, Tail> Result;
};

template<class Head, class Tail, class T>
struct Append<Typelist<Head, Tail>, T> {
 typedef Typelist<Head, typename Append<Tail, T>::Result> Result;
};

有了上边的Append. 现在要把float,double,long double附加到SignedIntegrals而
形成SignedTypes :

typedef Append<SignedIntegrals, TYPELIST_3(float, double, long double)>::Result
             SignedTypes; //新Typelist类型


3.9 移除Typelist中的某个元素

//可以用下边的Erase移除该元素的第一次出现. 实现如下:

template <class TList, class T> struct Erase;

template <class T>
struct Erase<NullType, T> {
 typedef NullType Result;
};

template <class T, class Tail>
struct Erase<Typelist<T,Tail>, T> {
 typedef Tail Result;
};

template <class Head, class Tail, class T>
struct Erase<Typelist<Head, Tail> T> {
 typedef Typelist<Head, typename Erase<Tail, T>::Result> Result;
};

用上边的Erase, 我们可以得到SignedTypes中除去float后的Typelist :
typedef Erase<SignedTypes, float>::Result  SomeSignedTypes;

//用Erase得到的是删除某类型的第一次出现. 用下边的EraseAll是删除它的所有出现:

template <class TList, class T> struct EraseAll;

template <class T>
struct EraseAll<NullType, T> {
 typedef NullType Result;
};

template <class T, class Tail>
struct EraseAll<Typelist<T, Tail>, T> {
 typedef typename EraseAll<Tail, T>::Result Result;
};

template <class Head, class Tail, class T>
struct EraseAll<Typelist<Head, Tail>, T> {
 typedef Typelist<Head, typename EraseAll<Tail, T>::Result>
                 Result;
};


3.10 移除重复元素

//用 NoDuplicates . 实现如下:

template <class TList> struct NoDuplicates;

template <> struct NoDuplicates<NullType> {
 teypdef NullType Result;
};

template <class Head, class Tail>
struct NoDuplicates< Typelist<Head, Tail> > {
private:
 typedef typename NoDuplicates<Tail>::Result L1;
 typedef typename Erase<L1, Head>::Result L2;
public:
 typedef Typelist<Head, L2> Result;
};  //真帅!!


3.11 替换Typelist中的某个元素

//用Replace . 实现代码如下:

template <class TList, class T, class U> struct Replace ;

template <class T, class U>
struct Replace<NullType, T, U> {
 typedef NullType Result;
};

template <class Tail, class T, class U>
struct Replace<Typelist<T, Tail> , T, U> {
 typedef Typelist<U, Tail> Result;
};

template <class Head, class Tail, class T, class U>
struct Replace<Typelist<Head, Tail>, T, U> {
 typedef Typelist<Head, typename Replace<Tail,T,U>::Result>
                 Result;
};


3.12 为Typelists局部更换次序

DerivedToFront //将派生类放在基类之前.

MostDerived  //传回在typelist中指定类Base的最终派生类(如果找不到则传回Base自己)
定义为:

template <class TList, class T> struct MostDerived;

template <class T>
struct MostDerived<NullType, T> {
 typedef T Result;
};

template <class Head, class Tail, class T>
struct MostDerived<Typelist<Head, Tail>, T> {
private:
 typedef typename MostDerived<Tail, T>::Result Candidate;
public:
 typedef typename Select< SUPERSUBCLASS(Candidate, Head),
                Head, Candidate>::Result Result;
};

然后用MostDerived来实现DerivedToFront

template<class T>struct DerivedToFront;

template<> struct DerivedToFront<NullType> {
 typedef NullType Result;
};

template <class Head , class Tail>
struct DerivedToFront<Typelist<Head, Tail> > {
private:
 typedef typename MostDerived<Tail, Head>::Result TheMostDerived;
 typedef typename Replace<Tail, TheMostDerived, Head>::Result L;
public:
 typedef Typelist<TheMostDerived, L> Result;  //这里如何递归没有看懂.
};


3.13 运用Typelists自动产生classes

运用template template parameters

3.13.1 产生"散乱的继承体系(scattered hierarchies)"

Loki中使用的是 GenScatterHierarchy . 它自动将typelist中的类型分发至客端代码.
实现如下:

template <class TList, template<class> class Unit>
class GenScatterHierarchy;

template <class T1, class T2, template<class> class Unit>
class GenScatterHierarchy<TYPELIST_2(T1, T2), Unit>
        : public GenScatterHierarchy<T1, Unit>
        , public GenScatterHierarchy<T2, Unit>
{ };

template <class AtomicType, template<class> class Unit>
class GenScatterNierarchy : public Unit<AtomicType> { };

template <template<class> class Unit>
class GenScatterHierarchy<NullType, Unit> {};

这样就自动产生了一些类. 其中包括将Typelist中的每个类型代入模板类Unit中.例如:

举一个例子:  有类模板
template <class T> struct Holder {
 T value_;
};

然后用
typedef GenScatterHierarchy< TYPELIST_3(int, string, Widget), Holder> W;
则 W 继承自 
GenScatterHierarchy<int> 和 GenScatterHierarchy<TYPELIST2(string,Widget)>
前者继承自Holder<int> 而后者继承自
GenScatterHierarchy<string> 和 GenScatterHierarchy<TYPELIST1(Widget)>
前者继承自Holder<string> 后者再继承自
GenScatterHierarchy<Widget> 和 GenScatterHierarchy<NullType>
前者继承自Holder<Widget>
 
可以看出这样就自动产生了 Holder<int> .  Holder<string> 等类型. 而W则是多继承和多重继承
后得到的复杂类型; 因为派生类的对象可以用基类的指针或引用来使用. 所以可以把每个 W 对象
当作 Holder<int>, Holder<string> , Holder<Widget> 类型的来使用. 每个W对象中也包含这些
类型的基类子对象. 例如要访问 W 对象的基类Holder<int>子对象的成员 value_ .可以:
W obj;
int x = (Holder<int>&) obj . value_ ;

这样的人工转换要是觉得麻烦. 这里有一个函数模板,会自动返回你希望的Holder<int>&. 如下
template<class T, class TList, template<class>class Unit>
Unit<T>& Field(GenScatterHierarchy<TList, Unit>& obj) {  //返回你希望的基类类型的引用
     return obj; 
}
它的参数接收的是像 W 这样多重继承后类型的对象. 返回的是对其的基类型的引用.使用如下:
int x = Field<int>(w).value_ ; //只要指定Field模板的第一个模板参数.其它的可以推演出.

当然. 如果合成 W 类时用的TypeList中有两个int .这个函数就不能用了. 因为有两份Holder<int>
基类的子对象. 它就不知道该返回对哪个的引用了. 但我们还有其它办法. Loli中提供了Field函数模板
的重载:
template<int i, class Tlist, template<class>class Unit>
Unit<TypeAt<Tlist, i>::Result>& Field ( GenScatterHierarchy<TList,Unit>& obj); //另一版本
这个函数模板的模板参数有个 int, 它指出我们想用在TList中第几个Type.
它的实现书上有. 我就不贴了. 它的使用也很简单如:
int x = Field<0>(obj).value_;
string s = Field<1>(obj).value_ ;


3.13.3 产生线性继承体系

前边的GenScatterHierarchy产生的是多继承的类. 多继承得到的类中保存多份虚函数指针. 对象体积
变大. 所以有时候需要用单继承的办法.

template <class TList, template<class AtomicType, class Base> class Unit,
              class Root = EmptyType>
class GenLinearHierarchy;

template <class T1, class T2, template<class, class> class Unit, class Root>
class GenLinearHierarchy<Typelist<T1, T2>, Unit , Root>
        : public Unit<T1, GenLinearHierarchy<T2, Unit, Root> > { };

template <class T, template<class, class> class Unit, class Root>
class GenLinearHierarchy<TYPELIST_1(T), Unit, Root>
        : public Unit<T, Root> { };

这样用GenLinearHierarchy产生的类就有线性继承体系.例如:

// 这个EventHandler类模板相当于上边的Unit. 需要两个模板参数.
template <class T, class Base> 
class EventHandler : public Base { //继承自第2个模板参数类型.
public :
 virtual void OnEvent(T& obj, int eventID);
};

typedef GenLinearHierarchy< TYPELIST_3(Window, Button, ScrollBar), EventHandler>
         MyEventHandler;
通过一系列单继承最终生成了 MyEventHandler.
它继承自 EventHandler<window,
            GenLinearHierarchy <TYPELIST_2(Button, ScrollBar), EventHandler> >
后者声明了一个纯虚函数 OnEvent(window&,int); 并继承自
EventHandler<Button, GenLinearHierarchy <TYPELIST_1(ScrollBar), EventHandler> >
后者声明了一个纯虚函数 OnEvent(Button&,int); 并继承自
EventHandler<Button,EmptyType>
后者声明了一个纯虚函数 OnEvent(ScrollBar&,int); 并继承自 EmptyType.
EmptyType是一个有类的定义,但类体内没什么的东西(而NullType则是没有被定义的类).

这样最终的MyEventHandler类中就有3个虚函数OnEvent. 不过由于派生类中声明的OnEvent()和
基类中的版本不同. 这会隐藏基类中的OnEvent版本. 所以你不能直接通过MyEventHandler对象去
调用基类中的OnEvent(ScrollBar&, int)这个版本的函数. 而要先将其转换为基类类型的引用. 方
便的是Loki中提供了 Field 函数模板.它在讲前边的GenScatterHierarchy时出现过. 这里的其实
是一个另一版的重载的函数模板.

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值