(1)计算整数的幂。
Pow<N,M>用来计算N的M次幂。实例化层次是Pow<N,M>,Pow<N,M-1>,...,Pow<N,0>,共M+1层。我们始终要记住编译器对模板元编程中的实例化层次是有限制的(否则会层次太深的话会耗尽编译器的可用资源),我测试出gcc 4.2.4最多只允许31层的实例化,因此这里如果使用Pow<2,31>,Pow<5,40>等,则编译不会通过。
(2)求整数的平方根(向上取整)。可以用二分查找算法来查找,也可以用普通的从0开始迭代的查找算法。
在模板元编程中,我们要尽量少用条件运算符?:来执行路径选择,因为这会导致两个分支中的递归模板都会被实例化,产生数量庞大的实例化体。例如使用sqrt1.hpp中注释掉的那句,当实例化Sqrt<N,LO,HI>时,会导致Sqrt<N,LO,mid-1>和Sqrt<N,mid,HI>的完全实例,这样最终的实例化个数大约是N的2倍。我们应该用模板特化来执行路径选择,例如我们使用前面类型萃取技术中介绍的IfThenElse<bool,T1,T2>模板。在它的特化中ResultT只返回其中一个类型(如T1),注意把T1类型typedef成ResultT并不会导致被实例化。当最终查找结果ResultT::resut时,就会实例化ResultT,可见这只实例化了一个IfThenElse中的一个分支。最终的实例化个数趋向于lg(N)。另外,在二分查找的实现中,返回是其中的一个分支类型,最后返回时应该是mid=HI时的Sqrt<N,mid,HI>,因此必须提供一个mid=HI的特化来结束Sqrt模板的递归,否则还会再去实例化Sqrt<N,mid,HI>。而在迭代查找的实现中,当I*I>=N时模板递归结束,这时返回Value<I>分支,用Value<I>::result直接返回计算出的结果,递归结束。因此不需要提供Sqrt的特化来结束递归。
(3)计算向量的点乘。
(4)判断一个数是否是素数。
(5)打印连续的素数。
总结出模板元编程的计算完整性:
1)状态变量:也就是模板参数
2)迭代构造(相当于循环语句):通过递归模板
3)路径选择(相当于条件语句):通过使用特化或条件表达式?:
4)整型对象(相当于变量):用enum定义的枚举值