初识c++模板元编程
模板元编程(Template metaprogramming,简称TMP)是编译器内执行的程序,编译器读入template,编译输出的结果再与其他源码一起经过普通编译过程生成目标文件。通俗来说,普通运行程序是编译器生成的机器码,由处理器解释执行得到结果,TMP则是编译器实例化template过程中得到结果。TMP已被证明是图灵完备的机器,不过模板实例化通常需要消耗巨大的编译器资源,而且难以追踪错误,没有合适的调试器,所以在实际开发中很少使用。
TMP有两个重要的作用:
- 将工作从运行期转移到编译期,一些在运行期才能发现的错误在编译时就找出来了。
- 产生较小的可执行文件,较短的运行时间,较少的内存需求。当然代价就是增加了编译时间。
下面让我们来看一个利用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++模板元编程的更多相关文章
- 初识C++模板元编程(Template Mega Programming)
前言:毕设时在开源库上做的程序,但是源码看得很晕(当时导师告诉我这是模板元编程,可以不用太在乎),最近自己造轮子时想学习STL的源码,但也是一样的感觉,大致了解他这么做要干什么,但是不知道里面的机制. ...
- C++模板元编程(C++ template metaprogramming)
实验平台:Win7,VS2013 Community,GCC 4.8.3(在线版) 所谓元编程就是编写直接生成或操纵程序的程序,C++ 模板给 C++ 语言提供了元编程的能力,模板使 C++ 编程变得 ...
- C++模板元编程 - 函数重载决议选择工具(不知道起什么好名)完成
这个还是基于之前实现的那个MultiState,为了实现三种类型“大类”的函数重载决议:所有整数.所有浮点数.字符串,分别将这三种“大类”的数据分配到对应的Converter上. 为此实现了一些方便的 ...
- C++模板元编程 - 挖新坑的时候探索到了模板元编程的新玩法
C++真是一门自由的语言,虽然糖没有C#那么多,但是你想要怎么写,想要实现什么,想要用某种编程范式或者语言特性,它都会提供. 开大数运算类的新坑的时候(又是坑),无意中需要解决一个需求:大数类需要分别 ...
- 读书笔记_Effective_C++_条款四十八:了解模板元编程
作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...
- c++ 模板元编程的一点体会
趁着国庆长假快速翻了一遍传说中的.大名鼎鼎的 modern c++ design,钛合金狗眼顿时不保,已深深被其中各种模板奇技淫巧伤了身...论语言方面的深度,我看过的 c++ 书里大概只有 insi ...
- C++模板元编程 - 3 逻辑结构,递归,一点列表的零碎,一点SFINAE
本来想把scanr,foldr什么的都写了的,一想太麻烦了,就算了,模板元编程差不多也该结束了,离开学还有10天,之前几天部门还要纳新什么的,写不了几天代码了,所以赶紧把这个结束掉,明天继续抄轮子叔的 ...
- C++模板元编程 - 2 模仿haskell的列表以及相关操作
这是昨天和今天写的东西,利用C++的可变模板参数包以及包展开,模式匹配的一些东西做的,感觉用typename...比轮子叔那个List<A,List<B, List<C, D> ...
- 一道模板元编程题源码解答(replace_type)
今天有一同学在群上聊到一个比较好玩的题目(本人看书不多,后面才知是<C++模板元编程>第二章里面的一道习题), 我也抱着试一试的态度去完成它, 这道题也体现了c++模板元编程的基础和精髓: ...
随机推荐
- PHP-----JSOM类型数据
JS里的数据类型 JS里的一种数据类型,JSOM类型数据 JSOM这种数据类型,在使用JS和jquery时经常使用的到,比较重要.用起来比较简单. <title>无标题文档</tit ...
- Linux脚本开头#!/bin/bash和#!/bin/sh是什么意思以及区别
一.意思 #!/bin/sh是指此脚本使用/bin/sh来解释执行,#!是特殊的表示符,其后面根的是此解释此脚本的shell的路径. 其实第一句的#!是对脚本的解释器程序路径,脚本的内容是由解释器解释 ...
- Vim插件及.vimrc文件的配置
关于Vim的配置基本是在.vimrc文件中完成的,该文件一般放在用户目录下. 今天安装了插件管理器Pathogen和python自动补全的插件pydiction,其中Pathogen需要事先创建两个文 ...
- 入门——Bootstrap栅格系统
作为刚接触到Bootstrap框架的新手一枚,刚开始对Bootstrap中的栅格系统一脸懵逼,后来经过反复的上网查找资料以及自己一直在练习,总算对栅格系统了解个差不多,所以我将我所了解的当成是日记写下 ...
- MyBatis之Mapper XML 文件详解(三)-Result Maps
resultMap 元素是 MyBatis 中最重要最强大的元素.它就是让你远离 90%的需要从结果 集中取出数据的 JDBC 代码的那个东西, 而且在一些情形下允许你做一些 JDBC 不支持的事 情 ...
- 04 关于oracle的锁的级别以及介绍
关于oracle的锁的级别以及介绍 oracle造成锁表的情况: 一.查看锁的对象视图:select object_id,session_id,locked_mode from v$locked_ob ...
- JavaScript-比较运算符
一.概述 > 大于运算符 < 小于运算符 <= 小于或者等于运算符 >= 大于或者等于运算符 == 相等运算符 === 严格相等运算符 != 不相等运算符 !== 严格不相等运 ...
- mysql复制表结构和数据
1.复制表结构: create table newName like oldName;//可以复制所有结构. 或者: create table newName select * from oldNam ...
- MySQL 5.7增强半同步测试
we've know the machenism of semi-synchronous replication in my previous article,let's do som ...
- MySQL 参数slave_pending_jobs_size_max设置
今天生产环境上从库出现SQL进程停止的异常,错误信息如下: Slave_IO_Running: Yes Slave_SQL_Running: No Replicate_Do_DB: Replicate ...