模版编程 在编译期完成递归工作

斐波那契数
  斐波那契数形如:0,1,1,2,3,5,8,13.....。该序列的通用方程式:Fib(n)=Fib(n-1)+Fib(n-2),递归生成斐波那契数的典型函数如下:
  unsigned RecursiveFib( unsigned n)
  {
    if(n<=1)
    return n;
   return RecursiveFib(n-1)+RecursiveFib(n-2);
  }
  这个程序的时间复杂度是指数级的,它非常低下,根本不能应用于产品中。

 


  但是距离模板化版本只有一步之遥。 
template< unsigned N> struct Fib
{
    enum
    {
     //递归定义
     Val=Fib< N-1 >::Val+Fib <N-2>:Val
    };
};
//模板特化,结束条件
template <> struct Fib <0> { enum { Val=0}; };
template <> struct Fib <1> { enum { Val=1}; };

 

//让该模板形如函数
#define FibT( N ) Fib< n >::Val
通过#define“调用”此模板:
std::cout<< FibT( 4 );   //Fib< 4 >::Val
此模板化版本有几个注意点:
   1.此模板数不是真正的函数-----它是叫做Val的枚举类型,在编译期递归生成,
       Val=Fib< N-1 >::Val+Fib< N-2 >::Val并不常见,但是合法。
   2.模板参数N用于指定函数的输入,并不常见,但完全可行。
   3.要终止递归,需要正确处理结束条件,对斐波那契数来说,结束条件是N为0和1时,
        本模板中使用的是模板特化

   4.如果当i还是可变的变量时调用FibT(i),将会产生编译错误。
=Fib< 4 >::Val
=Fib< 3 >::Val + Fib< 2 >::Val
=Fib< 2 >::Val +Fib< 1>::Val + Fib< 1 >::Val + Fib< 0 >::Val
=Fib< 1>::Val + Fib< 0 >::Val + 1+1+0
=1+0+1+1+0
=3
由于所有的输入在编译器都确定了,所以编译程序可以将Fib< N >换算成常数。
std::cout<< FibT( 4 );//与3完全等价 
        该方法可以成为你C++工具包中的有用工具,你很可能会有指数级运行时间不能降为零的情况,通过使用模板元编程,就可以通过增加额外的编译时间来减少执行时间。
 
posted @ 2012-06-04 14:06  Velx  阅读(219)  评论(0编辑  收藏  举报