c++模版的应用是可以分类的。按照用途,可以分为:
1)工程模版
2)算法和数据结构的解耦
3)工作于编译期的模版
4)XX的封装
5)适配器模式
首先解释一下,这里的划分属于较高层的应用划分,但这些应用都是基于模版的一些共同特性的,比如带默认参数、特化和偏特化等。
分别解释一下就是:
(1)工程模版:《c++模版的一些使用方法(一)》中提到修改第三方库的应用属于这一类。工程模版主要是在大工程中的一些处理手法,不太好说。
(2)算法和数据结构的解耦就很清晰了,比如stl库,find算法既可以用于vector也可以用于list。再比如经常使用的单件模式,将它声明为几类,任何需要是单件模式的类只要从这个基类派生即可获得单件属性
template<typename T>
class Singleton
{
protected:
Singleton(){}
public:
static T& GetInstance()
{
static T Instance;
return Instance;
}
};
class MyClass:public Singleton<MyClass>
{};
由代码到可执行文件分为几个阶段:
No.1预处理阶段:处理#define,#ifdef,#include等预处理指令。它使在编译之前提供了一次修改源文件的机会,具有很大的灵活性。
No.2编译期:将源代码编成机器码,每个模块生成obj文件,
No.3链接器:将n个obj文件组合在一起,解析他们之间的交叉关系,得到可执行文件。
平时我们所说的执行效率,是指可执行文件处理一组数据的效率,可能还听说过在程序设计比赛中可以利用预处理来做一些事情,以此减少程序处理数据的时间,那么同样,有些事情是可以在编译期做的,同样可以通过把一些事情提前到编译期来提高程序的效率。
首先要明白哪些工作可以在编译期做:
No.1当有函数重载时,编译器在编译期决定调用哪个函数;
No.2sizeof操作符,typedef操作符,+ - = < > :?等运算符,等等等
No.3enum类型的赋值
No.4模版的特化、偏特化和实例化
那么,可以在编译期做哪些事呢?
我总结的有两点:
1)计算一些数据
2)生成代码
计算数据时,比如,可以这样计算Fibonacci数列:
template<int N>
struct Fibonacci
{
enum
{
result = Fibonacci<N-1>::result+Fibonacci<N-2>::result
};
};
template<>
struct Fibonacci<1>
{
enum
{
result =1
};
};
template<>
struct Fibonacci<0>
{
enum
{
result =0
};
};
int main()
{
time_t t1=time(NULL);
printf("%d\n",Fibonacci<40>::result);
time_t t2=time(NULL);
printf("UseTime:%d\n",t2-t1);
return 1;
};
首先定义了一个模版,还有它的两个特化(针对1和0),接着调用Fiboncaai<40>::result,则编译器在编译时会尝试给模版中enum::result赋值,赋的是它后面那个表达式,而后面的表达式是一个另外两个模版的实例化,这同样也发生在编译期,所以编译器会继续跟下去,一直跟到Fiboncaai<1>::result+Fiboncaai<0>,然后编译器发现针对1和0是有模版特化的,于是它去调用特化,特化中定义了出口,于是赋值结束。可以将其理解为类递归,但不同的是,真正意义的递归是函数的嵌套调用本身,时间复杂度很高,而这里,由于在编译器,每次“递归”实质上是模版的实例化,而出口是模版的特化,所以不存在任何的函数嵌套调用。
上面Fiboncaai<40>输出的结果是102334155,反汇编看一下,如图:
编译器经过计算,直接在这里放了一个立即数,译成十进制正是102334155。
而上面代码中所消耗的时间是0。如图
而经过测试,用普通的函数递归计算Fiboncaai的第40个,需要8秒的时间。
用于生成代码时,也可以成为模版的元编程,元编程是指某类计算机程序的编写,这类计算机程序编写或者操纵其他程序(或者自身)作为它们的数据,或者在编译时完成部分本应在运行时完成的工作。很多情况下比手工编写全部代码相比工作效率更高。编写元程序的语言称之为元语言,被操作的语言称之为目标语言。一门语言同时也是自身的元语言的能力称之为反射。
由上面的定义可知,元编程也是工作在编译期,其实上面的计算数据的应用,也可以归为元编程,因为编译器不断的实例化模版来“递归”,本质上也是在帮我们生成代码。Loki库中的Typelist就是使用模版元编程的经典之作。
XX的封装和适配器模式以后再说吧