crtp基类模板需声明为template,派生类必须显式继承base并实现约定接口,通过static_cast调用派生函数,配合static_assert和if constexpr实现编译期类型安全与逻辑分化。

定义CRTP基类模板并确保派生类可安全转型
要让基类在编译期就能调用派生类的具体实现,必须先构造一个能“认出”派生类类型的模板基类,否则static_cast
第一步:声明模板基类,仅接受一个类型参数Derived,且所有对派生类成员的访问必须通过static_cast
第二步:在基类公有接口中调用派生类约定函数(如draw_impl()),禁止直接写this->draw_impl()——这会触发虚函数查找或编译错误;
第三步:在关键调用点插入static_assert,例如static_assert(std::is_member_function_pointer_v
注意:【Base本身不是类型,Base
派生类必须显式传入自身完整类型并严格实现接口
派生类不是普通继承参与者,而是模板特化的共同作者——它必须亲手把自身名字原封不动塞进基类模板参数里,少一个字符、多一层别名,整个链条就断掉。
方法一:非模板派生类直接继承,语法必须是class Circle : public ShapeBase
方法二:若派生类自身是模板(如template
方法三:禁止使用typedef、using别名或中间基类占位,例如class Circle : public ShapeBase
【派生类定义必须在基类模板实例化前完成】。若头文件中先声明class Circle;再#include "shape_base.h",则ShapeBase
用if constexpr替代运行时分支实现编译期逻辑分化
当不同派生类需在统一接口中执行差异化行为(如Circle走抗锯齿路径、Rect走批处理路径),绝不能用if (typeid(*this) == typeid(Circle))——这依赖RTTI且强制引入虚函数表。
在基类模板成员函数中封装分支逻辑,例如render()函数内部使用if constexpr (std::is_same_v
未选中的分支仍需语法合法:即使Circle分支里写了circle_specific_optimize(),Rect也必须声明该函数(哪怕为空实现),否则模板实例化失败;
这一步操作起来很简单,直接把条件判断换成if constexpr即可,但必须确保所有分支中调用的函数都在对应派生类中真实存在且签名完全匹配——拼错名、漏const、参数类型差int与long,都会让整个特化版本编译中断。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











