如何实现仅允许派生类传入自身作为参数的CRTP模板基类
解决方案
你遇到的是奇异递归模板模式(CRTP)场景下的典型校验时机问题:模板参数列表中的std::is_base_of校验触发时,基类Self和派生类T都处于不完整状态,类型特性无法正常计算结果。
最简洁且兼容性最优的实现方案是利用友元权限限制实现约束,仅允许模板参数对应的类继承当前基类实例:
#include <type_traits> template <class T> class Self { protected: typedef T self; // 可选:增加类型校验,确保T是类类型 static_assert(std::is_class<T>::value, "Template parameter T must be a class type"); private: // 构造函数私有,仅友元可访问 Self() = default; // 仅模板参数T有权限访问基类的私有构造函数 friend T; }; // 编译正常:ValidDerived是基类的友元,可以调用基类构造函数 class ValidDerived : public Self<ValidDerived> { }; // 编译报错:InvalidDerived不是Self<ValidDerived>的友元,无法调用基类私有构造函数 class InvalidDerived : public Self<ValidDerived> { };
该方案完全匹配你的需求:
- 只有派生类传入自身作为模板参数时才能正常编译
- 可以直接通过
self别名获取派生类类型,直接调用typeid(self).name()即可拿到最派生类的类型名称,满足反射场景的需求。
如果需要更明确的错误提示,可以在C20及以上版本结合concept做进一步约束,上述友元方案兼容C11及所有后续标准。
内容的提问来源于stack exchange,提问作者OmniSudo
相关产品推荐
相关产品推荐

