C++ 模板系統圖靈完備,其本質屬於函數式程式設計範式:以「定義與替換」為核心,對應 Lambda 演算的變數替換規則。本文透過費氏數列編譯期計算範例,揭示模板元程式的函數式本質,並挑戰實作編譯期質數列印。
#include
template struct Fib {
static const int value = Fib::value + Fib::value;
};
template <> struct Fib<0> { static const int value = 0; };
template <> struct Fib<1> { static const int value = 1; };
template void PrintFib() {
PrintFib();
std::printf("%d\n", Fib::value);
}
template <> void PrintFib<0>() { std::printf("%d\n", Fib<0>::value); }
int main() { PrintFib<8>(); return 0; }
所有計算在編譯期完成,執行階段僅輸出結果。遞歸深度受編譯器模板實例化深度限制(通常 ~900 層)。
λx.λy.x+y → 定義函數、應用參數、β-歸約替換。template<int N> struct Fib → 定義;Fib<8>::value → 應用;編譯器實例化 → 替換/歸約。原版指數複雜度極慢,改用尾遞歸累積參數達 O(N):
template struct Fib {
static const int value = Fib::value + Fib::last;
static const int last = Fib::value;
};
template <> struct Fib<0> { static const int value = 0; };
template <> struct Fib<1> { static const int value = 1; static const int last = 0; };
1994 年 Unruh 利用編譯錯誤訊息輸出質數序列,震驚 C++ 標準委員會。嘗試實作一個模板,使編譯錯誤訊息包含質數列表(如 Prime<2>::value、Prime<3>::value...),致敬經典!