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.

奇异递归模板模式(Curiously Recurring Template Pattern,CRTP)相关推荐

  1. 浅谈 CRTP:奇异递归模板模式

    浅谈 CRTP:奇异递归模板模式 前言 建议先看一遍文末的参考资料! 建议先看一遍文末的参考资料! 建议先看一遍文末的参考资料! 思维导图 一.CRTP 是什么 CRTP 全称 : Curiously ...

  2. 【C++】CRTP:奇异递归模板模式

    1. 什么是CRTP? 什么是CRTP?CRTP的全称是Curiously Recurring Template Pattern,即奇异递归模板模式,简称CRTP.CRTP是一种特殊的模板技术和使用方 ...

  3. 关于CRTP(Curiously Recurring Template Prattern)的使用

    在阅读frameworks/rs/cpp/util/RefBase.h之LightRefBase时,我记得<C++设计新思维>里对这种用法是有过介绍的,可是今天翻箱倒柜,怎么都找不到那本奇 ...

  4. 2022年6月11日记:王老师的春天,奇异的模板模式

    推荐一个 零声学院 免费公开课程,个人觉得老师讲得不错,分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S ...

  5. c#中的奇异递归模式

    奇异递归模式,Curiously Recurring Template Pattern (CRTP) ,作用是能使父类中能够使用子类的信息.下面是我对这个问题的分析过程. 按照一般的继承关系,父类是无 ...

  6. Java设计模式之模板模式【通过LOL选英雄案例】

    初衷 设计模式(Design Pattern)引用百度百科中的一句话,就是一套被反复使用.多数人知晓的.经过分类的.代码设计经验的总结.实际上在我们的实际编码中到处都有设计模式的影子,比如最常用的单例 ...

  7. 模板模式(Template Pattern)

    23种软件设计模式完整教程 使用场景: 模板模式通常又叫模板方法模式(Template Method Pattern)是指定义一个算法的骨架,并允许子类为一个或者多个步骤提供实现.适用于流程标准化的业 ...

  8. 不重复发明轮子 -- 模板模式 (Template Pattern) 介绍 使用场景案例分析 优缺点 及代码演示

    一句话概括: 一个抽象类公开定义了执行它的方法的方式/模板,它的子类可以重写方法实现,但调用将以抽象类中定义的方式进行. 补充介绍: 模板模式(Template Pattern)使得子类可以不改变一个 ...

  9. 3.5 模板模式(Template Pattern) -《SSM深入解析与项目实战》

    文章目录 3.5 模板模式(Template Pattern) 3.5.1 策略模式与模板模式 3.5.2 场景实例 抽象模板角色&具体模板角色 抽象模板类 具体模板角色 测试类 演示结果 总 ...

最新文章

  1. Ubuntu 上安装rust
  2. java 虚拟机 初始化_Java虚拟机 类初始化 阶段
  3. php yof框架特点_腾讯正式开源高性能超轻量级 PHP 框架 Biny
  4. 控件包含代码块(即 ),因此无法修改控件集合 (转自http://blog.csdn.net/wangchao1982/archive/2007/11/19/1892472.aspx)...
  5. 数据结构:栈和列之如何用两个队列实现一个栈?两个栈实现一个队列?
  6. appender log4j 扩展_Log4j扩展使用--输出地Appender
  7. CRM 客户端程序开发:设置实体表单界面字段的值
  8. 彭亚雄:7月24日阿里云上海峰会企业存储大神
  9. python打包exe与反编译exe文件与防止反编译方式生成exe
  10. 如何区分网线是几类的_几类网线怎么区分
  11. Matlab更改计算机用户名
  12. 【转载】《周一清晨的领导课》读书笔记!!!
  13. OpenCV4.3 Java 编程入门:离散傅里叶变换
  14. java 四舍六入五成双_【数据小常识】“四舍六入五成双”
  15. 以太网,令牌网,FDDI,ATM是什么?有什么区别?
  16. SAP中采购订单关于收货和发票三种不同控制情况的分析
  17. 4.花瓣特效----js+旋转+位移+随机颜色+随机位置
  18. 一个35岁男人的自学编程之路
  19. Nature子刊:基于静息态EEG功能连接模式识别精神疾病亚型
  20. h5滚动时侧滑出现_HTML5移动端触摸事件以及滑动翻页效果

热门文章

  1. 【旅行】——出发!露营去。
  2. java增删改查_Java程序员你真的甘心只做增删改查吗
  3. 计算机无法上网的软件故障,解决你99%无法联网问题,高手教你只用1招轻松搞定...
  4. php获取其他php文件变量值,php 引入其他文件中的变量
  5. 网站开发与服务器匹配,合格的网站开发员应当深入考虑站点框架搭建与SEO优化的关系...
  6. java多核并行计算_谈谈Java任务的并行处理
  7. 全自动洗衣机维修教程
  8. 硬盘安装linux_buffalo ls-wvl 简便安装debian 10
  9. oracle自带的加密函数,oracle 的加密解密函数
  10. Eclipse中获取html jsp 标签的属性提示信息方法