书籍《C++ template metaprogramming》讲述了现在C++中功能强大的惯用法。Metaprogram是用来生成和操作程序的代码。自从泛型编程引入C++,程序员们在编译的时候使用了大量的模板技巧(template tricks)。本文是在阅读《C++ template metaprogramming》之后step by step介绍了MetaProgramming的基础概念,做为范型编程的入门基础。
Metaprogramming的定义
什么是Metaprogramming
一个数值运算的例子
根据模板在编译时候的推导能力以及特化实现迭代运算。
使用运行期的方法实现:
那么区分编译期计算和运行期计算的两个区别:
终止条件不同
编译器不能有变量
对于metaprogramming 的定义:关于类型的计算。
为什么要进行Metaprogamming
相对于编译器的运算可选的方案有两个:运行期计算和用户分析。
对于运行期计算,编译期有两优点,一是相对运行期可以获得更块的速度;二是可以和目标语言比较深层的交互。相对用户分析,编译器的优点有三个:一是方便,避免用户处理;二是编写的代码可读性更强;三是不容易出错并且便于维护。
什么时候需要进行Metaprogramming
1. 当代码需要表述的是抽象问题领域的时候
2. 当需要编写一大堆同一样板的代码的时候
3. 当需要根据参数类型信息来选择组件时间的时候
4. 当想要利用泛型编程的一些优点,比如静态类型检查、行为定制、优化效率的时候
5. 需要使用C++进行代码生成的时候
Metaprogramming基础:萃取和类型运算
在程序有变量、函数构成代码,那么在Metaprogramming中也相应介绍metadata和metafunction的概念来方便理解metaprogramming。
相关概念
Metadata
Metadata指在编译期操作的对象实体。这个实体分为两类:类型和非类型。
MetaFunction
下面看一个例子,交互迭代器内容:
上述写法中需要为输入的迭代器类型定义value_type,所以无法处理原生指针类型。此时想起来一句话:FTSE (The Fundamental Theorem of Software Engineering) : We can solve any problem by introducing an extra level of indirection.这个就是传说中软件工程理论的基础。
增加新的层次,更换写法为:
对于STL中iterator_traits实现如下:
使用偏特化来处理原生类型:
这里的iterator_traits就是一个MetaFunction。这里可以对MetaFunction进行一个定义:
1. MetaFunction是一个类
2. MetaFunction是一个模板类,所有的操作的参数是型别。
3. MetaFunction是一个MPL库的核心抽象方法。
对于iterator_traits的使用方式就是iterator_traits<Para>::value_type,其中Para是参数,输入是型别,value_type是返回值。那么可以看出MetaFunction和普通函数的区别有以下两点:
1. MetaFunction通过特化实现分支判断和函数功能。
2. MetaFunction可以有多个返回值。
这个时候需要详细介绍另外一个概念:
多态(Polymorphism)
在引入了范型编程后,多态的概念要和OO中的多态概念进行区分。对于多态而言应该分为静态多态(编译期多态)和动态多态(运行期多态)。
对于运行期多态有下面三个特征:
1. 对象真正的类型在运行期决定。
2. 运行我们通过基类的指针或者引用处理多继承类型的对象。
3. 运行期多态是面向对象编程的主要特征。
对于编译期多态有以下特征:
1. 对象真正的类型在编译期决定。
2. 允许通过相同的语法和相同的方式操作不通的类型。
3. 编译期多态是范型编程的基础。
4. 编译期多态的两个效率问题:一是使程序的大小变大,二是使编译的时间增加。
Boost库的相关简介
Primary Type Categorization
判断参数类型是那种原生类型
Secondary Type Categorization
判断输入类型是否是一些高级类型,比如对象等,使用的是Primary Type Categorization的组合判断。
Type Properties
Relationships Between Types
判断类型之间的关系
is_same<T,U>
is_convertible<T,U>
is_base_and_derived<B,D>
Type Transformations
实现参数类型的转换