《Effective C++》:条款48:理解力template 元编程

Template metaprogramming(TMP,模板元编程)这是写template-based C++规划。编译过程。template metaprogramming随着C++写模板程序,化的过程。也就是说,TMP程序运行后,从templates详细化出来C++源代码。不再是模板了。

TMP有两个作用,一是它让某些事更easy。

比如编写STL容器,使用模板,可是存放不论什么类型元素。二是将运行在运行期的某些工作转移到了编译期。另一个结果是使用TMP的C++程序可能在其它方面更高效:较小的可运行文件、较短的运行期、较少的内存需求。可是将运行期的工作转移到了编译期。编译期可能变长了。

再看一下条款 47中的advance伪码

 template<typename Iter, typename DistT>
    void advance(IteT& iter,DistT d)
    {
        if(iter is a random access iterator)
            iter+=d;
        else
        {
            if(d>=0)
                while(d--) ++iter;
            else
                while(d++) --iter;
        }
    }

能够使用typeid让推断iter类型的伪码运行

 template<typename Iter, typename DistT>
    void advance(IteT& 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-based解法效率比traits解法低,由于在此方案中,1类型測试发生在运行期而不是编译期,2运行期类型測试代码在(或被连接于)可运行文件里。

这个样例能够说明TMP比正常的C++程序更高效,由于traits解法就是TMP。

一些东西在TMP比在正常的C++更easy。advance提供一个好样例。

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

    std::list<int>::iterator iter;
    ……
    advance(iter,10);
    void advance(std::list<int>::iterator& iter,int d)
    {
        if(typeid(typename 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;
        }
    }

在+=这个操作符上是错误调用。由于list::iterator不支持+=,它是bidirectional迭代器。

我们知道不会运行+=那一行,由于typeid那一行总是不相等;可是编译期要确保全部源代码都有效,即使是不会运行的代码。traits-based TMP解法针对不同类型运行不同代码,不会出现上述问题。

TMP已被证明是个图灵全然机器,也就是说它的威力足以计算不论什么事物。能够使用TMP声明变量、运行循环、编写调用函数……。有时候这会和正常C++相应物看起来非常是不同。比如条款 47展示的TMP if-else是由templas和其特化详细表现出来。只是那是汇编语言级的TMP。针对TMP设计的程序库(比如Boost’s MPL。**条款**55)提供更高级的语法。

为了再次认识下事物在TMP中怎样运作,来看下循环。TMP没有真正循环。循环由递归(recursion)完毕。

TMP递归甚至不是正常的递归。由于TMP递归不涉及递归函数调用,而是涉及递归模板化(recursive template instantiation)。

TMP的起手程序是在编译期计算阶乘。

TMP的阶乘运输示范怎样通过递归模板详细化实现循环,以及怎样在TMP中创建和使用变量

    template<unsigned n>
    struct Factorial{
        enum {value=n*Factorial<n-1>::value};
    };
    template<>
    struct Factorial<0>{ //特殊情况。Factorial<0>的值是1
        enum {value=1};
    };

有了这个template metaprogram,仅仅要指涉Factorial::value就能够得到n阶乘值。循环发生在template详细化Factorial内部指涉另一个template详细化Factorial之时。

特殊情况的template特化版本号Factorial<0>是递归的结束。

每一个Factorial template详细化都是一个struct。每一个struct都声明一个名字为value的TMP变量,用来保存当前计算所获得的阶乘值。

TMP以递归模板详细化代替循环。每一个详细化有自己一份value,每一个value有其循环内适当值。

用Factorial示范TMP就像用hello world示范编程语言一样。为了领悟TMP之所以值得学习,就要先对它能够达成什么目标有一个比較好的理解。以下举三个样例:

  • 确保量度单位正确。使用TMP就能够确保在编译期全部量度单位的组合都正确。
  • 优化矩阵运算。

    条款 21以前提到过某些函数包含operator * 必须返回新对象,在条款 44中有一个SquareMatrix。

    假设这样使用

    typedef SquareMatrix<double,1000> BigMatrix;
    BigMatrix m1,m2,m3,m4,m5;
    ……
    BigMatrix result=m1 * m2 * m3 * m4 * m5;

上面乘法会产生四个暂时性矩阵,乘法还可能产生了4个作用在矩阵元素身上的循环。假设使用高级、与TMP相关的template(即expression templates),就有可能消除那些暂时对象并合并循环。所以TMP使用较少内存。运行速度也有提升。

  • 能够生成客户定制之设计模式(custom design pattern)实现品。使用policy-based design之TMP-based技术,有可能产生一些templates用来表述独立的设计项(所谓policies)。然后能够随意结合它们,导致模式实现品带着客户定制的行为。

TMP眼下还不全然成熟,语法不直观,支持的工具还不充分。

但TMP对难以或甚至不可能于运行期实现出来的行为表现能力非常吸引人。尽管TMP不会成为主流。可是会成为一些程序猿(特别是程序库的开发者)的主要粮食。

总结

  • Template metaprogramming(TMP,模板元编程)可将工作由运行期移到编译期,因而得以实现早期错误侦測和更高的运行效率。
  • TMP可被用来生成“基于政策选择组合”(based on combinations of policy choices)的客户定制代码。也可用来避免生成对某些特殊类型并不适合的代码。

版权声明:本文博主原创文章,博客,未经同意不得转载。

《Effective C++》:条款48:理解力template
元编程

时间: 2024-08-07 16:40:07

《Effective C++》:条款48:理解力template 元编程的相关文章

Effective C++ 条款48 认识template元编程

1. 模板元编程(template mataprogramming,TMP)是编写C++程序并执行于编译期的过程,"所谓template mataprogram(模板元程序),是以C++写成,执行于C++编译器内的程序.一旦TMP程序结束执行,其输出,也就是从templates具现出来的若干C++源码,便会一如往常地被编译". 2. 自从templates加入C++,TMP底层特性便被引进了,自从TMP于1990s初期被发现,TMP被日渐证明十分有用.TMP有两个伟大效力: 1). 它

Effective C++ Item 48 认识 template 元编程

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:Template metaprogramming (TMP, 模板元编程)可将工作由运行期移往编译期,因而得以实现早期错误侦测和更高的执行效率 示例1: template<typename IterT, typename DistT> void advance(IterT &iter, DistT d){ if(typeid(typename std::iterator_t

读书笔记 effective c++ Item 48 了解模板元编程

1. TMP是什么? 模板元编程(template metaprogramming TMP)是实现基于模板的C++程序的过程,它能够在编译期执行.你可以想一想:一个模板元程序是用C++实现的并且可以在C++编译器内部运行的一个程序,它的输出——从模板中实例化出来的C++源码片段——会像往常一样被编译. 2. 使用TMP的优势 如果这没有冲击到你,是因为你没有足够尽力去想. C++不是为了模板元编程而设计的,但是自从TMP早在1990年被发现之后,它就被证明是非常有用的,为了使TMP的使用更加容易

模板Trait 技术与简述template 元编程

模板Trait 技术 想了好久都没有想到合适的例子,已是干脆直接使用[1]中的例子就好了. STL 中引入了迭代器的概念.但是在本文中的例子不直接使用STL 的迭代器,而是写了一段很简短的代码,作为演示使用. 本例中的迭代器有三种: Forward_Iter,只能向前进,也就是只能加非负数 Bidirectional_Iter,可以双向增减 Random_Iter,可以随意增减 *本例并没有沿用STL 中的名称,请注意区别 对于三种的迭代器的偏移,大概如下: template<typename

Effective C++ 条款48

本节条款:了解模板元编程 本节条款是对模板元编程的简单介绍,让读者知道有这么一种编程方式,更确切的说是一种技术. 那么,什么是模板元编程?模板元编程有什么好处?按照作者的原话就是: 1. TMP可将工作由运行期转移到编译期,因而得以实现早期错误侦测或者更高的执行效率. 2. TMP可被用来生成"基于政策选择组合"的客户定制代码,也可以用来避免生成对某些特殊类型并不适合的代码. 说原理容易让人不知所云,来一段作者的代码,大家看看. template <int N> struc

《Effective C++》:条款48:认识template元编程

Template metaprogramming(TMP,模板元编程)是编写template-based C++程序,编译的过程.template metaprogramming是用C++写的模板程序,编译器编译出具体化的过程.也就是说,TMP程序执行后,从templates具体化出来C++源码,不再是模板了. TMP有两个作用,一是它让某些事更容易.例如编写STL容器,使用模板,可是存放任何类型元素.二是将执行在运行期的某些工作转移到了编译期.还有一个结果是使用TMP的C++程序可能在其他方面

Item 48:了解模板元编程

Item 48: Be aware of template metaprogramming. 模板元编程(Template Metaprogramming,TMP)就是利用模板来编写那些在编译时运行的C++程序. 模板元程序(Template Metaprogram)是由C++写成的,运行在编译器中的程序.当程序运行结束后,它的输出仍然会正常地编译. C++并不是为模板元编程设计的,但自90年代以来,模板元编程的用处逐渐地被世人所发现. 模板编程提供的很多便利在面向对象编程中很难实现: 程序的工

初识C++模板元编程(Template Mega Programming)

前言:毕设时在开源库上做的程序,但是源码看得很晕(当时导师告诉我这是模板元编程,可以不用太在乎),最近自己造轮子时想学习STL的源码,但也是一样的感觉,大致了解他这么做要干什么,但是不知道里面的机制.于是开始学习<C++模板元编程>,看完第二章对一些东西豁然开朗. PS:该书也有点老了,C++11标准还没出来,主要用的Boost库. Traits(特征) 说正题,在STL中经常可以见到后缀为traits的名字,比如经常用到的std::string,本质是类模板basic_string的第一个参

Effective C++ 条款54 让自己熟悉包括TR1在内的标准程序库

1. TR1(Technical Report 1)是C++ 03标准的一个扩展,它并不属于C++ 03标准,只是一份草稿文件,用于指出下一版C++标准很可能吸收的特性.目前,它的大部分已被C++ 11采纳,成为官方标准. 2. C++ 98列出的标准库的组成: STL(Standard Template Library,标准模板库).包含容器,迭代器,算法,函数对象,各种容器适配器(container adapter)和函数对象适配器(function object adapter)等. Io