.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时出现过. 这里的其实
是一个另一版的重载的函数模板.