函数式语言依赖模式匹配和递归完成类似命令式语言里分支选择和循环迭代的功能。模板元编程中可以完成模式匹配的两种方式上节已经介绍。本节介绍模板元编程中的递归。
前面在介绍编译期数值计算的整数阶乘的例子时,就已经展示了使用类模板进行递归计算的一般做法。这里再补充一点就是C++11支持了变长模板参数,而模板的变长参数也必须是要通过递归进行参数展开的。
如下,我们实现一个可以对任意个IntType进行求和的元函数Sum:
// "tlp/int/algo/Sum.h"
template<typename ...Numbers> struct Sum;
template<typename Number, typename ...LeftNumbers>
struct Sum<Number, LeftNumbers...>
{
using Result = typename Add<Number, typename Sum<LeftNumbers...>::Result>::Result;
};
template<> struct Sum<>
{
using Result = IntType<0>;
};
#define __sum(...) typename Sum<__VA_ARGS__>::Result
在上面代码中,元函数Sum的原型是template<typename ...Numbers> struct Sum
,它的参数是变长的typename ...Numbers
。如果参数个数为0,则选择特化版本template<> struct Sum<>
,这时结果为IntType<0>
;否则递归展开参数,用当前参数和剩余参数的总和进行相加using Result = typename Add<Number, typename Sum<LeftNumbers...>::Result>::Result
。注意声明变长参数时...
在参数名前面,而对其使用时...
在参数名后面。
该元函数的使用如下:
__sum(); // 返回 IntType<0>
__sum(__int(1), __int(2), __int(5)); // 返回 IntType<8>