纠纷奇闻作文社交美文家庭
聚热点
家庭城市
爱好生活
创业男女
能力餐饮
美文职业
心理周易
母婴奇趣
两性技能
社交传统
新闻范文
工作个人
思考社会
作文职场
家居中考
兴趣安全
解密魅力
奇闻笑话
写作笔记
阅读企业
饮食时事
纠纷案例
初中历史
说说童话
乐趣治疗

C模板元编程系列专题2模板特化的概念从何而来

8月8日 火云谷投稿
  0。前言
  C里的模板能做什么呢?它好比C语言中的宏、C和Java中的自省(restropection)和反射(reflection),是C语言的外延。更极端一点地理解:它是一门新的图灵完备的编程语言(也就是说,C模板能实现图灵机模型里的全部功能)。在《ModernCDesign》中,作者抛出了以下几个问题:
  (1)如何撰写更高级的C程式?
  (2)如何应付即使在很干净的设计中仍然像雪崩一样的不相干细节?
  (3)如何构建可复用组件,使得每次在不同程式中应用组件时无需大动干戈?
  解决上述问题的方法就是模板元编程。元(meta)本身就是个很抽象(abstract)的词,因为它的本意就是抽象。元编程,也可以说就是编程的抽象。用更好理解的说法,元编程意味着你撰写一段程序A,程序A会运行后生成另外一个程序B,程序B才是真正实现功能的程序。那么这个时候程序A可以称作程序B的元程序,撰写程序A的过程,就称之为元编程。
  C中,元编程的手段,可以是宏,也可以是模板。
  在继续阅读下面的内容之前,请先回顾下我之前的文章:
  C类模板和实例化
  C性能优化系列专题1:优化string的使用(上)
  C模板元编程系列专题1:入门1、为什么需要泛型编程:从宏到模板,再到元编程
  如果元编程中所有的变量(或者说元编程的参数),都是类型,那么这样的编程,我们有个特定的称呼,叫泛型。
  模板的发明,仅仅是为了做和宏几乎一样的替换工作吗?可以说是,也可以说不是。
  一方面,模板可以用来替换类型,这点和宏没什么区别。只是宏在编译阶段基于文本做纯粹替换,被替换的文本本身没有任何语义。而模板会在分析模板时以及实例化模板的时候都会进行检查,而且源代码中也能与调试符号一一对应,所以无论是编译时还是运行时,排错都相对简单。
  另一方面,模板和宏也有很大的不同,模板最大的不同在于它是可以运算的。我们来看一个例子:voidAdd(uint8t,unit8t){}
  上述函数实现了一个uint8t和uint8t类型的加法运算,如果现在要实现int16和int16类型的加法运算,该怎么办呢?简单点的方法如下:if(type8){Add(uint8t,uint8t)}elseif(type16){Add(uint16t,uint16t)}
  但是这里有两个难点:首先,if(typex)是不存在于C中的其次,即便存在获取变量type的方法(Boost。Any中的typeid),我们也不希望它在运行时判断,这样会变得很慢。是否可以不引入ifelse,在编译期就把Add的方法确定呢?
  有人说,重载、虚函数也能解决如上问题:voidAdd(uint8t,uint8t){}voidAdd(uint16t,uint16t){}
  甚至在C语言中定义新的结构体Variant或使用void也能解决该问题:structVariant{union{uint8x;uint16y;}uint32ttypeId;};
  没错,但是如果我还有uint9t、uint10t等各种类型的加法运算呢?Anyway,不管是哪种方法都很难避免ifelse的存在。
  模板与上述这些方法最大的区别在于:模板无论其参数或者是类型,它都是一个编译期分派的方法。编译期就能确定的东西既可以做类型检查,编译器也能进行优化,砍掉任何不必要的代码执行路径。2、类模板的特化:模板世界里的ifelse2。1根据类型执行代码
  我们先来看看一个模板的例子:templatetypenameTTAddFloatOrMulInt(Ta,Tb);我们希望这个函数在T是float的时候做加法运算,在T是int类型的时候做乘法运算
  那么当传入两个不同类型的变量,或者不是int和float变量,编译器就会提示错误。
  从能力上来看,模板能做的事情都是编译期完成的。编译期完成的意思就是,当你编译一个程序的时候,所有的量就都已经确定了。比如下面的例子:inta3,b5;VariantaVar,bVaVar。setInt(a);我们新加上的方法,怎么实现的无所谓,大家明白意思就行了。bVar。setInt(b);VariantresultAddFloatOrMulInt(aVar,bVar);
  从上述代码中我们可以看到:aVar和bVar都一定会是整数。所以如果有合适的机制,编译器就能知道此处的AddFloatOrMulInt中只需要执行int路径上的代码,而且编译器在此处也能单独为int路径生成代码,从而去掉那个不必要的if。在模板代码中,这个合适的机制就是指特化和部分特化(PartialSpecialization),后者也叫偏特化。2。2、如何写模板特化的代码
  1。0版本伪代码intfloatAddFloatOrMulInt(a,b)类的静态函数{if(typeisint){}elseif(typeisfloat){}}voidfoo(){floata,b,c;caddFloatOrMulInt(a,b);intx,y,z;zaddFloatOrMulInt(x,y);}
  2。0版本函数重载floatAddFloatOrMulInt(floata,floatb){}intAddFloatOrMulIntDo(inta,intb){}voidfoo(){floata,b,c;cAddFloatOrMulInt(a,b);intx,y,z;zAddFloatOrMulInt(x,y);}
  3。0版本纯模板这个是给float用的。templatetypenameTclassAddFloatOrMulInt{TDo(Ta,Tb){}};这个是给int用的。templatetypenameTclassAddFloatOrMulInt{TDo(Ta,Tb){}};voidfoo(){floata,b,c;我们需要cAddFloatOrMulIntfloat::Do(a,b);。。。觉得哪里不对劲。。。啊!有两个AddFloatOrMulInt,class看起来一模一样,要怎么区分呢!}
  好吧,问题来了!如何要让两个内容不同,但是模板参数形式相同的类进行区分呢?特化!特化(specialization)是根据一个或多个特殊的整数或类型,给出模板实例化时的一个指定内容。
  4。0版本模板特化首先,要写出模板的一般形式(原型,即初始化,不能省)templatetypenameTclassAddFloatOrMulInt{staticTDo(Ta,Tb)注意这里必须得是静态方法!!!{returnT(0);}};其次,我们要指定T是float时候的代码:templateclassAddFloatOrMulIntfloat{public:staticfloatDo(floata,floatb){}};再次,我们要指定T是int时候的代码,这就是特化:templateclassAddFloatOrMulIntint{public:staticintDo(inta,intb){}};intfoo(){returnAddFloatOrMulIntfloat::Do(1。0,2。0);}intmain(){std::coutfoo();输出结果3。0}
  解释:我们这个模板的基本形式是什么?templatetypenameTclassAddFloatOrMulI但是这个类,是给T是int的时候用的,于是我们写作classAddFloatOrMulI当然,这里编译是通不过的。但是它又不是个普通类,而是类模板的一个特化(特例)。所以前面要加模板关键字template,以及模板参数列表template这里要填什么?classAddFloatOrMulI最后,模板参数列表里面填什么?因为原型的T已经被int取代了。所以这里就不能也不需要放任何额外的参数了。所以这里放空。templateclassAddFloatOrMulIntint{。。。针对int的实现。。。}Done!
  至此,第一个模板特化的代码已经写完了。这里的AddFloatOrMulInt如同是一个函数,却只能在编译期间执行。如果你体味到了这一点,那么恭喜你,你的模板元编程已经开悟了。3、总结
  本文核心只讲了两个问题:一是为什么需要泛型编程,重点介绍了宏、模板和元编程的关系;二是模板类的特化代码如何编写。关于特化,还有很多细节知识,在之后的文章中我们继续探究,另外将还介绍偏特化等知识点,敬请期待。
投诉 评论 转载

CPUi38100这几天价格突然暴涨,还值不值的入手呢长久以来酷睿i3都是采用双核心四线程的设计,但是全新的八代酷睿处理器采用了四核心四线程的设计,在规格上甚至超越上代i5,性能上更是没得说,同时这款处理器对于吃鸡的支持也很不错,……2021LPL年度纪录片不破不立全球总决赛篇上线时隔一月,历IT之家12月11日消息,《英雄联盟》2021LPL年度纪录片《不破不立》第一集于11月20日在B站上线。首集EDG篇讲述银龙骑士在2021LPL春夏季赛的一路历程,最终不破不……英雄联盟LNG官宣Doinb正式加入战队,担任中单位IT之家12月10日消息,今日下午,LNGaming电子竞技俱乐部发布最新俱乐部人员公告,Doinb正式加入战队,担任中单位。公告原文:经过俱乐部与选手金泰相(ID:LN……C模板元编程系列专题2模板特化的概念从何而来0。前言C里的模板能做什么呢?它好比C语言中的宏、C和Java中的自省(restropection)和反射(reflection),是C语言的外延。更极端一点地理解:它是……奇瑞汽车做自己就好,何必争当车圈鸿星尔克?善举精神可嘉,盲目攀比打肿脸充胖子不可取。鸿星尔克火了,其它各行各业的潜在鸿星尔克们,还是克制一点的好,不必急着争当XX圈鸿星尔克。郑州及河南的一场水灾,牵动无数国……新证据表明,8400万年前的真极漂移,差点让地球翻了车我们知道,真极漂移(TPW)偶尔会使整个行星和卫星相对于它们的轴发生倾斜,但目前,我们还不清楚这种情况在地球上发生的频率。近日,一项新研究提供了大约8400万年前发生的此……自动驾驶计算芯片公司黑芝麻智能完成数亿元战略轮及C轮融资自动驾驶计算芯片厂商黑芝麻智能于9月22日宣布今年已经完成数亿美元的战略轮及C轮两轮融资。战略轮由小米长江产业基金,富赛汽车等参与投资;C轮融资由小米长江产业基金领投,闻泰战投……哆啦A梦版天猫精灵见过么创意满满的天猫精灵您了解一下双11马上就要到了,你想好了要入手些啥了没?亲,智能音箱设备您不妨了解一下呀。说到智能音箱设备,天猫精灵、百度、小米必须拥有姓名。这三大品牌在国内智能音箱市场长期呈现三足……英雄联盟12。2版本更新新英雄泽丽上线,无限乱斗回归IT之家1月20日消息,据《英雄联盟》官方消息,《英雄联盟》12。2版本现已更新,新英雄祖安花火泽丽上线,无限乱斗模式回归。《英雄联盟》表示,为了增添年味,无限乱斗模式将……新鲜早科技丨谷歌苹果遭意大利监管机构罚款小米宣布新一轮组织架21世纪经济报道记者杨清清实习生史贝琪综合报道早上好,新的一周又开始了。在过去的这个周末里,科技行业发生了哪些有意思的事情?来跟21tech一起看看吧。【巨头风向标……哔哩哔哩UP主大三做的游戏,最终登上了B站新品发布会IT之家8月10日消息8月4日,在2021bilibili游戏新品发布会上,B站一次性发布了16款游戏新作。除10款B站独家代理游戏外,B站还公布了6款自研游戏。这也是自201……自研游戏首次亮相,B站密集发布新游戏6款自研10款独家代理IT之家8月4日消息今日晚间,以你的幻想世界为主题的2021bilibili游戏新品发布会举行。IT之家了解到,此次发布会一次性发布了16款游戏新作。其中,除10款B站独……
快看看京郊这11条又美又险的盘山公路,您都自驾过哪一条?平时多给孩子做这个吃,酥脆软糯,好吃不贵,再忙也不能亏待孩子官宣!全国首批5条示范步行街公布双系统怎么删除一个(双系统怎样卸载其中一个)我国一水上村庄,被称东方ampampquot威尼斯ampam加拿大两任国防参谋长性侵女下属被查时,士兵们正在南海卖命送死科普下淝水之战简介科普下黄鹤楼是什么体裁的诗小米手机怎么预定(小米之家预定手机流程)档案调动流程(人才市场档案调动流程)都挺好挺火的,苏大强又要去看林芝桃花了,你还不去吗?百度与高德导航对比
游戏机造句用游戏机造句大全性药对人身体的6个伤害还在穿阔腿裤吗?这条裤子才是真洋气给儿子的一封信来宾属于哪个市(广西来宾女人的特点)京东卖家店铺动态的吸粉技巧该死造句用该死造句大全与你在一起作文长牙期宝宝豢养原则火锅外卖的锅是一次性的吗火锅外卖的锅还收走吗男子过年送礼买9万余元茅台,发现所购62瓶全为假货,你怎么看风靡一时的卫星锅,为何被国家禁用?难道它真能发现外星人?

友情链接:中准网聚热点快百科快传网快生活快软网快好知文好找美丽时装彩妆资讯历史明星乐活安卓数码常识驾车健康苹果问答网络发型电视车载室内电影游戏科学音乐整形