C++11 模板元编程 - 前言


熟悉C++的程序员都知道,C++是一门多范式编程语言,支持面向过程、面向对象、泛型编程以及函数式编程范式。然而提到C++模板元编程,在很多人心里这却是C++里的黑魔法:它很难学习,一旦进入这个领域曾经那些熟悉的东西(if,for...)都不再灵验;它很强大,但现实中却鲜见有人用它来解决实际问题,除过偶尔在一些编码练习中被某些C++狂热粉当做奇淫巧技拿出来秀秀肌肉。

其实模板元编程是C++所支持的一种非常强大的计算能力,它是使用C++开发高质量库和框架所离不开的一项武器。

掌握C++模板元编程,至少可以在以下场合帮助到你:

  • 实现高扩展性,并且兼具高性能的库
  • 实现灵活且易于使用的框架
  • 实现基于C++的内部DSL(Domain Specific Language)
  • 帮助更深入地理解并使用模板和泛型编程,更好地去使用C++ STL库中的高级特性

如果你是一个C++的库或框架的开发者,了解和掌握一些模板元编程的知识,可以让你的作品更易于扩展、拥有更易用的接口,甚至更高的运行时效率。而即使你只使用C++设计和开发应用程序,了解模板元编程也会帮助你更好的去使用STL库的各种特性,帮助你的局部设计做的更加漂亮。

实际上C++模板元编程技术已经渗透在我们日常使用的各种库和框架中,例如我们最常使用的STL库以及各种xUnit测试框架和mock框架。可以说,模板元编程是中级C++程序员迈向高级的必经之路!

然而现实是,C++模板元编程的学习之旅却并不平坦。

一方面,由于C++模板元编程的本质是函数式编程,熟练掌握并使用函数式编程的程序员比较小众,绝大多数程序员初次进入这个领域时面对模式匹配、递归和不可变性时都会手足无措。另一方面,由于C++的模板元编程能力是被意外发现的,不像别的函数式编程语言经过良好的设计,所以C++的这种函数式计算能力天生存在着各种缺陷,直到C++11标准才开始逐渐完善起来。在之前很多重要特性都靠很绕的方式去迂回实现,增加了学习的难度。

另外,市面上介绍模板元编程的书和资料也乏善可陈,以下的书相对还不错,但对于模板元编程的介绍仍旧存在一些问题:

  • 《C++ Templates Complete》
    介绍C++模板知识最全面的一本书,涉及到了模板各个方面的基础知识和应用技巧。由于元编程并不是此书重点,所以仅有短短一章列举了一些利用模板元编程做数值计算的例子。现实中使用模板元编程单纯做数值计算的场合并不多,模板元编程更大的价值在于做类型计算和代码生成,书中却涉及甚少。

  • 《Modern C++ Design》
    介绍如何使用模板进行C++高阶设计的一本书。介绍了TypeLists的概念,作为一种重要的编译时数据结构,是元编程的基础。但遗憾作者并没有明确的提出元编程的概念,也没有对C++编译时的运算特征进行总结和提炼。最后由于此书基于的C++ 98标准对于模板以及编译期类型计算支持上的欠缺,书中介绍的不少实现比较迂回复杂。

  • 《C++模板元编程》
    正式介绍C++模板元编程的一本书,引入了元函数的概念。通过对模板计算的规范化,发挥了编译期元函数可组合的优势。遗憾的是,此书只能算是boost中mpl库的用户手册,基本上是在讲mpl库的用户接口和使用方法,没有涉及库的实现细节。现实中我们采用元编程解决问题,一般不会引用boost这么重的库,往往只会在某一局部借鉴类似的设计技巧。所以对于元编程来说,授之以渔的意义远大于授之以鱼。另外由于boost mpl库中用了大量C++预处理期代码生成技术,导致通过阅读mpl源码去掌握模板元编程的同学一上来就陷入到一堆宏中,对于学习元编程增加了非常多的干扰因素。

基于以上原因,我基于C++11标准实现了一个模板元编程的基础库:TLP (https://github.com/MagicBowen/tlp),然后再通过本手册来为大家全面介绍C++模板元编程的基本知识和使用技巧。

TLP库包含以下内容:

  • 基本的编译期数据类型和算法;
  • 基本的编译期数据结构TypeList,以及针对它的各种基本算法函数:length、append、erase、replace、unique、belong、comb...
  • 基于TypeList的各种高阶函数,如 any,all,sort、transform、map,filter,fold...
  • 辅助模板元编程的常用函数,如 __is_eq(),__if(),__print() ...
  • 一些有用的编译期Traits工具,如 IsBaseOf,IsConvertible,IsBuiltIn...
  • 一些常用的元编程模式,如 “元函数转发”等;
  • 一个面向模板元编程的测试框架,用它描述的所有测试用例执行在C++的编译期,我们使用它来对TLP进行测试;

除此之外,TLP库中还包含了如下示例代码,用来演示如何在现实场景中应用好模板元编程和TLP库:

  • 示范了如何使用模板元编程做纯编译期计算,完成一个自动数三角形的程序;
  • 示范了如何使用模板元编程技术来实现代码生成,自动创建visitor设计模式;
  • 示范了如何使用模板元编程技术来实现一个DSL,用于描述并生成有限状态机;

上面提到的TypeList以及使用代码生成来创建visitor设计模式的原创者是《Modern C++ Design》的作者Andrei Alexandrescu。在TLP中我用C++11对TypeList及其算法进行了改写,并进行了高阶函数的扩展。得益于C++11标准对模板元编程的更好支持,新的实现比起原来的更加清晰和简洁。

示例代码中利用模板元编程创建有限状态机DSL的设计最初来自于《C++模板元编程》一书,为了让其更好被理解,我对例子以及代码进行了较大的改编。

除了上面的例子,本手册中还介绍了我自己开发的针对C++模块和子系统FT(Functional Test)级别的测试框架dates,展示了它如何使用模板元编程来进行类型萃取、类型选择以及类型校验,最终使得框架变得更易用、更高效以及更安全。这些技巧可以帮助到大家更好地使用模板元编程去解决现实问题。

最后,TLP库自身的测试通过一个原创的C++模板元编程测试框架。该框架专门针对C++编译期计算进行测试,它的用法和常见的xUnit测试框架类似,但有趣的是使用该框架描述的所有测试用例的执行发生在C++编译期。本文会专门介绍该框架的一些实现细节。


C++模板元编程当年被提出来的时候,函数式编程还没有像今天这样被更多的人所了解和接受,当时的C++标准和编译器对模板和编译期计算的支持也存在着很多缺陷。然而到了今天,很多事情发生了变化!本文的读者最好能够有一些函数式编程的基础,了解C++模板的基本用法,熟悉一些C++11标准的内容。当然文中所有用的到模板技术、C++11标准和涉及到的函数式编程概念也都会专门介绍和说明。

如果你从来没有接触过C++模板元编程,那么最好从一开始就把它当做一门全新的语言去学习,从头掌握C++中这种不一样的计算模型和语法。这种新的语言和我们熟识的运行期C++在语法和计算模型上都有较大的差异,但它的优势在于能和运行期C++紧密无缝地结合在一起,无论是在提高程序可扩展性还是提高程序运行效率上,都能创造出非常不可思议的效果来。希望通过本手册,可以让更多的人掌握C++模板元编程这一设计利器,在适合的场合下以更有效、更酷的方式去解决问题。

文中出现的所有代码片段,如果在注释中给出了TLP库中对应的文件路径,则都能在TLP库中找到源码。除此之外的其它代码则是为了文章需要所构造的临时代码。另外,为了减少干扰,本文中所示TLP库中的代码均没有加命名空间,阅读文章和TLP库源码时请注意区分。


模板的基础知识

返回 C++11模板元编程 - 目录

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容