Item 48:了解模板元编程

模板元编程(Template Metaprogramming,TMP)就是利用模板来编写那些在编译时运行的C++程序。 模板元程序(Template Metaprogram)是由C++写成的,运行在编译器中的程序。当程序运行结束后,它的输出仍然会正常地编译。

C++并不是为模板元编程设计的,但自90年代以来,模板元编程的用处逐渐地被世人所发现。

  • 模板编程提供的很多便利在面向对象编程中很难实现;
  • 程序的工作时间从运行期转移到编译期,可以更早发现错误,运行时更加高效。
  • 在设计模式上,可以基于不同的策略,自动组合而生成具体的设计模式实现。

静态类型检查

template<typename IterT, typename DistT>
void advance(IterT& iter, DistT d) {
  if (typeid(typename std::iterator_traits<IterT>::iterator_category) ==
    typeid(std::random_access_iterator_tag)){
      iter += d;
  }
  ...
}
 
list<int>::iterator it;
advance(it, 10);

其实上述代码是不能编译的,设想以下advance<list<int>::iterator, int>中的这条语句:

iter += d;

list<int>::iterator 是双向迭代器,不支持+=运算。虽然上述语句不会执行,但编译器不知道这一点。 编译时这条语句仍然会抛出类型错误。

模板元编程

TMP 后来被证明是图灵完全的,这意味着 TMP 可以用来计算任何可计算的问题。你可以声明变量、执行循环、编写和调用函数等等。 但它的使用风格和普通 C++ 完全不同。

我们来看看 TMP 中如何执行一个循环:

template<unsigned n>
struct Factorial{
    enum{ value = n * Factorial<n-1>::value };
};
template<>
struct Factorial<0>{
    enum{ value = 1 };
};
 
int main(){
    cout<<Factorial<5>::value;
}

TMP 的用途

为了更好地理解TMP的重要性,我们来看看TMP能干什么:

  • 确保量纲正确。在科学计算中,量纲的结合要始终保持正确。比如一定要单位为 ”m” 的变量和单位为 ”s” 的变量相除才能得到一个速度变量(其单位为”m/s”)。 使用 TMP 时,编译器可以保证这一点。因为不同的量纲在 TMP 中会被映射为不同的类型。
  • 优化矩阵运算。比如矩阵连乘问题,TMP 中有一项表达式模板的技术,可以在编译期去除临时变量和合并循环。 可以做到更好的运行时效率。
  • 自定义设计模式的实现。设计模式往往有多种实现方式,而一项叫基于策略设计的 TMP 技术可以帮你创建独立的设计策略,而这些设计策略可以以任意方式组合。生成无数的设计模式实现方式。

总结

  • 模板元编程能将工作从运行时转移到编译时,这样就能够更早察觉错误并提高运行时性能。
  • TMP 能用于在 policy choices 的组合的基础上生成自定义代码,也能用于避免为特殊类型生成不适当的代码。
posted @ 2020-02-27 20:14  刘-皇叔  阅读(216)  评论(0编辑  收藏  举报