• 初识c++模板元编程


    模板元编程(Template metaprogramming,简称TMP)是编译器内执行的程序,编译器读入template,编译输出的结果再与其他源码一起经过普通编译过程生成目标文件。通俗来说,普通运行程序是编译器生成的机器码,由处理器解释执行得到结果,TMP则是编译器实例化template过程中得到结果。TMP已被证明是图灵完备的机器,不过模板实例化通常需要消耗巨大的编译器资源,而且难以追踪错误,没有合适的调试器,所以在实际开发中很少使用。

    TMP有两个重要的作用:

    1. 将工作从运行期转移到编译期,一些在运行期才能发现的错误在编译时就找出来了。
    2. 产生较小的可执行文件,较短的运行时间,较少的内存需求。当然代价就是增加了编译时间。

    下面让我们来看一个利用TMP计算3的幂的例子

    template<int N>
    class Pow3 {
     public:
      enum {result=3*Pow3<N-1>::result};
    };
    
    template<>
    class Pow3<0> {
     public:
      enum {result=1};
    };
    
    int main() {
      std::cout<<"Pow3<7> = "<<Pow3<7>::result<<std::endl; 
    }

    Pow<7>的实例化导致Pow3<6>的实例化,Pow3<6>又出发Pow3<5>的实例化,递归直至Pow3<0>结束,Pow<7>::result直接被常量值替换。

    一个TMP程序可以包含以下几部分:

    • 状态变量:即模板参数
    • 迭代构造:TMP没有循环等构件,全部用递归实现,另一方面递归的实例化也是降低编译器效率的主要原因。
    • 路径选择:通过使用条件表达式或者特化。
    • 整形算法(即枚举)

    c++中,在类内部声明常量值只有枚举和静态常量初始化两种方式。上面的例子中可以将枚举改成静态常量,

    template<int N>
    class Pow3 {
     public:
      static int const result=3*Pow3<N-1>::result;
    };
    
    template<>
    class Pow3<0> {
     public:
      static int const result=1;
    };

    不过静态常量是左值,如果将结果作为引用参数传递给一个函数,

    void foo(int const&);

    foo(Pow3<7>::result);

    编译器必须获取 Pow3<7>::result的地址,这会强制编译器实例化静态成员的定义,并分配内存,这就跳出了编译期范围。

    而枚举不是左值,没有这个约束,通过引用传递的时候跟使用常量值形式是一样的,所以一般都用枚举类型。

     

    Reference:

    《c++ templates: the complete guide》

    《effective c++》

  • 相关阅读:
    C#子线程抛出的异常给主线程
    WebBrowser1_DocumentCompleted事件里面无法触发InvokeMember("click")
    判断页面是否完全载入对ExtendedWebBrowser的DocumentCompleted再扩展
    webBrowser载入网页机制网页加载是否完毕判断
    验证码识别必备,c#分析bmp图形文件,一个有用的BMP图形分析类
    ConcurrentDictionary数据结构的使用方法
    手机号码归属地查询api接口
    Eclipse自动提示
    学计算机该看的书
    天气预报api整理
  • 原文地址:https://www.cnblogs.com/coderkian/p/3682007.html
Copyright © 2020-2023  润新知