元函数:编译期的函数
Metafunction: compile-time analogs of runtime functions
与运行期使用函数封装算法相对应,在C++编译期同样存在着封装算法进行编译期计算的需要。元函数(metafunction)便是实现这一需求的主要手段。元函数这一概念最早是由Boost.MPL类库提出并定义的。
作为在编译期进行计算的函数,元函数具有以下不同于运行期函数的特点:
- 输入(即参数)与输出(即返回值)均只包含两种类型:1)类型(名)2)整形常量。
- 可以返回一个或多个值,但不能没有返回值。
- 没有副作用:元函数在计算过程中既不能改变参数的值,也不具备“向控制台输入输出”之类的附加功能。
元函数的分类
Kinds of Metafunction
按照返回值的类型来划分,元函数可分为以下两大类:
- type型元函数:返回类型(名)的元函数,也就是在编译期进行类型计算的元函数。
示例代码1: 示例代码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。 - value型元函数:返回整形常量的元函数,也就是在编译期进行常量计算的元函数。
示例代码2:示例代码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: 示例代码3(取自Boost.MPL类库)实现了一个布尔常量的包装器。
元函数bool_共有3个返回值。
1) 布尔值value。
2) 元函数自身的类型type。
3) 布尔值value的类型value_type。
根据元函数bool_的定义,不难推出以下等式为真。
1) false_::value == false。
2) true_::type::value == true。
示例代码3: 示例代码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:
示例代码4:
“成员”元函数
Member Metafunction
元函数也可在类或类模板中定义,即元函数通过嵌套类的方式来实现。
这种元函数可称作“成员”元函数,也可称作“元方法”。
示例代码5: 在示例代码5(取自Boost.Pheonix类库)中,类模板value总共定义了2个元方法。
1) value型元方法no_nullary。
这里no_nullary被定义为false_的同义词,false_的定义可参见示例代码3。
2) type型元方法result。
示例代码5: 在示例代码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
编译期“元函数” | 运行期“函数” | |
是否允许返回多值 | 是 | 否 |
是否允许不返回值 | 否 | 是 |
是否存在副作用 | 否 | 是 |
是否允许零参数 | 是 | 是 |
能否作为类成员 | 是 | 是 |
是否存在高阶函数 | 是 | 是 |