C++/元函數

維基教科書,自由的教學讀本
< C++

元函數
[編輯]

定義[編輯]

元函數(metafunction)在編譯時利用類模板,輸入參數為類型或者編譯期常量(一般要求為整型),返回類型或常量。 注意這一定義不包含constexpr函數。

元函數這一概念最早是由Boost.MPL類庫提出並定義的。

作為在編譯期進行計算的函數,元函數具有以下不同於運行期函數的特點:

  • 輸入(即參數)與輸出(即返回值)均只包含兩種類型:1)類型(名)2)整形常量。
  • 可以返回一個或多個值,但不能沒有返回值。
  • 沒有副作用:元函數在計算過程中既不能改變參數的值,也不具備「向控制台輸入輸出」之類的附加功能。

動機[編輯]

元函數的實現[編輯]

元函數是用類模板實現,並常使用模板特化技術。

分類[編輯]

按照返回值的類型來劃分,元函數可分為以下兩大類:

type型元函數:返回類型(名)的元函數,也就是在編譯期進行類型計算的元函數。例如,下述IF類模板,根據第一個模板參數的值,返回第二個或第三個模板參數。這類似於運行時的if語句:

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;

value型元函數:返回整形常量的元函數,也就是在編譯期進行常量計算的元函數。例如,Factorial元函數是遞歸計算階乘,返回的最終結果為常量(應該是靜態數據成員或者枚舉類型的值):

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
}


與運行期的函數有所不同,編譯期所定義的元函數也可返回不止一個值。即"Multiple returns"(返回多值的元函數)。例如,Boost.MPL類庫中的Integral Constant Wrapper(整形常量包裝器)就屬於這種返回多個類型名及整形常量的元函數:

    template< bool x > struct bool_
    {
        static bool const value = x;        
        typedef bool_<x> type;              
        typedef bool value_type;            
        operator bool() const { return x; } 
    };
     
    typedef bool_<false> false_;
    typedef bool_<true> true_;

元函數也可不用類模板而用普通的類來定義,此時元函數的參數個數為0,即元函數沒有輸入只有輸出。即Nullary Metafunction(零參數元函數)。例如:

    struct always_int
    {
        typedef int type;
    };

用例[編輯]

Boost.MPL

參考文獻[編輯]

A Deeper Look at Metafunctions -- David Abrahams and Aleksey Gurtovoy