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

TMP有两个重要的作用:

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

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

template<int N>
class Pow3 {
public:
enum {result=*Pow3<N->::result};
}; template<>
class Pow3<> {
public:
enum {result=};
}; int main() {
std::cout<<"Pow3<7> = "<<Pow3<>::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=*Pow3<N->::result;
}; template<>
class Pow3<> {
public:
static int const result=;
};

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

void foo(int const&);

foo(Pow3<7>::result);

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

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

Reference:

《c++ templates: the complete guide》

《effective c++》

初识c++模板元编程的更多相关文章

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

    前言:毕设时在开源库上做的程序,但是源码看得很晕(当时导师告诉我这是模板元编程,可以不用太在乎),最近自己造轮子时想学习STL的源码,但也是一样的感觉,大致了解他这么做要干什么,但是不知道里面的机制. ...

  2. C++模板元编程(C++ template metaprogramming)

    实验平台:Win7,VS2013 Community,GCC 4.8.3(在线版) 所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得 ...

  3. C++模板元编程 - 函数重载决议选择工具(不知道起什么好名)完成

    这个还是基于之前实现的那个MultiState,为了实现三种类型“大类”的函数重载决议:所有整数.所有浮点数.字符串,分别将这三种“大类”的数据分配到对应的Converter上. 为此实现了一些方便的 ...

  4. C++模板元编程 - 挖新坑的时候探索到了模板元编程的新玩法

    C++真是一门自由的语言,虽然糖没有C#那么多,但是你想要怎么写,想要实现什么,想要用某种编程范式或者语言特性,它都会提供. 开大数运算类的新坑的时候(又是坑),无意中需要解决一个需求:大数类需要分别 ...

  5. 读书笔记_Effective_C++_条款四十八:了解模板元编程

    作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...

  6. c++ 模板元编程的一点体会

    趁着国庆长假快速翻了一遍传说中的.大名鼎鼎的 modern c++ design,钛合金狗眼顿时不保,已深深被其中各种模板奇技淫巧伤了身...论语言方面的深度,我看过的 c++ 书里大概只有 insi ...

  7. C++模板元编程 - 3 逻辑结构,递归,一点列表的零碎,一点SFINAE

    本来想把scanr,foldr什么的都写了的,一想太麻烦了,就算了,模板元编程差不多也该结束了,离开学还有10天,之前几天部门还要纳新什么的,写不了几天代码了,所以赶紧把这个结束掉,明天继续抄轮子叔的 ...

  8. C++模板元编程 - 2 模仿haskell的列表以及相关操作

    这是昨天和今天写的东西,利用C++的可变模板参数包以及包展开,模式匹配的一些东西做的,感觉用typename...比轮子叔那个List<A,List<B, List<C, D> ...

  9. 一道模板元编程题源码解答(replace_type)

    今天有一同学在群上聊到一个比较好玩的题目(本人看书不多,后面才知是<C++模板元编程>第二章里面的一道习题), 我也抱着试一试的态度去完成它, 这道题也体现了c++模板元编程的基础和精髓: ...

随机推荐

  1. 2019.1.6 2.8 Spring的AOP事务

    2.8 Spring的AOP事务 xml配置aop事务 先applicationContext.xml 文件 配置事务管管理器 配置通知 织入目标对象

  2. 从零一起学Spring Boot之LayIM项目长成记(一) 初见 Spring Boot

    项目背景 之前写过LayIM的.NET版后端实现,后来又写过一版Java的.当时用的是servlet,websocket和jdbc.虽然时间过去很久了,但是仍有些同学在关注.偶然间我听说了Spring ...

  3. sourcetree创建分支与分支合并

    一.Sourcetree简单介绍 通过Git可以进行对项目的版本管理,但是如果直接使用Git的软件会比较麻烦,因为是通过一条一条命令进行操作的.  Sourcetree则可以与Git结合,提供图形界面 ...

  4. PAT——1016. 部分A+B

    正整数A的“DA(为1位整数)部分”定义为由A中所有DA组成的新整数PA.例如:给定A = 3862767,DA = 6,则A的“6部分”PA是66,因为A中有2个6. 现给定A.DA.B.DB,请编 ...

  5. STM32F103 ucLinux开发之一(BOOT分析及源码)

    STM32F103 ucLinux开发BOOT STM3210E-EVAL官方开发板主芯片STM32F103ZET6: 片内512K Flash,地址0x0800 0000 ~ 0x0807 FFFF ...

  6. FreeRTOS 和uCOS II的简单比较

    转载:http://www.viewtool.com/bbs/forum.php?mod=viewthread&tid=114 这是两种RTOS, 现在粗略比较一下. freeRTOS比uCO ...

  7. Java IP白名单相关工具类

    关于设置IP白名单相关的一些方法,整理,记录了一下. package com.tools.iptool; import java.util.ArrayList; import java.util.Ha ...

  8. pl/sql developer开发工具的beautifier美化插件

    对于存储过程中需要编写大量的sql语句,这必然需要美化语句,使得程序可读性更高. pl/sql developer开发工具自带美化工具,不过美化的时候容易使得语句全部改变成大写格式,这样就需要一个插件 ...

  9. js取一个对象中的另一个对象

    最开始的截图 原本是想取到其中的foodName 先是用一个for循环循环了下 for (var i=0;i<res.data.length;i++) { this.goodsList.res. ...

  10. 在centos6.7通过源码安装python3.6.7报错“zipimport.ZipImportError: can't decompress data; zlib not available”

    在centos6.7通过源码安装python3.6.7报错: zipimport.ZipImportError: can't decompress data; zlib not available 从 ...