C++惯用法:metafunction(元函数)

 

元函数:编译期的函数

Metafunction: compile-time analogs of runtime functions

 
与运行期使用函数封装算法相对应,在C++编译期同样存在着封装算法进行编译期计算的需要。元函数(metafunction)便是实现这一需求的主要手段。元函数这一概念最早是由Boost.MPL类库提出并定义的。
 
作为在编译期进行计算的函数,元函数具有以下不同于运行期函数的特点:
  1. 输入(即参数)与输出(即返回值)均只包含两种类型:1)类型(名)2)整形常量。
  2. 可以返回一个或多个值,但不能没有返回值。
  3. 没有副作用:元函数在计算过程中既不能改变参数的值,也不具备“向控制台输入输出”之类的附加功能。
 

元函数的分类

Kinds of Metafunction

 
按照返回值的类型来划分,元函数可分为以下两大类:
  1. type型元函数:返回类型(名)的元函数,也就是在编译期进行类型计算的元函数。
    示例代码1:template <bool B, 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; 示例代码1定义了一个用于编译期类型选择的元函数IF,其实现依赖于类模板IF及其特化。
    元函数IF的输入由3个模板参数构成:布尔类型B,类型名L,类型名R。
    元函数IF的输出也就是需要返回的类型由typedef语句来定义,用于返回的类型名为type。
    此处用于返回的类型名取名为type是为了遵循Boost.MPL类库的惯例。
    若B的值为true,则元函数IF返回类型名L。(此分支由模板特化来定义)
    若B的值为false,则元函数IF返回类型名R。(此分支由主模板来定义)
    此处用struct关键字而不是class关键字来定义类模板的理由是:元函数IF的返回类型必须能被外界所访问,即type的访问权限必须是public。
  2. value型元函数:返回整形常量的元函数,也就是在编译期进行常量计算的元函数。
    示例代码2:template <int N> struct Factorial { enum { value = N * Factorial<N - 1>::value }; //static const int value = N * Factorial<N - 1>::value; }; template <> struct Factorial<0> { enum { value = 1 }; //static const int value = 1; }; // Factorial<4>::value == 24 // Factorial<0>::value == 1 void foo() { int x = Factorial<4>::value; // == 24 int y = Factorial<0>::value; // == 1 } 示例代码2定义了一个用于编译期计算阶乘的元函数Factorial,其实现依赖于类模板Factorial及其特化。
    元函数Factorial的输入仅由1个模板参数构成:整数类型N。
    元函数Factorial的输出也就是需要返回的整形常量由枚举或静态整形常量来定义,用于返回的常量名为value。
    此处用于返回的常量名取名为value是为了遵循Boost.MPL类库的惯例。
    若N的值为0,则元函数Factorial返回1。(此分支由模板特化来定义)
    若N的值大于0,则元函数Factorial返回N*Factorial(N-1)。(此分支由主模板来定义)
    此处用struct关键字而不是class关键字来定义类模板的理由是:元函数Factorial的返回值必须能被外界所访问,即value的访问权限必须是public。
 

返回多值的元函数

Metafunction with "Multiple returns"

 
与运行期的函数有所不同,编译期所定义的元函数也可返回不止一个值。
Boost.MPL类库中的Integral Constant Wrapper(整形常量包装器)就属于这种返回多个类型名及整形常量的元函数。
示例代码3: 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_; 示例代码3(取自Boost.MPL类库)实现了一个布尔常量的包装器。
元函数bool_共有3个返回值。
1) 布尔值value。
2) 元函数自身的类型type。
3) 布尔值value的类型value_type。
根据元函数bool_的定义,不难推出以下等式为真。
1) false_::value == false。
2) true_::type::value == true。
 

零参数元函数

Nullary Metafunction

 
元函数也可不用类模板而用普通的类来定义,此时元函数的参数个数为0,即元函数没有输入只有输出。
示例代码4: struct always_int { typedef int type; };
 

“成员”元函数

Member Metafunction

 
元函数也可在类或类模板中定义,即元函数通过嵌套类的方式来实现。
这种元函数可称作“成员”元函数,也可称作“元方法”。
示例代码5: template <typename T> struct value { BOOST_STATIC_ASSERT( mpl::not_<is_reference<T> >::value != 0); typedef mpl::false_ no_nullary; template <typename Env> struct result { typedef T type; }; value(T const& arg) : val(arg) {} template <typename Env> T const& eval(Env const&) const { return val; } T val; }; 在示例代码5(取自Boost.Pheonix类库)中,类模板value总共定义了2个元方法。
1) value型元方法no_nullary。
   这里no_nullary被定义为false_的同义词,false_的定义可参见示例代码3。
2) type型元方法result。
 

高阶元函数

Higher-order Metafunction

 
元函数的参数也可以是另一个元函数,这种元函数被称作高阶元函数。Boost.MPL类库中的transform就属于高阶元函数。
 

元函数 vs 函数

Metafunction vs Function

 
  编译期“元函数” 运行期“函数”
是否允许返回多值
是否允许不返回值
是否存在副作用
是否允许零参数
能否作为类成员
是否存在高阶函数

你可能感兴趣的:(C++,算法,struct,function,Class,wrapper)