奇异递归模板模式(Curiously Recurring Template Pattern,CRTP)

The Curiously Recurring Template Pattern (CRTP) is a C++ idiom whose name was coined by James Coplien in 1995, in early C++ template code.

The “C” in CRTP made it travel the years in the C++ community by being this: a Curiosity. We often find definitions of what CRTP is, and it is indeed an intriguing construct.

But what’s even more interesting is what CRTP means in code, as in what you can express and achieve by using it, and this is the point of this series.

If you have used CRTP in your own code then you certainly know what it is useful for. In this case you may know most of what’s written in this series of posts (though you may want to give a quick glance to episode #2, just to make sure we’re in line), and you can just skip over to episode #3 where I propose a generic helper for CRTP, that I found helpful when using it in code.

The CRTP, episode One: Definition
The CRTP, episode Two: What it can bring to your code
The CRTP, episode Three: Implementation

What CRTP is

The CRTP consists in:

  • inheriting from a template class,
  • use the derived class itself as a template parameter of the base class.

This is what it looks like in code:

template <typename T>
class Base
{...
};class Derived : public Base<Derived>
{...
};

The purpose of doing this is using the derived class in the base class. From the perspective of the base object, the derived object is itself, but downcasted. Therefore the base class can access the derived class by static_casting itslef into the derived class.

template <typename T>
class Base
{
public:void doSomething(){T& derived = static_cast<T&>(*this);//use derived...}
};

Note that contrary to typical casts to derived class, we don’t use dynamic_cast here. A dynamic_cast is used when you want to make sure at run-time that the derived class you are casting into is the correct one. But here we don’t need this guarantee: the Base class is designed to be inherited from by its template parameter, and by nothing else. Therefore it takes this as an assumption, and a static_cast is enough.

What could go wrong

If two classes happen to derive from the same CRTP base class we likely get to undefined behaviour when the CRTP will try to use the wrong class:

class Derived1 : public Base<Derived1>
{...
};class Derived2 : public Base<Derived1> // bug in this line of code
{...
};

There is a solution to prevent this, that has been proposed by Marek Kurdej in the comments section. It consists in adding a private constructor in the base class, and making the base class friend with the templated class:

template <typename T>
class Base
{
public:// ...
private:Base(){};friend T;
};

Indeed, the constructors of the derived class have to call the constructor of the base class (even if you don’t write it explicitly in the code, the compiler will do his best to do it for you). Since the constructor in the base class is private, no one can access it except the friend classes. And the only friend class is… the template class! So if the derived class is different from the template class, the code doesn’t compile. Neat, right?

Another risk with CRTP is that methods in the derived class will hide methods from the base class with the same name. As explained in Effective C++ Item 33, the reason for that is that these methods are not virtual. Therefore you want to be careful not to have identical names in the base and derived classes:

class Derived : public Base<Derived>
{
public:void doSomething(); // oops this hides the doSomething methods from the base class !
}

The first time I was shown CRTP my initial reaction was: “wait, I didn’t get it”. Then I saw it a couple of other times and I got it. So if you didn’t get how it works, just re-read section 1 a couple of times, and that should do it (if it doesn’t just get in touch and I’ll be happy to talk with you about it).

To tell you the truth, I started by writing a huge blog post about CRTP, which would have been daunting to read completely I think. For that reason I decided to split it up into several logical parts, which constitute the episodes of this series. This post was relatively short, but was necessary to put the basics in place.

Next up: how the CRTP can be useful to your code.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/242680.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

因为征信原因,买房的2万定金没了

近日有一位网友在网上发帖寻求帮助&#xff0c;他自己买了套房&#xff0c;已经向开发商交了2万元定金&#xff0c;但是等他去办理贷款的时候&#xff0c;银行却说他不符合贷款条件&#xff0c;所以按揭贷款没有批下来&#xff0c;最后他要求开发商退还那2万的定金&#xff0c;…

愿你白天有说有笑,晚上睡个好觉

插画&#xff1a;annie.Z-1-手机设置了静音&#xff0c;早晨起来&#xff0c;被十几条未接电话惊醒&#xff0c;准备回拨过去&#xff0c;看到姑姑发来的短信&#xff1a;祝你生日快乐。看了看日历才反应过来&#xff0c;今天是自己的农历生日。打开微信&#xff0c;一朋友发来…

C指针的理解

C指针的理解 指针 &#xff08;编程语言中的一个对象&#xff09;:指针也就是内存地址&#xff0c;指针变量是用来存放内存地址的变量&#xff0c;在同一CPU构架下&#xff0c;不同类型的指针变量所占用的存储单元长度是相同的&#xff0c;而存放数据的变量因数据的类型不同&a…

你以为有白金卡就很牛逼?错!

近段有个朋友办了一张平安银行的白金卡&#xff0c;额度5万元&#xff0c;然后他高兴得不得了&#xff0c;还到处炫耀&#xff0c;以为带个“白金”字就很牛逼&#xff0c;其实不然&#xff0c;表面上看&#xff0c;白金卡虽然高大上&#xff0c;其实也只是一种卡级而已。所以今…

解决Win10下_findnext()异常

在win10中&#xff0c;使用文件遍历函数_findnext会报0xC0000005错误 原因&#xff1a; _findnext()第一个参数”路径句柄”&#xff0c;返回的类型为intptr_t&#xff08;long long&#xff09;&#xff0c;如果定义为long&#xff0c;在win7中是没有问题&#xff0c;但是在…

串口(RS - 232)

串口(RS - 232) 串行接口是将FPGA连接到PC的一种简单方法。我们只需要一个收发模块。 异步发射器 它通过序列化要传输的数据来创建一个信号“TxD”。 异步接收器 它从FPGA外部接收信号“RxD”,并对其进行“反序列化”,以便在FPGA内部轻松使用。 RS-232串行接口是如何工作…

震惊,用过微粒贷的人没资格贷款买房!

在网络借贷非常发达的今天&#xff0c;使用借呗&#xff0c;金条的人应该很多&#xff0c;因为简单方面&#xff0c;随借随还&#xff0c;所以深受广大朋友欢迎。但是这种方便有时候也会给一些朋友带来了巨大的烦恼。用过微粒贷&#xff0c;金条不能贷款买房近日&#xff0c;南…

信用卡PK信用贷款,那个更划算?

信用贷款和信用卡都是解决资金短缺很好的方式&#xff0c;两者都是无抵押无担保&#xff0c;因此成为了很多人解决小额资金难题的首选。但是无抵押贷款和信用卡也是有很大的区别的&#xff0c;所以今天我们就来分析下两者的优劣&#xff0c;看看哪个更划算。申请条件信用贷款&a…

JTAG接口

JTAG接口 JTAG是IEEE标准(1149.1),于20世纪80年代开发,用于解决电子板制造问题。现在,它被更多地用于编程、调试和探测端口。 但是首先,让我们看看JTAG最初的用途——边界测试。 这是一个简单的电子板(也被称为“PCB”的“印刷电路板”),有两个集成电路(“集成电路”),…

全相FFT

作者&#xff1a;桂。 时间&#xff1a;2017-12-02 23:29:48 链接&#xff1a;http://www.cnblogs.com/xingshansi/p/7956491.html 一、相位提取 以正弦信号为例&#xff0c;x sin(2pi*f*tpi)&#xff0c;希望提取phi&#xff1a; 思路1&#xff1a;通过Hilbert变化解决 思路…

现金贷合法吗?

说到现金贷&#xff0c;大家估计都听说过&#xff0c;甚至使用过&#xff0c;因为最近现金贷很火&#xff0c;整顿也很火&#xff0c;新闻充斥了各种平台。现金贷可以说让人欢喜让人优&#xff0c;喜的是&#xff0c;现金贷门槛很低&#xff0c;让那些借钱无门的朋友找到了一个…

I2C接口

I2C接口 I2C总线是一种简单的方法来连接多个芯片,特别是fpga / cpld。 I2C总线的特点 除了电源和接地外,只使用2根电线(命名为“SDA”和“SCL”)可以在同一总线上支持超过100个设备(总线上的每个设备都有一个单独可访问的地址)多主机(例如,两个cpu可以很容易地共享相同的I…

不行是谁决定的呢,明明你眼前就有这么多的可能啊

插画&#xff1a;排骨chop -1- 最近事情繁杂&#xff0c;总觉得精力跟不上&#xff0c;加之天气骤变&#xff0c;有点小感冒&#xff0c;吃了药就想睡觉&#xff0c;躺在床上&#xff0c;回顾最近的几个月&#xff0c;脑子里飘过最多的一句话就是&#xff1a;“坚持就是胜利。…

计算机原码、反码、补码详解

注&#xff1a;之前查找了关于原码、反码、补码的相关资料&#xff0c;张子秋的博客&#xff1a;原码, 反码, 补码 详解讲的比较透彻。为了方便&#xff0c;现将其转载至此&#xff0c;版权归原作者所有。更加深入的分析&#xff0c;可以参考作者的原文。 本文大部分内容来源于…

EPP (Enhanced Parallel Port 增强型并口)

EPP (Enhanced Parallel Port 增强型并口) EPP使与PC的通信快速和容易。 这里我们使用Pluto-P FPGA板与启用epp的PC通信。 EPP是IEEE 1284(并行端口标准)的一部分。 IEEE 1284还定义了SPP和ECP,但EPP提供了两者的最佳特性,即速度和简单性。 EPP的主要特点是: 通过并行端口…

公积金10万元,为何却不能贷款买房?

近日有一朋友&#xff0c;自己和老公公积金加在一起已经超过10万元&#xff0c;可是想用公积金去办理贷款的时候却被拒绝了&#xff0c;这到底是怎么回事呢&#xff1f;其实类似这样的案例最近在很多城市都有发生&#xff0c;继海南停止执行装修提取住房公积金政策之后&#xf…

现金贷平台倒闭后,借的钱是否可以不还?

目前火热的现金贷遭到一盆冷水&#xff0c;国家已经开始着手大力整顿那些不合规的现金贷&#xff0c;凡是没有获得相关放贷资质的就不能从事现金贷业务。在监管重拳整顿之下&#xff0c;很多现金贷已经开始吃不消&#xff0c;甚至有的面临倒闭的风险。11月份&#xff0c;就有媒…

好用的Perl包 Class::Ref

包的链接 https://metacpan.org/pod/Class::Ref 网页上介绍是 Class::Ref - Automatic OO wrapping of container references 就是将一个哈希、数组引用到一个 package 中来使用。 下面给出一个例子&#xff1a; #!/usr/bin/perluse FindBin qw($RealBin); use lib "$…

以太网UDP帧发包设计

以太网UDP帧发包设计 RTL8211 是一片 10M/100M/1000M 自适应以太网收发器&#xff0c;提供 MII/GMII/RGMII 接口的 MAC 连接。 下图为 RTL8211 与 FPGA 的连接关系。 以太网MAC层&#xff08;媒体介入控制层&#xff09;接口介绍 MII 接口 PHY是物理接口收发器&#xff0…

如何学习

读百度学术“机长夫人”的《研究生毕业后&#xff0c;才知道什么是真正的学习》后的笔记和感想 关于学习学习是什么&#xff1f;学习是通过各种途径获得知识和技能的过程。它只是过程和手段&#xff0c;而绝不应该成为目的&#xff0c;它最终是为了改变行为&#xff0c;升级自己…