初探模板元编程

来看一个小例子:

#include<iostream>
template<long num>
struct Fibonacci
{
	static const long val = Fibonacci<num - 1>::val + Fibonacci<num - 2>::val;
};

template<> struct Fibonacci<2> { static const long val = 1; };
template<> struct Fibonacci<1> { static const long val = 1; };
template<> struct Fibonacci<0> { static const long val = 0; };

int main()
{
	int i=Fibonacci<10>::val
	std::cout<<i;
}

上面程序的输出结果正是斐波那契数列第11个项。与通常的程序不同之处在于,它的结果是在编译时计算出来的。对此我们可以查看反汇编:

可见运行时直接使用的是37h即55这个值。

下面我们来分析一下。
首先定义了一个非类型参数的模板Fibonacci,该模板类定义了一个静态变量val,而val被递归地定义为特化num=num-1和num-2的类中val之和。
所以,val = Fibonacci<num - 1>::val + Fibonacci<num - 2>::val
Fibonacci<num - 1>::val又被递归定义为val = Fibonacci<num - 2>::val + Fibonacci<num - 3>::val,同理Fibonacci<num - 2>::val被递归定义为Fibonacci<num - 3>::val+Fibonacci<num - 4>::val
既然是递归,就必须有边界条件作为递归的终点。
所以我们特化当num=0,1,2时val的值为确定的0,1,1。

template<> struct Fibonacci<2> { static const long val = 1; };
template<> struct Fibonacci<1> { static const long val = 1; };
template<> struct Fibonacci<0> { static const long val = 0; };

因为模板是在编译时被推导展开的,所以Fibonacci数列的值也就在编译时被计算出来了。

再举一个阶乘的小例子:

#include<iostream>
template<long num>
struct Factorial
{
	static const long val = num*Factorial<num - 1>::val;
};

template<> struct Factorial<1> { static const long val = 1; };

int main()
{
	int fib = Factorial<10>::val;
	std::cout << fib;
}

思路完全相同,这里就不再赘述。

ps:template元编程是图灵完备的,也就是说,任何程序中需要表达的计算,都可以采用这种方式表达。

原文地址:https://www.cnblogs.com/cknightx/p/7821068.html