1. 簡介

  自從 C++ 編譯器加入 template 泛型功能後,就替傳統的 C++ 語言帶入新的革命。C++ 語言不僅是 C 包含物件導向功能,更增加了型態通用。後來的 C++ 編譯器 為了 執行時期的效率,在template 泛型內限定計算變數型態。如此更增加編譯時期的判斷及執行時期效率。

相關的簡介可參考以下網站:
https://riptutorial.com/cplusplus/topic/462/metaprogramming

2. 練習:將 Fibonacci 數列改寫成 meta programming

  傳統的 C 語言寫出Fibonacci 數列
long fib(int n)
{
  if((n == 0) || (n == 1))
     return 1;
  else
     return fib(n-1) + fib(n-2) ;
}

利用 template 改寫成:

template<T>
long fib(T n)
{
  if((n == 0) || (n == 1))
     return 1;
  else
     return fib(n-1) + fib(n-2) ;
}

利用 meta programming 在 compiling time


template<long N>
struct Fib
{
    enum{ value =  Fib <N - 2>::value  + Fib <N - 1>::value };  //  
};

template<>
struct Fib<1>
{
    enum { value = 1 };
};

然後在 main() 呼叫
cout << "Fib<5>::value = " << Fib<7>::value << endl;

經過編譯,出錯了
00_compilError.png

編譯器說內容太複雜,到網路上找資料
說是 終止條件沒給
01_net_explain.png

但是上面都給了終止條件。仔細思考一下,
Fib(n-1)+Fib(n-2)
Fib(1) 有,Fib(0) 卻沒有
再加上 Fib(0)


template<>
struct Fib<0>
{
    enum { value = 1 };
};

呼叫時採用 Fib<7>::value 

這樣就通過編譯了,也順利執行

02.png

 

3. C++ 2011

#include <type_traits>
#include <iostream>

template<long long n>
struct Fib_c11 :
    std::integral_constant<long long, (Fib_c11 <n - 1>::value) + (Fib_c11 <n - 2>::value) > {};

template<>
struct Fib_c11<0> :
    std::integral_constant<long long, 1> {};

template<>
struct Fib_c11<1> :
    std::integral_constant<long long, 1> {};

4. C++ 2014 版
 新加入 constexpr 關鍵字

constexpr long long Fib_c14(long long n)
{
    if (n == 0 || n == 1)
        return 1;
    else
        return Fib_c14(n - 1) + Fib_c14(n - 2);
}

呼叫時採用  Fib_c14(7) 不需要 ::value