奇异递归模板模式(Curiously Recurring Template Pattern,CRTP)
来源:互联网 发布:淘宝零食店排行榜 编辑:程序博客网 时间:2024/05/17 23:25
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)
- 奇异递归模板模式( Curiously Recurring Template Pattern,CRTP)1
- C++惯用法:奇特的递归模板模式(Curiously Recurring Template Pattern,CRTP,Mixin-from-above)
- C++惯用法:奇特的递归模板模式(Curiously Recurring Template Pattern,CRTP,Mixin-from-above)
- C++惯用法:奇特的递归模板模式(Curiously Recurring Template Pattern,CRTP,Mixin-from-above)
- C++惯用法:奇特的递归模板模式(Curiously Recurring Template Pattern,CRTP,Mixin-from-above)
- 递归模板模式--The curiously recurring template pattern
- curiously recurring template pattern
- Curiously Recurring Template Pattern
- 关于CRTP(Curiously Recurring Template Prattern)的使用
- CRTP 奇异递归模板模式
- 奇异递归模板模式(CRTP)应用--表达式模板(expression template) 2
- Curiously recurring template pattern (zz)
- Curiously Recurring Template
- 模板模式(Template Pattern)
- 模板模式(Template Pattern)
- 模板模式 Template Pattern
- 模板模式(Template Pattern)
- 复习时间
- Myeclipse:使用Servlet中文出现乱码解决方案
- 组合模式
- 双面柔性线路板网印中 要留意的疑问
- jq和js如何判断checkbox是否选中
- 奇异递归模板模式(Curiously Recurring Template Pattern,CRTP)
- JS用Canvas绘图-基本语法
- Spring Security 参考手册(二)
- easyui-(二)
- java 去除空格、标点符号
- POJ 1797 Heavy Transportation(Dijkstra算法)
- 移动端问题
- 学习opencv第二章课后题4,5
- 【剑指offer+扑克牌顺子+数学建模+模拟】