C++11 模板元編程 - 模板遞歸


模板可以被遞歸調用,在模板遞歸的過程中,可以執行前面我們提到的兩種編譯期計算:數值計算和類型計算。

下面我們用模板遞歸來做數值計算,在編譯期計算N的階乘。

template<int N>
struct Factorial
{
    enum { Value = N * Factorial<N - 1>::Value };
};

template<>
struct Factorial<1>
{
    enum { Value = 1 };
};

可以看到,我們在主模板template<int N> struct Factorial的定義中,使用了模板自身Factorial<N - 1>::Value。編譯器會一直用不同的N - 1的值來具現化主模板,一直到N變為1,這時選擇Factorial的特化版本template<> struct Factorial<1>,內部的Value變為1,遞歸終止了。

我們可以在編譯期運行這個函數__print(Factorial<5>::Value),可以看到編譯器會打印出120。

對于上面的例子,我們看到是通過模板特化來終止遞歸的。事實上我們對比一下Haskell語言中計算階乘的函數實現:

factorial :: Int -> Int
factorial n = n * factorial (n - 1)
factorial 1 = 1

Haskell是一門純函數式語言,它通過模式匹配進行條件選擇,通過遞歸來進行循環控制。對于上面的factorial定義,當入參是1的時候模式匹配會選擇到factorial 1 = 1實現,否則匹配到factorial n = n * factorial (n - 1)的遞歸實現。

可以看到上面我們使用C++模板的方式和Haskell中定義函數是如此的類似。編譯器對模板的特化版本選擇就相當是Haskell在做模式匹配,而兩者的循環控制都是通過遞歸來完成。已經證明模板的這種編譯時計算能力就是一種純函數式編程范式,是圖靈完備的!

不同的是,C++這種編譯期計算支持的計算對象只能是整形常量和類型。

C++這種編譯期函數式計算就是本文要介紹的C++模板元編程,類模板在里面充當了函數的角色。本文用到的關于類模板所有知識基本就是前文所述這些。后面我們將會對類模板進行規范化,讓其能夠和函數式計算更加地一致,最大程度發揮編譯期函數式計算的威力。


關于模板的基本知識就介紹這里,我們接下來正式介紹所謂的“模板元編程”!

模板元編程

返回 C++11模板元編程 - 目錄

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容