如何实现支持继承检测的C++模板特化派生判断concept
实现方案
完全可以实现,以下是兼容C++17及以上版本的可用实现,符合你提出的所有判断要求:
#include <type_traits> template <class T, template <class...> class Primary> struct derived_from_specialization_of { private: // 匹配任意Primary模板的特化基类 template <class... Args> static std::true_type test(const Primary<Args...>*); // 兜底重载,没有匹配到对应基类时触发 static std::false_type test(...); public: static constexpr bool value = decltype(test(static_cast<const T*>(nullptr)))::value; }; // 标准库风格的辅助变量模板 template <class T, template <class...> class Primary> constexpr bool derived_from_specialization_of_v = derived_from_specialization_of<T, Primary>::value; // C++20 下可额外定义概念版本 #if __cplusplus >= 202002L template <class T, template <class...> class Primary> concept derived_from_specialization_of = derived_from_specialization_of_v<T, Primary>; #endif
实现原理
利用C++的隐式指针转换规则:派生类指针可以隐式转换为可访问、无歧义的公有基类指针。我们通过两个重载的test函数让编译器自行完成匹配:如果传入的T指针能转换为任意Primary<Args...>类型的指针,就会匹配到返回std::true_type的重载,否则触发变参兜底函数返回std::false_type。
验证测试
你给出的所有测试用例都可以正常通过:
单参数模板继承测试
template<class> struct A {}; template<class T> struct B : A<T> {}; template<class T> struct C : B<T> {}; static_assert(derived_from_specialization_of_v< A<int>, A>); static_assert(derived_from_specialization_of_v< B<int>, B>); static_assert(derived_from_specialization_of_v< C<int>, C>); static_assert(derived_from_specialization_of_v< B<int>, A>); static_assert(derived_from_specialization_of_v< C<int>, B>); static_assert(derived_from_specialization_of_v< C<int>, A>);
多参数、参数包模板测试
// 多参数模板 template<class, class> struct MultiA{}; struct DerivedMulti : MultiA<int, double> {}; static_assert(derived_from_specialization_of_v<DerivedMulti, MultiA>); // 参数包模板 template<typename...> struct VariadicB{}; struct DerivedVariadic : VariadicB<int, char, double> {}; static_assert(derived_from_specialization_of_v<DerivedVariadic, VariadicB>);
注意限制
- 仅对公有、无歧义的继承生效:如果是私有/保护继承,或者
T同时继承了多个不同的Primary<Args...>特化,会返回false或者触发编译歧义错误。 - 当前版本仅支持模板参数全为类型参数的模板,如果需要支持包含非类型模板参数、模板模板参数的模板,需要针对场景调整匹配规则。
内容的提问来源于stack exchange,提问作者Ramon
相关产品推荐
相关产品推荐

