模板元编程(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. PHP-----TP框架基础

    TP框架基础 把Thinkphp框架的压缩包解压到php文件夹下----www目录下.   Thinkphp文件夹都有什么呢??? (所有用TP框架做的程序,要访问程序里面的网页.内容的话,全部要走这 ...

  2. struts2不同版本在核心filter在web.xml中的配置

    FilterDispatcher是struts2.0.x到2.1.2版本的核心过滤器.配置如下: <filter> <filter-name>struts2</filte ...

  3. 如何用C#对Gridview的项目进行汇总统计?

    上一次用了javascript对gridview进行了汇总统计,但那个统计是在客户端进行的,虽然减轻了服务器的负担,但是,当需要把统计信息汇出excel时,汇总信息却死活不出来了,所以,绕半天又绕回来 ...

  4. HTML&CSS笔记001

    lesson1 <!DOCTYPE html><html lang="en,zh"><!-- 告诉搜索引擎爬虫,我们的网站是关于什么内容的 --> ...

  5. Xcode 怎么查看代码总行数

    打开终端 输入 cd 空格 你的工程路径这里有一个小技巧,你把要统计的文件夹直接拖住拖到终端里,路径就出来了.然后输入find . -name "*.m" -or -name &q ...

  6. Vue--- 一点车项目 6个小时实际看了10天(完结)

    一个项目 环境安装   使用了 cli 脚手架  Koa2  workpackage  其他小的不计 前端Vue组件搭建 数据的简单测试交互 数据库的设计 创建.连接接数据库 前台[表单/分类]   ...

  7. CodeChef March Lunchtime 2018 div2

    地址https://www.codechef.com/LTIME58B?order=desc&sortBy=successful_submissions 简单做了一下,前三题比较水,第四题应该 ...

  8. mysql 配置安装

    1.     下载: mysql-5.7.20是解压版免安装的,mysql-5.7.20下载地址:http://dev.mysql.com/downloads/mysql/ 直接下载,无需注册和登录. ...

  9. 自己写的代码实现Session

    package com.zq.web.context.windows; import java.util.HashMap;import java.util.Map; import org.apache ...

  10. java并发实战:连接池实现

    池化技术简介 在我们使用数据库的过程中,我们往往使用数据库连接池而不是直接使用数据库连接进行操作,这是因为每一个数据库连接的创建和销毁的代价是昂贵的,而池化技术则预先创建了资源,这些资源是可复用的,这 ...