更多 C++ 習語/元函式
- 封裝複雜的型別計算演算法
- 使用編譯時型別選擇技術生成型別
模板是 C++ 的一個強大功能,它可以用於在編譯時執行任意計算,這被稱為模板超程式設計。編譯時執行的一些基本計算示例包括:(1)根據編譯時常量選擇型別,或(2)計算數字的階乘。事實上,C++ 模板是 C++ 的圖靈完備子語言。元函式習語是編寫 C++ 編譯時演算法的主要方式。
演算法 - 編譯時或執行時 - 應該被封裝,以使其更容易使用和重用。按照慣例,執行時演算法被封裝在函式中,這些函式在執行時被呼叫。另一方面,元函式是執行時函式的編譯時模擬。傳統的函式接受值/物件作為引數並返回值/物件。但是,元函式接受型別和編譯時常量作為引數並返回型別/常量。
元函式,與其名稱相反,是一個類模板。元函式的實現通常基於模板特化。例如,考慮以下IF元函式,它是執行時if語句的編譯時等效項。根據第一個引數的值,IF元函式在下面的示例中產生一個int或一個long。
template <bool, class L, class R>
struct IF
{
typedef R type;
};
template <class L, class R>
struct IF<true, L, R>
{
typedef L type;
};
IF<false, int, long>::type i; // is equivalent to long i;
IF<true, int, long>::type i; // is equivalent to int i;
下面的Factorial元函式是另一個示例,展示瞭如何使用 C++ 模板封裝遞迴階乘計算演算法。此元函式產生一個整數值,而不是一個型別。
template <int N>
struct Factorial
{
enum { value = N * Factorial<N - 1>::value };
};
template <>
struct Factorial<0>
{
enum { value = 1 };
};
// Factorial<4>::value == 24
// Factorial<0>::value == 1
void foo()
{
int x = Factorial<4>::value; // == 24
int y = Factorial<0>::value; // == 1
}
元函式和型別生成器
元函式比型別生成器習語更通用的習語。元函式習語的目的是封裝編譯時計算,而型別生成器簡化了型別的規範。生成型別作為編譯時計算結果的元函式是型別生成器,但並非所有元函式都是型別生成器。例如,之前顯示的Factorial元函式產生一個整數值,而不是一個型別。元函式通常使用編譯時控制結構或其他元函式來實現。
諸如Boost.MPL之類的庫提供大量元函式和編譯時資料結構,以簡化 C++ 模板超程式設計。
高階元函式
這些是接受其他元函式作為引數並在計算期間使用它們的元函式。這在概念上類似於在執行時接受指向另一個函式的指標或函式物件的函式。唯一的區別是元函式只存在於編譯時。boost::mpl::transform是這種高階元函式的一個例子。
深入瞭解元函式 - David Abrahams 和 Aleksey Gurtovoy