C模板22(基于traits的泛型程序设计)
熟悉STL的了解traits,特别是typetraits,提供了很多traits,称为元函数,可以基于某个类型计算出所需的类型。
Policy其实也是一种trait,只是后者强调类型,而前者重视行为。AndreiAlexandrescu,ModernCDesign的作者认为:
policies和policyclasses有助于我们设计出安全、有效率且具高度弹性的设计元素,所谓policy,就是用来定义一个class和classtemplate的接口,该接口由下列之一或全部组成:内隐型别定义(innertypedefinition)、成员函数和成员变量。
下面通过一个简单的例子来说明一下:计算某个序列的和。templatetypenameTTaccumulate(constTbegin,constTend){Tsum{};while(begin!end){sumbegin;begin;}returnsum;}
上面代码很容易理解,不过其间也有几个隐式约束:序列必须是连续存放的,通过移动begin最终可以到达end,T类型可以通过缺省初始化为零值,其解引用的值能够使用运算。intnum〔〕{1,2,3,4,5};accumulate(num,num5);15charhello〔〕hello,world;accumulate(hello,hellosizeof(hello)1);120??
好像有点问题,哦,原因是char的数值范围太小了,作为返回值的类型在累加计算过程中它溢出了。解决方式可以应用traits,定义模板参数T的累加和返回值类型时的关联类型(元函数)。templatetypenameTstructaccumulatetraits{usingtypeT;};templatestructaccumulatetraitschar{usingtypeint;};templatestructaccumulatetraitsshort{usingtypeint;};templatetypenameTusingaccumulatetraitsttypenameaccumulatetraitsT::type;templatetypenameTaccumulatetraitstTaccumulate(constTbegin,constTend){accumulatetraitstTsum{};while(begin!end){sumbegin;begin;}returnsum;}
我们定义了一个trait(元函数)accumulatetraits,用来计算类型参数T的返回值类型:缺省返回T自己,对于size小于int的类型(如char,short)则返回int。我们还仿照C14的做法,定义了acculatetraitst,方便用户使用。intnum〔〕{1,2,3,4,5};accumulate(num,num5);15charhello〔〕hello,world;accumulate(hello,hellosizeof(hello)1);1160
这回运行一切正常。accumulate模板函数对付基本数值类型足够了,但是accumulatetraitstTsum{};
这里累加和sum变量的零值初始化的依赖有点让人担心(使用类型的缺省构造,且符合零值语义)。如果用于自定义类型,一不小心这里很容易挂掉。我们未雨绸缪,再添加一个policy,用来定义返回值类型的零值,这样将来如果需要支持的类型有特定的零值构建方式,可以使用特化技术来添加对此类型的支持。templatetypenameTstructaccumulatetraits{usingtypeT;inlinestaticconstexprtypezerovalue0;};templatestructaccumulatetraitschar{usingtypeint;inlinestaticconstexprintzerovalue0;};templatestructaccumulatetraitsshort{usingtypeint;inlinestaticconstexprintzerovalue0;};templatetypenameTusingaccumulatetraitsttypenameaccumulatetraitsT::type;templatetypenameTaccumulatetraitstTaccumulate(constTbegin,constTend){accumulatetraitstTsumaccumulatetraitsT::zerovalue;while(begin!end){sumbegin;begin;}returnsum;}
如果有个自定义类型Foo,它定义了自己的返回值类型,还有特有的初始化方式,我们可以针对它添加特化templatestructaccumulatetraitsFoo{usingtypetypenameFoo::ResultType;inlinestaticconstexprFoozerovalueFoo::Initialize(0);};
这种声明式的(通过添加定义)无缝、透明地功能扩展方式也是STL功能扩展的一种方式,一旦你理解了其间的运作方式,会大大提升你的编程效率。这里模板参数T的关联属性通过trait(返回值类型)或policy(零值的获取方式),可以非常方便地配置、扩展accumulate函数,使之适用于各种类型。比如说这里的累和算法,也可以通过定义一个policy来定制化,缺省内置数值类型我们使用运算符,对于自定义类型,可以使用特定的累加方式。
最后补充一点:上面traits的应用是固定的,你无法更换,我们可以将traits类型也参数化,这样在特定场合,你可以用其他的traits来替换它,只要你的traits也提供了同样的traits定义。templatetypenameT,typenameATaccumulatetraitsTautoaccumulate(constTbegin,constTend){typenameAT::typesumAT::zerovalue;while(begin!end){sumbegin;begin;}returnsum;}
我们把traits类型定义为第二个模板参数,它有一个缺省值,就是我们之前定义好的traits类,通常你不需要关注它,除非你有特定的需求,需要替换缺省实现。看着是不是有点眼熟?是啊,STL的容器模板类里就有很多类似的应用。
君实RdRp抑制剂的隐忧丨与3CL蛋白酶抑制剂的对比说起君实生物旗下的口服核苷类抗新型冠状病毒(SARSCoV2)药物VV116(JT001)的一项三期临床研究数据发表在权威期刊《新英格兰医学杂志》,结论为疗效不输辉瑞的新冠药Pax……
辽宁八个乡村入选2022年中国美丽休闲乡村辽宁的乡村这样美辽宁八个乡村入选2022年中国美丽休闲乡村日前,农业农村部公布2022年中国美丽休闲乡村推介结果。经各省遴选推荐、专家评审和网上公示,全国255个乡村入选……
数据世界杯D组法国笑看沙特成为C组大BOSS阿根廷能否避开法2022世界杯世界杯16强阿根廷法国梅西莱万多夫斯基波兰2022年卡塔尔世界杯CD组积分榜2022年卡塔尔世界杯小组赛将迎来CD两组最后一场角逐,C组出线形势不明朗……
欧国联德国VS匈牙利同德一心留力世界杯德国近况第一:9月份刚出本次集训欧国联赛事,就有三人因为感染而离队,一门队长诺伊尔、格雷茨卡呈现新冠感染,后者布兰特是因为密接,通过各大媒体预测首发,后腰位置相对较缺,京……
关于育娃把选择权交给孩子我家宝宝19个月,发现养娃是件很难的事情。因为养娃的过程有预期,我们都希望宝宝好,这个好是全方面的,包括了身体的健康、物质的丰足、精神的愉悦等等,是综合的好。但孩子的成长……
苹果14Pro太惊艳价格不变,暗紫色灵动岛超乎想象万众期待的iPhone14Pro系列正式登场了!相比于苹果14系列,14Pro系列改动十分之多,可以看出,这一次苹果为了打造14Pro系列下足了功夫,小编已经整理好了,下面就来……
实验发现金属玻璃中类液原子根据原子运动状态的不同,物质通常可分为固、液、气三种状态。三态之间有明显区别,例如,液态的水和固态的冰,固液两相即使充分混合仍会存在清晰的边界。然而,一些最新的研究却挑战我们对……
机械键盘的外观设计有什么设计技巧?深圳牧本设计机械键盘外观设计涉及设备的形状、颜色、材料等方面,今天我们来具体介绍一些机械键盘外观设计的一些设计技巧。一、外壳流畅设计对于机械键盘产品的外观设计,我们需要注意机械……
10月9日足球赛事前瞻,旅游的那些小事球仟任碎碎念:昨天给大家说了说宜昌的温差之大,今天给朋友们分享一下关于宜昌的风土人情。宜昌是我非常喜欢的一座城市,本人闲来无事就喜欢去旅游,宜昌这座城市我去过很多次,当然近几年……
回国就狂了!拿铜牌不服,张本智和发声,队友马龙双手都在颤抖成都世乒赛已经落下帷幕,很多外国运动员已经回到自己的国家,而有的运动员则是奔赴下一个战场,那就是WTT冠军赛,本月19日WTT冠军赛将在中国澳门举行,据悉该项赛事总奖金为80万……
肾结石,到底能有多痛?谈到肾结石问题,真正被结石折磨过的都应该清楚,确实是疼!医学上把疼痛分为10级,分娩为9级疼痛,而肾绞痛可以达到8级!大多数人认为肾结石只有在夏天高发,其实冬季发生肾结石……
iPhone14同价能买到的折叠屏,华为三星OPPO软硬结合如今正在双十一期间,相信不少人都在准备换机中。而相比于选择传统直板机,折叠屏手机作为如今已经逐渐成熟、更有生产力的选择,同样成为了许多人的换机目标。今天,我就来给大家推荐三款用……