条款48:认识模板元编程(Be aware of template metaprogramming)

条款48:认识模板元编程

1.1 模板元编程

  1. 模板元编程(Template metadata programming, TMP)是编写在编译期间执行的基于模板的C++程序的过程。TMP是被发现的,而不是发明的。
  2. 特点是:更小的可执行文件,更短的运行时间,更少的内存需求,但需要更长的编译时间。
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; 
    } 
    else {//对于其他迭代器类别,使用对++或——的迭代调用
        if (d >= 0) { while (d--) ++iter; } 
        else { while (d++) --iter; } 
    } 
}
//基于typeid的方法比使用traits的方法效率低,因为
//(1)类型测试发生在运行时,而不是在编译期间;
//(2)进行运行时类型测试的代码必须存在于可执行文件中。

1.2 提出问题

advance基于typeid的实现可能会导致编译问题:

std::list<int>::iterator iter;
...
advance(iter, 10); // 基于上面的实现,无法编译通过

考虑上述调用将生成的advance版本:

void advance(std::list<int>::iterator& iter, int d)
{
//编译器必须确保所有源代码都是有效的,即使它们没有被执行
    if (typeid(std::iterator_traits<std::list<int>::iterator>::iterator_category) ==
        typeid(std::random_access_iterator_tag)) {
        iter += d; // 错误!
    } else {
        if (d >= 0) { while (d--) ++iter; }
        else { while (d++) --iter; }
    }
}

相比之下,基于traits的TMP解决方案将不同类型的代码拆分为单独的函数,每个函数只使用适用于它所编写的类型的操作。

1.3 举个栗子

TMP已经被证明是图灵完备的,这意味着它足够强大,可以计算任何东西。

template<unsigned n> // 一般情况:
struct Factorial { // Factorial<n>的值是Factorial<n-1>的值的n倍
    enum { value = n * Factorial<n - 1>::value };
};
//TMP使用递归模板实例化来代替循环
template<> // 特殊情况: 
struct Factorial<0> { // Factorial<0>的值为1
    enum { value = 1 };
};

int main()
{
    std::cout << Factorial<5>::value; // 打印 120
    std::cout << Factorial<10>::value; // 打印 3628800
}

1.4 使用场景

TMP的使用场景,下面提供了三个:

  1. 确保尺寸单位的正确性。
  2. 优化矩阵运算,请看下面的代码:
typedef SquareMatrix<double, 10000> BigMatrix;
BigMatrix m1, m2, m3, m4, m5; // 创建矩阵
... // 给它们赋值
BigMatrix result = m1 * m2 * m3 * m4 * m5; // 计算
  1. 生成自定义设计模式实现。

使用与TMP相关的一种高级模板技术——表达式模板(expression templates),可以消除临时变量并合并循环,不需要改变客户代码的语法。由此产生的软件使用的内存更少,运行速度更快。

1.5 总结

  1. 模板元编程可以将工作从运行时转移到编译时,从而支持更早的错误检测和更高的运行时性能。
  2. TMP可用于根据策略选择的组合生成自定义代码,它还可用于避免生成不适合特定类型的代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值