C++模版的本质图灵实例化编程算法参数化

C++的一些高级特性对于新人来说,很具有挑战性,而模板就是其中之一,晦涩语法让很多新人望而生畏;大多数人苦苦磨练,却始终没有掌握这门绝学,本文通过揭开模板的一些面纱,希望帮助新人掌握模板的心法,从而学会这门武功(技术),助你跨过C++这座大山,向C++顶级程序员迈进,升职加薪;

C++模版的诞生

程序=数据结构+算法---NiklausEmilWirth

程序本质是数据结构+算法,任何一门语言都可以这样理解,这个公式对计算机科学的影响程度足以类似物理学中爱因斯坦的“E=MC^2”——一个公式展示出了程序的本质。

最初C++是没有标准库的,任何一门语言的发展都需要标准库的支持,为了让C++更强大,更方便使用,BjarneStroustrup觉得需要给C++提供一个标准库,但标准库设计需要一套统一机制来定义各种通用的容器(数据结构)和算法,并且能很好在一起配合,这就需要它们既要相对的独立,又要操作接口保持统一,而且能够很容易被别人使用(用到实际类中),同时又要保证开销尽量小(性能要好)。BjarneStroustrup提议C++需要一种机制来解决这个问题,所以就催生了模板的产生,最后经标准委员会各路专家讨论和发展,就发展成如今的模板,C++第一个正式的标准也加入了模板。

C++模版是一种解决方案,初心是提供参数化容器类和通用的算法(函数),目的就是为了减少重复代码,让通用性和高性能并存,提高C++程序员生产力。

什么是参数化容器类?

首先C++是可以提供OOP(面向对象)范式编程的语言,所以支持类概念,类本身就是现实中一类事物的抽象,包括状态和对应的操作,打个比喻,大多数情况下我们谈论汽车,并不是指具体某辆汽车,而是某一类汽车(某个品牌),或者某一类车型的汽车。

所以我们设计汽车这个类的时候,各个汽车品牌的汽车大体框架(骨架)都差不多,都是4个轮子一个方向盘,而且操作基本上都是相同的,否则学车都要根据不同厂商汽车进行学习,所以我们可以用一个类来描述汽车的行为:

classCarpublic:Car(...);//otheroperationsprivate:Tirem_tire[4];Wheelm_wheel;//otherattributes...};

但这样设计扩展性不是很好,因为不同的品牌的车,可能方向盘形状不一样,轮胎外观不一样等等。所以要描述这些不同我们可能就会根据不同品牌去设计不同的类,这样类就会变得很多,就会产生下面的问题:

这个时候,就希望这个类是可以参数化的(属性参数化),可以根据不同类型的参数进行属性配置,继而生成不同的类。类模板就应运而生了,类模板就是用来实现参数化的容器类。

什么是通用算法?

程序=数据结构+算法

算法就是对容器的操作,对数据结构的操作,一般算法设计原则要满足KISS原则,功能尽量单一,尽量通用,才能更好和不同容器配合,有些算法属于控制类算法(比如遍历),还需要和其他算法进行配合,所以需要解决函数参数通用性问题。举个例子,以前我们实现通用的排序函数可能是这样:

voidsort(void*first,void*last,Cmpcmp);

这样的设计有下面一些问题:

所以要满足通用(支持各种容器),设计复杂度低,效率高,类型安全的算法,模板函数就应运而生了,模板函数就是用来实现通用算法并满足上面要求。

C++模板的实现

C++标准委员会采用一套类似函数式语言的语法来设计C++模板,而且设计成图灵完备(Turing-complete)(详见参考),我们可以把C++模板看成是一种新的语言,而且可以看成是函数式编程语言,只是设计依附在(借助于)C++其他基础语法上(类和函数)。

C++实现类模板(classtemplate)技术

a.定义模板类,让每个模板类拥有模板签名。

templateclassX{...};

上面的模板签名可以理解成:X;主要包括模板参数和模板名字X(类名),基本的语法可以参考《C++Templates:TheCompleteGuide》,《C++primer》等书籍。

模板参数在形式上主要包括四类,为什么会存在这些分类,主要是满足不同类对参数化的需求:

c.选好模板类之后,编译器会进行模板类实例化--即带入实际参数的类型或者常量自动生成代码,然后再进行通常的编译。

C++实现模板函数(functiontemplate)技术

模板函数实现技术和模板类形式上差不多:

templateretTypefunction_name(Tt);

其中几个关键点:

C++模板的核心技术

SFINAE-Substitutionfailureisnotanerror

要理解这句话的关键点是failure和error在模板实例化中意义,模板实例化时候,编译器会用模板实参或者通过模板实参推导出参数类型带入可能的模板集(模板备选集合)中一个一个匹配,找到最优匹配的模板定义,

Failure:在模板集中,单个匹配失败;

Error:在模板集中,所有的匹配失败;

所以单个匹配失败,不能报错误,只有所有的匹配都失败了才报错误。

模板特化

模板特化为了支持模板类或者模板函数在特定的情况(指明模板的部分参数(偏特化)或者全部参数(完全特化))下特殊实现和优化,而这个机制给与模板某些高阶功能提供了基础,比如模板的递归(提供递归终止条件实现),模板条件判断(提供true或者false条件实现)等。

模板实参推导

模板实参推导机制给与编译器可以通过实参去反推模板的形参,然后对模板进行实例化,具体推导规则见参考;

模板计算

模板参数支持两大类计算:

一类是类型计算(通过不同的模板参数返回不同的类型),此类计算为构建类型系统提供了基础,也是泛型编程的基础;一类是整型参数的算术运算,此类计算提供了模板在实例化时候动态匹配模板的能力;实参通过计算后的结果作为新的实参去匹配特定模板(模板特化)。

模板递归

模板递归是模板元编程的基础,也是C++11变参模板的基础。

C++模版的应用场景

C++Library:

可以实现通用的容器(Containers)和算法(Algorithms),比如STL,Boost等,使用模板技术实现的迭代器(Iterators)和仿函数(Functors)可以很好让容器和算法可以自由搭配和更好的配合;

C++typetraits

通过模板技术,C++typetraits实现了一套操作类型特性的系统,C++是静态类型语言,在编译时候需要对变量和函数进行类型检查,这个时候typetraits可以提供更多类型信息给编译器,能让程序做出更多策略选择和特定类型的深度优化,TypeTraits有助于编写通用、可复用的代码。

C++创始人对traits的理解:

"Thinkofatraitasasmallobjectwhosemainpurposeistocarryinformationusedbyanotherobjectoralgorithmtodetermine"policy"or"implementationdetails".-BjarneStroustrup

而这个技术,在其他语言也有类似实现,比如go的interface,java的注解,反射机制等。

Templatemetaprogramming-TMP

随着模板技术发展,模板元编程逐渐被人们发掘出来,metaprogramming本意是进行源代码生成的编程(代码生成器),同时也是对编程本身的一种更高级的抽象,好比我们元认知这些概念,就是对学习本身更高级的抽象。TMP通过模板实现一套“新的语言”(条件,递归,初始化,变量等),由于模板是图灵完备,理论上可以实现任何可计算编程,把本来在运行期实现部分功能可以移到编译期实现,节省运行时开销,比如进行循环展开,量纲分析等。

Policy-BasedClassDesign

C++Policyclassdesign首见于AndreiAlexandrescu出版的《ModernC++Design》一书以及他在C/C++UsersJournal杂志专栏Generic,参考wiki。通过把不同策略设计成独立的类,然后通过模板参数对主类进行配置,通常policy-baseclassdesign采用继承方式去实现,这要求每个策略在设计的时候要相互独立正交。STL还结合CRTP(Curiouslyrecurringtemplatepattern)等模板技术,实现类似动态多态(虚函数)的静态多态,减少运行开销。

GenericProgramming(泛型编程)

由于模板这种对类型强有力的抽象能力,能让容器和算法更加通用,这一系列的编程手法,慢慢引申出一种新的编程范式:泛型编程。泛型编程是对类型的抽象接口进行编程,STL库就是泛型编程经典范例。

C++模版的展望

模版的代价

没有任何事物是完美的,模板设计如此精良也有代价的,模板的代码和通常的代码比起来,

如何降低门槛,对初学者更友好,如何降低复杂性,这个是C++未来发展重要的方向。现代c++正在追求让模板,或者说编译期的计算和泛型约束变简单,constexpr,concept,foldexpression,还有C++20一大堆consteval,constinit,constexprvirtualfunction,constexprdynamiccast,constexprcontainer等等特性的加入就是为了解决这些问题。曾经的递归变成了普通的constexpr函数,曾经的SFINAE变成了concept,曾经的枚举常量变成了constexpr常量,曾经的递归展开变成了foldexpression,越来越简单,友好了。

基于模板的设计模式

随着C++模板技术的发展,以及大量实战的经验总结,逐渐形成了一些基于模板的经典设计,比如STL里面的特性(traits),策略(policy),标签(tag)等技法;Boost.MPL库(高级C++模板元编程框架)设计;AndreiAlexandrescu提出的Policy-BasedClassDesign;以及JimCoplien的curiouslyrecurringtemplatepattern(CRTP),以及衍生Mixin技法;或许未来,基于模板可以衍生更多的设计模式,而这些优秀的设计模式可以实现最大性能和零成本抽象,这个也是C++的核心精神。

模板的未来

随着模板衍生出来的泛型编程,模板元编程,模板函数式编程等理念的发展,将来也许会发展出更抽象,更通用编程理念。模板本身是图灵完备的,所以可以结合C++其他特性,编译期常量和常量表达式,编译期计算,继承,友元friend等开阔出更多优雅的设计,比如元容器,类型擦除,自省和反射(静态反射和metaclass)等,将来会出现更多优秀的设计。

希望本文对想学习C++的同学有一定的帮助,如果精通了C++,学Java,C#,go,Python,Rust等这类的语言将是非常轻松的!

THE END
1.什么是算法?算法设计有哪些基本方法?算法基本设计方法什么是算法?算法设计有哪些基本方法? 算法是解决问题的一种方法或过程,它是一组有限的、明确的步骤,用于解决特定问题或执行特定任务。算法通常具有五个基本特征:输入、输出、确定性、有限性和可行性。 算法设计的基本方法包括以下几种: 列举法:通过列出所有可能的情况并检验条件满足性来解决问题。这种方法简单但当https://blog.csdn.net/m0_61505785/article/details/144050327
2.算法就是设计HackerVirus总结一下,本文介绍了插入排序体现的算法套路,即重用与增量有序的设计思想,另外也介绍了任一元素如何完成插入排序这一标准作业,最后演示了代码实现。 用一只海龟来引入“递归”,是有一些滑稽,但也没有关系。可能你更喜欢的是海龟而不是无穷的递归调用,那递归长什么样呢? https://www.cnblogs.com/Leo_wl/p/10952609.html
3.《算法设计与分析》是学什么的?和《数据结构》一样吗?谢谢!三者都不一样 通俗点说,算法就是解决问题的方法,因为和计算密切相关,所以不交方法,叫算法 数据结构https://developer.aliyun.com/ask/125539
4.的自动驾驶决策规划算法工程师是做什么的工作内容描述BOSS直聘自动驾驶决策规划算法工程师职位百科,介绍自动驾驶决策规划算法工程师岗位信息:包括岗位职责(自动驾驶决策规划算法工程师是做什么的?)以及不同工作经验自动驾驶决策规划算法工程师的任职要求和岗位工作内容描述,帮您快速定位,并能通过自动驾驶决策规划算法工https://www.zhipin.com/baike/b100120/6509ed8c622d892e1nR829y-GVNS.html
5.算法设计(2021年人民邮电出版社出版的图书)《算法设计》是2021年3月人民邮电出版社出版的图书,作者是[美] 乔恩·克莱因伯格(Jon Kleinberg),本书围绕算法设计进行组织,对每种算法技术用多个典型范例进行分析,把算法的理论跟实际问题结合起来,具有很大的启发性。内容简介 这是一本关于算法设计和分析的经典教材。本书围绕算法设计进行组织,对每种算法技术https://baike.baidu.com/item/%E7%AE%97%E6%B3%95%E8%AE%BE%E8%AE%A1/59777089
6.学习前端算法前你需要了解的‘大O表示法’腾讯云开发者社区那么应该怎么比较不同算法之间的优劣呢?答:应该从时间与空间两方面入手。 本文主要带你了解什么是大O表示法,但是在了解大O表示法之前,你有必要了解什么是算法。 读完本文,你将了解到: 什么是算法 算法设计的要求 算法的好坏评定标准 大O表示法 什么是算法? https://cloud.tencent.com/developer/article/1655539
7.《算法》教学设计优秀教案.pdf《算法》教学设计-优秀教案.pdf 8页内容提供方:jijifujiji 大小:325.9 KB 字数:约3.61万字 发布时间:2021-12-05发布于江苏 浏览人气:647 下载次数:仅上传者可见 收藏次数:0 需要金币:*** 金币 (10金币=人民币1元)《算法》教学设计-优秀教案.pdf 关闭预览 想预览更多内容,点击免费在线预览全文 https://m.book118.com/html/2021/1205/8012022013004052.shtm
8.第三章算法的基础知识教学设计一、教学基本信息 学科 信息技术 授课老师 课题 算法 授课年级 高一 教材 普通高中教科书 信息技术 必修1 数据与计算 (粤教版) 二、教学分析 教材分析 本节选自广东教育出版社《信息技术必修一 数据与计算》的第三章《算法基础》,是信息技术课程的核心内容之一。算法作为解决问题的明确指令集合,是计算机程序设计的https://www.zxxk.com/soft/43875726.html
9.小林手撕LRU算法!如果采用暴力遍历所有主机的方式来找到超时的主机,在面对只有几百台主机的场景是没问题,但是这个算法会随着主机越多,算法复杂度也会上升,程序的性能也就会急剧下降。 所以,我们应该设计一个可以应对超大集群规模的宕机判断算法。 我们先来思考下,心跳包应该有什么数据结构来管理? https://www.51cto.com/article/672356.html
10.字节跳动33:设计模式(看坦克大战一期项目) 4:redis 5: zookeeper 6: mysql调优课程 7:算法(核心) 8:网络(netty网游后端项目),应届生工程项目经验为基本为0,这个项目被视为加分项目,所以被死磕Java。 9.简历指导 那既然学习路线已经有了,是不是缺少对应的文档和视频来学习了呢?小编一一给大家介绍! https://maimai.cn/article/detail?fid=1663985877&efid=TP99-4Gnjz5uI46gYIbONQ
11.算法描述和软件设计说明书对基于互联网大数据的事件智能抓取和画像系统进行算法描述和软件设计说明。 1.2 项目背景 项目背景:随着互联网大数据的发展,各种大数据的分析对各行业都产生了不同程度的影响。网站数据、社交媒体数据等是互联网大数据的重要组成部分。对于民航业领域,社会事件的发生,会很大程度影响旅客的出行需求变化,从而影响航空公司飞机https://www.jianshu.com/p/e05581327a5c
12.新闻生产中的算法风险:成因类型与对策设计算法时,设计者需要用数据对算法进行训练。训练时采用的数据和实际输入的数据在数据质量上重合度愈高,愈能得出符合预期目标的结论数据。如果用于训练算法的数据存在缺陷(如不完整、陈旧、不相关),无论算法设计得多么完美,最后的数据输出也是错误的。如果训练算法的数据本身包含偏见,就会导致“偏见进,偏见出”。 https://www.media.sdu.edu.cn/info/1002/7926.htm
13.高中信息技术课程标准信息技术科目的选修部分包括“选修1:算法与程序设计”“选修2:多媒体技术应用”“选修3:网络技术应用”“选修4:数据管理技术”和“选修5:人工智能初步”五个模块,每个模块2学分。选修部分强调在必修模块的基础上关注技术能力与人文素养的双重建构,是信息素养培养的继续,是支持个性发展的平台。模块内容设计既注重技术深https://www.fqkhzx.cn/index/article/view/id/94.html
14.电商嘲下“智能导购机器人”的原理与设计步骤人人都是产品经理电商场景下“智能导购机器人”的原理与设计步骤 电商行业中,导购扮演着非常重要的角色——既触达客户解答产品疑惑,又能够通过沟通推广销售产品。那么在电商场景中,我们就可以利用智能导购,通过多轮会话的方式来完成导购流程 一、什么是“智能导购”? 我们在逛商店时候,有时候不知道买哪一款商品,需要找导购人员咨询。https://www.woshipm.com/pd/3434517.html
15.学术研究政治与法律孙祁:规范生成式人工智能产品提供者的生成式人工智能产品的提供者在数据来源、算法设计等决定人工智能生成内容的核心要素方面充当着“把关人”和决定者的角色,因此,应明确其是生成式人工智能产品的责任主体。基于此,最近发布的《生成式人工智能服务管理办法(征求意见稿)》明确规定生成式人工智能产品的服务提供者应承担产品生成内容的生产者责任以及个人信息https://ilaw.sass.org.cn/2023/0821/c2514a552849/page.htm