zoukankan      html  css  js  c++  java
  • effective C++ 条款 48:认识template元编程

    template metaprogramming(模板元编程)是编写template-based c++程序并执行于编译期的过程。是以c++写成,执行于c++编译器内的程序。一旦tmp程序执行结束,其输出,也就是template具现出来的若干c++源码,便会一如往常的编译。

    tmp有两个伟大的效力。第一,它让某些事情更容易。如果没有它,那些事情将是困难的,甚至是不可能的。第二,由于tmp执行于c++编译期,因此可将工作从运行期转移到编译期。导致一个结果是,某些错误原本通常在运行期才能侦测到,现在可在编译期找出来。另一个结果是使用tmp的c++程序可能在每一方面都更高效:较小的可执行文件、较短的运行期、较少的内存需求。编译时间长了。

    条款47指出,advance那个typeid-based解法的效率比traits解法低,因为此方案中,1.类型测试发于运行期而非编译器,2。运行期类型测试代码会出现在可执行文件中。traits解法就是tmp,它引发“编译期发生于类型身上的if。。。else计算。

    advance的typeid-based实现方式可能导致编译期问题:

    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;                //wrong!
        }
        else
            ...
    }

    list<int>::iterator是bidirectional不支持+=。我们知道绝不会执行+=那一行,但是编译器必须确保所有源码都有效,纵使是不会执行的代码

    针对tmp而设计的boost's mpl,见条款55 提供更高层的语法。

    让我们看看循环,tmp藉由递归完成。tmp递归并不涉及递归函数调用,而是涉及“递归模板具现化”(recursive template instantiation)。

    template<unsigned n>
    struct Factorial{                            //一般情况
        enum{value = n*Factorial<n-1>::value};
    };

    template<>
    struct Factorial<0>{                //特殊情况
        enum{value = 1};
    };

    和良好递归一样,我们需要一个特殊情况造成递归结束。这里的特殊情况就是template特化体Factorial<0>.

    std::cout << Factorial<5>::value;           //印出120

    tmp值得学习,3个例子:

    1.确保量度单位正确。如果使用tmp,就可以确保(在编译期)程序中所有量度单位的组合都正确,可被用来早期错误侦测。

    2.优化矩阵运算。

    BigMatrix m1,m2,m3,m4,m5;
    BigMatrix result = m1*m2*m3*m4*m5;

    正常的函数调用计算result,会创建4个临时性矩阵,每一个用来存储operator*的调用结果。各自独立的乘法产生了4个作用于矩阵元素上的循环。如果使用tmp相关的template技术,即所谓的expression templates,就有可能消除那些临时对象并合并循环,这一切都是无需改变客户端的做法。tmp使用较少的内存,执行速度又有显著的提升。

    3.可以生成客户定制的设计模式实现品。设计模式都可以多种方式实现出来。运用所谓policy-based design之tmp-based技术,有可能产生一些templates用来表述独立的设计选项(policies),然后任意结合它们,导致模式实现品带着客户定制的行为。这项技术已经超越编程公益领域,更广义地成为generative programming(殖生式编程)的一个基础。

    tmp或许永远不会成为主流,但对某些程序员——特别是程序库开发人员——几乎确定会成为他们的主要粮食。

  • 相关阅读:
    「UVA12293」 Box Game
    「CF803C」 Maximal GCD
    「CF525D」Arthur and Walls
    「CF442C」 Artem and Array
    LeetCode lcci 16.03 交点
    LeetCode 1305 两棵二叉搜索树中的所有元素
    LeetCode 1040 移动石子直到连续 II
    LeetCode 664 奇怪的打印机
    iOS UIPageViewController系统方法崩溃修复
    LeetCode 334 递增的三元子序列
  • 原文地址:https://www.cnblogs.com/lidan/p/2356535.html
Copyright © 2011-2022 走看看