《Modern C++ Design》Loki库源码读解随想
大牛Andrei Alexandrescu的《Modern C++ Design》讨论的是C++语言的最前沿研究:generative programming。本书中译版估计得要半年以后才能出来,所以只能靠其所附源码来窥测generative programming了。
目前,我刚将源码读解了约一半,等全部读完,我会将我的读解注释放出来的。现在,现谈一下我的感想。
先扯得远一点。C++有两个巨大优点:和C兼容,自由;有两个巨大缺点:和C兼容,复杂。C++极其复杂,很难掌握,而这正是“自由”的代价。C++语言是个多编程风格的语言,它同时支持过程化、基于对象、面向对象、泛型、生成性这5种编程思想,具有极其强大的表达能力,可以方便地将各种设计转化为实现。
generic Programming的思想精髓是基于接口编程(相对于OOP,连多态所需的基类都不要了),它的技术出发点是选择子,核心技术是:类型推导、类型萃取、特化/偏特化,其成果是STL库:一组通用容器和一组操作于通用容器上的通用算法。
generative programming的思想精髓是基于策略编程(编译器根据策略自动生成所需代码,由于具有更高的抽象性,所以代码复用度也更高),在Loki库的实现中,目前只使用了递归策略,它的技术出发点是Typelist,核心技术是:类型推导、类型萃取、特化/偏特化、多重继承、类型间去耦合,其成果是Loki库:对设计模式的封装。
Typelist是一种对类型本身进行存储和管理的技巧,它的源码已经贴过了,我也作了注解,此处不再谈论。
这是多重继承在COM之后的又一大型运用。多重继承极易发生菱型缺陷,所以Loki库使用了类型间去耦合技术来避免:
template <typename T>
struct Type2Type
{
typedef T OriginalType;
};
经过这样一层转换后,原类型T间的各种转换关系(尤其是继承/派生关系)已不复存在,菱型缺陷不会再发生了。
Loki库的具体实现相当讲究技巧,设计它非常困难(难度远大于STL库,和Boost库有得一拼啊)。但使用它却非常容易,而且便利显著。由于Loki库提供了对设计模式的封装,所以极大量地丰富了C++语言的表达能力,使的你的设计更容易地转化为实现。
目前,Loki库只提供了对厂模式和visitor模式的封装,它还处于发展初期。
我以visitor模式为例,讲解Loki库提供的便利。
Visitor模式有四种实现方式:1一串RTTI的类型判断;2二次调度(double dispatch);3建立类型与处理函数的对应表;4非循环visitor(Acyclic Visitor)。在《More Effective C++》 Item 31中讨论了前3种实现(虽然它的例子本身不太算visitor模式的)。第四种方式在《使用设计模式改善程序结构》(二)(http://www-900.ibm.com/developerWorks/cn/java/l-dpstruct/part2/index.shtml)中有详细讲解。
原型图
以这张原型图而言,用户需要自己实现大量的代码,而且,由于使用多重继承技术,在具体Host类间有继承关系时,它一定会发生问题。
Loki库实现图使用Loki库,用户实现visitor模式时只需:让Host类从BaseVisitable继承,并在所有派生类中加上DEFINE_VISITABLE()宏,让所有Visitor类从BaseVisitor类和VisitorImpl类进行二重继承(并且可以只提供对自己感兴趣的Host类的处理函数,不感兴趣的不提供处理函数)。用户的工作量非常小、非常简单,设计人员可以不用为实现而分心了。
更重要的是,由于采用了类型间去耦合技术,多个Host之间存在继承关系时,不会发生问题(其具体实现较复杂,于是我在UML图上作了模糊处理,没有展示出来,留在以后Loki库源码读解时讲述)。