CRTP是一种编译期确定的模板惯用法:派生类以自身为模板参数继承基类,实现零开销静态多态;它支持编译期类型检查、完全内联,但不支持动态多态或运行时行为。

CRTP 是什么:编译期确定的“假继承”
CRTP(Curiously Recurring Template Pattern)不是语言特性,而是一种模板编程惯用法:派生类以自身为模板参数继承基类。它让基类在编译期就能“知道”最终派生类型,从而实现静态多态——不靠 vtable、不产生虚函数调用开销。
典型写法长这样:
templateclass Base { public: void interface() { static_cast (this)->implementation(); // 编译期绑定 } }; class MyConcrete : public Base
{ public: void implementation() { / 实际逻辑 / } };
为什么用 CRTP 而不用虚函数
核心动机是零成本抽象:避免运行时虚函数查表、禁止对象切片、支持 static_assert 在编译期校验接口契约。
- 性能敏感场景(如数学库、嵌入式驱动)中,
Base可被完全内联,生成和直接调用::interface() MyConcrete::implementation()几乎等价的汇编 - 基类可强制要求派生类提供特定成员(比如
value_type或size()),用static_cast触发 SFINAE 或编译错误(this)->size() - 无法用于多态数组或动态向上转型——CRTP 对象之间没有公共基类指针/引用关系,
Base*和Base*类型完全不同
容易踩的坑:循环依赖与 this 指针安全
CRTP 最隐蔽的问题不是语法,而是派生类定义未完成时基类就试图访问其成员。
立即学习“C++免费学习笔记(深入)”;
大高朋团购系统是一套Groupon模式的开源团购程序,开发的一套网团购程序,系统采用ASP+ACCESS开发的团购程序,安装超简,功能超全面,在保留大高朋团购系统版权的前提下,允许所有用户免费使用。大高朋团购系统内置多种主流在线支付接口,所有网银用户均可无障碍支付;短信发送团购券和实物团购快递发货等。 二、为什么选择大高朋团购程序系统? 1.功能强大、细节完善 除了拥有主流团购网站功能,更特别支
- 在
Base构造函数里调用static_cast是未定义行为——此时(this)->xxx() Derived的构造函数还没开始执行,对象内存未就绪 - 若基类模板中用到
Derived::some_nested_type,必须确保该类型在继承声明前已定义(常需前置声明 + 后续定义分离) - 不要试图在 CRTP 基类中存储
Derived*并长期持有——生命周期管理责任不清,易悬垂
典型用途:表达式模板与混合类型操作
CRTP 真正发挥威力的地方,是需要在编译期组合类型行为的场景,比如 Eigen、xtensor 这类数值库。
例如实现向量加法不立即计算,而是构建表达式树:
templateclass VectorAdd : public Base > { LHS lhs_; RHS rhs_; public: auto operator[](size_t i) const { return lhs_[i] + rhs_[i]; } }; // 用户代码: auto expr = vec1 + vec2; // 类型是 VectorAdd
,无临时对象、无虚调用 double x = expr[5]; // 到这里才真正计算
这种模式依赖 CRTP 让 Base 能统一处理所有表达式类型,同时保持每个具体表达式类型可区分、可优化。一旦涉及运行时决定行为(比如用户输入算子类型),CRTP 就不再适用——它只活在编译期。









