现在的位置: 首页 > 综合 > 正文

模板元编程递归解析

2018年02月08日 ⁄ 综合 ⁄ 共 2694字 ⁄ 字号 评论关闭
关于术语的问题:
 演绎,推导,演推,我也不知道哪个准确,反正就是这个意思

template<int  i>
class A
{
public:
	static const int a = 3 *  A< i - 2>::a *  A<i -1>::a;

};
template<>
class A<2>
{
public:
	static const int a = 2;
};
template<>
class A<1>
{
public:
	static const int a = 1;
};
cout<<A<6>::a<<endl; //请问输出什么 

这个稍微有些复杂. 先来看个简单的:

示例1:
template<int i>
class A
{
public:
	static const int a = 5 ; // 实例化 a = 5;
}

cout<<A<6>::a<<endl; //请问输出什么 

当然是 5 了


示例2:
template<int i>
class A
{
public:
	static const int a  ;
};

template<int a>
const int A<a>::a =7; // 实例化 a = 7;


cout<<A<6>::a<<endl; //请问输出什么 

当然是 7 了

示例3:

template<int i>
class A
{
public:
	static const int a  = i ;
};

cout<<A<6>::a<<endl;
cout<<A<7>::a<<endl; 

输出: 
6
7
因为它用这里的常数来 实例化了类模板中的a; 静态常量.


示例4:
template<int i>
class A
{
public:
	static const int a  = A<i >::a;
};

cout<<A<6>::a<<endl; //输出什么?

答: 编译不过,为什么?因为 A<i> 这里应该是常量表达式 例如: A<i-1>, A<i+1>, A<i+2>...... ,
为什么要为样做呢, 看了下面的或许你就懂了.



示例5:
template<int i>
class A
{
public:
	static const int a  = A<i -1 >::a;//注意这里的-1 , 这个表达式有点像递归
}; 
template<>//这个是什么? 这个是递归结束条件 也就是所谓的特化,如果不写			//会导致编译器死掉的,因为它会死循环.
class A<1>
{
public:
	static const int a = 1;
};
cout<<A<6>::a<<endl; //输出什么?
输出
1

哪 
cout<<A<10>::a<<endl; //输出什么?
还是
1
为什么呢,因为在编译的时候编译器要初始化a ,例如:
cout<<A<6>::a<<endl;
它就从6开始把6带到模板中我们模拟一下它的过程

第一次:
template<6>
class A
{
public:
	static const int a  = A<6 -1 >::a; // 6-1 = 5
//A<5> 也就是这样的,
}; 
发现没有A<5> 这样的特化模板,然后呢,怎么办呢?, 我们这里不是有个-1吗, 它就会减1, 减1 后就变成了5 继续演绎它.
第二次
template<5>
class A
{
public:
	static const int a  = A<5 -1 >::a; // 5-1 = 4
//A<4> 也就是这样的,
};

第三次
A<4>
第四次
A<3>
第五次
A<2>
第六次
A<1>
好了 这次终于找到组织了,A<1>, 还记得我们写的特化模板吗,
template<>
class A<1>
{
public:
	static const int a = 1;
};

找到了, 哇塞 找到了耶, 是1, 所以它就以1来实例化它

示例6:
如果 
static const int a  = A<i -1 >::a;
改为
static const int a  = A<i -2 >::a;

cout<<A<6>::a<<endl;

模板是不是还是从6开始演绎呢? 是的 但不是 
6 5 4 3 2 1
而是
6 4 2 0 -2 -4..... 这样的,因为这里是-2 .如果找不到终止的偏特化模板它就会死掉


哪如果 + 2呢
6 8 10 12....
哪如果是 * 2呢
6 12 24 48 ......

总之一句话:
static const int a  = A<i -2 >::a;
这里的表达式是什么它就,怎么演推



示例7:

template<int i>
class A
{
public:
	static const int a  = 3 * A<i -1>::a;
};

template<>
class A<1>
{
public:
	static const int a = 1;
};

cout<<A<6>::a<<endl;

这里又会输出什么
243 
为什么


其实我们说应该先确定终止条件,终止条件是1 ,那就是当i = 2的时候就能满足这个条件:

当i是2的时候:
template<2>
class A
{
public:
	static const int a  = 3 * A<2 -1>::a; // A<1> 所以这里的 a = 3
};

这个知道了 其它的就好办了.

其它的就是一共多少次了倒着往上把下一层的值 一直 *3

红色为当模板实参值为: 

6 81*3 = 243
5 27*3 = 81
4 9*3 = 27
3 3 *3 =9
2 1 * 3 = 3 // 当模板实参为2 时 模板表达式 2-1 = 1 达到了终止条件. 确定了 a的值 为 1


示例 8



template<int  i>
class A
{
public:
	static const int a = A< i - 2>::a  +  A<i -1>::a;

};
template<>
class A<1>
{
public:
	static const int a = 1;
};
template<>
class A<2>
{
public:
	static const int a = 2;
};

	cout<<A<6>::a<<endl;//

输出: 13
递归如下:

 

(6)=f(5)+f(4); = 8 + 5

f(5)=f(4)+f(3); = 5 +3

f(4)=f(3)+f(2); = 3 + 2

f(3)=f(2)+f(1) = 2 + 1= 3



如果把上题变一下

 template<int  i>  struct B {	  static const int a = B< i - 2>::a  +  B<i-3>::a;  };
  template<>  struct B<2>  { 	  static const int a = 2;  };
  template<>  struct B<1>  {    static const int a = 1;  };
  template<>  struct B<0>  {    static const int a = 0;  };

cout<<B<10>::a<<endl; //输出 13

注: f 后面的数字加上一个括号 我省略了 f(10) = f10

f10= f8 +f7 = 7 +6
f8= f6+f5 = 4 +3 =7
f7= f5 +f4 = 3 + 3 = 6
f6 = f4+f3 = 3 +1 = 4
f5 = f3+f2 =  1 + 2 =3
f4 = f2+f1 = 3
f3 = f1+f0 = 1+0 =1

规律就是

f(n) = f(表达式一) 运算符 f(表达式二) ...

f(表达式一) = ...

f(表达式二) = ...

不断的分解未知表达式


鸣谢 :群里的大牛们的帮助.



【上篇】
【下篇】

抱歉!评论已关闭.