为什么奇怪的重复模板模式 (CRTP) 有效
why Curiously Recurring Template Pattern (CRTP) works
我遇到了很多关于CRTP是什么的解释,但没有解释它为什么有效。
Microsoft CRTP 在 ATL 中的实现是由 Jan Falkin 独立发现的,也是在 1995 年,他意外地从派生类中派生了一个基类。 Christian Beaumont 第一次看到 Jan 的代码,最初认为它不可能在当时可用的Microsoft编译器中编译。在发现它确实有效之后,克里斯蒂安将整个ATL和WTL设计建立在这个错误的基础上。
例如
template< typename T >
class Base
{
...
};
class Derived : public Base< Derived >
{
...
};
我理解为什么以及何时可以使用它。但我想知道编译器是如何以这种方式工作的。因为在我的脑海中,由于无休止的递归,它不应该工作:类Derived
继承自Base< Derived >
,其中Derived
是从Base< Derived >
继承的类,其中Derived
......等等。
您能否从编译器的角度逐步解释它是如何工作的?
归定义的类型并不罕见:链表也是递归的。它之所以有效,是因为在循环中的某一点,您不需要完成类型,您只需要知道它的名称。
struct LinkedNode {
int data;
LinkedNode *next; // Look ma, no problem
};
在CRTP的情况下,这一点在这里:
Base<Derived>
实例化Derived
的Base
不需要Derived
完成,只需要知道它是一个类类型。 即,以下工作正常:
template <class>
struct Foo { };
struct Undefined;
Foo<Undefined> myFoo;
因此,只要Base
的定义不需要Derived
是完整的,一切都会起作用。
CRTP 被命名为重复出现,因为在
class Derived: public Base<Derived> { ... }
类模板Base
在类Derived
上实例化,该类继承自类Base<Derived>
,而类又是类模板Base
实例化在继承Base<Dervied>
Derived
...等等。
上面Derived
的名称在其自己的定义中使用,在尚未完全定义的上下文中,因此,这使得Derived
成为不完整的类型。 Base<Derived>
正在实例化在当时不完整的类型 Derived
上,所以这就是递归结束的地方,因为Base
不知道Derived
反过来又从Base<Derived>
继承。
public Base< Derived >
在这里,Derived
仅指用于Base
内部T
的字体名,仅此而已。您当然可以获得无限递归,但这完全取决于您如何在Base
中使用T
。 T
本身只是一种类型,就像任何其他类类型一样,类型本身实际上并不执行任何操作。
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 为什么在保护模式下继承升级不起作用
- 如何在全屏模式下(在OpenGL中)使背景透明
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 简化使用 CRTP 模式的类的声明
- CRTP 模式不会触发完整的模板实例化
- 为什么这些 CRTP 模式中只有一个可以编译?
- 为什么奇怪的重复模板模式 (CRTP) 有效
- CRTP 模式 但是在数据结构中存储非同构类型
- 为什么CRTP(奇怪的递归模板模式)试图选择另一个私有基类的另一个同名函数
- 可以解析CRTP模式
- C++和CRTP模式的实现与编译器困境
- 奇怪的重复模板模式(CRTP)和派生的构造函数参数
- 奇怪的重复模板模式 (CRTP),在 Clang 中使用静态 constexpr
- C++中的两种不同的mixin模式.(混合蛋白?CRTP?)
- 使用 CRTP 和'anonymous types/template'实现观察者模式
- 通过值传递的CRTP模式的未初始化副本
- 奇怪的循环模板模式(CRTP),自动列表和c++
- 使用奇怪循环模板模式(CRTP)和其他类型参数