如何测试类是否派生自未指定参数的任意模板类?
实现
is_derived_from_template Concept的简便方式 可以通过重载解析+隐式转换的思路实现这个concept,核心是利用C++的隐式转换规则,检测派生类能否转换为目标模板的任意实例类型。
完整实现代码
#include <concepts> // 辅助检测函数:匹配BasePredicate的任意实例 template<template<typename...> typename BasePred, typename... Args> constexpr bool is_base_of_template_impl(const BasePred<Args...>&) noexcept { return true; } // 通用重载:匹配所有不满足条件的情况 constexpr bool is_base_of_template_impl(...) noexcept { return false; } // 目标concept template<typename DerivedSubject, template<typename...> typename BasePredicate> concept is_derived_from_template = requires(DerivedSubject&& subj) { // 用const volatile转换覆盖所有cv限定的派生类情况 { is_base_of_template_impl<BasePredicate>(static_cast<const volatile DerivedSubject&>(subj)) } -> std::convertible_to<bool>; };
原理说明
- 当
DerivedSubject确实继承自BasePredicate的某个实例(比如BasePredicate<int>或BasePredicate<string, double>)时,static_cast<const volatile DerivedSubject&>(subj)可以隐式转换为对应的BasePredicate<Args...> const volatile&,从而匹配到第一个重载,返回true。 - 如果
DerivedSubject与BasePredicate的任何实例都无继承关系,编译器会选择可变参数的通用重载,返回false。
测试示例
// 单参数基类模板 template<typename T> struct Base {}; struct Derived : Base<int> {}; struct Unrelated {}; static_assert(is_derived_from_template<Derived, Base>); static_assert(!is_derived_from_template<Unrelated, Base>); // 多参数基类模板 template<typename T, typename U> struct MultiBase {}; struct MultiDerived : MultiBase<int, std::string> {}; static_assert(is_derived_from_template<MultiDerived, MultiBase>);
注意事项
- 该实现支持cv限定的派生类(比如
const Derived),因为使用了const volatile的转换。 - 即使派生类是
final,依然可以正常检测,因为转换到基类引用不受final限制。 - 不会误判非继承关系的类型,只有真正的公共/保护继承会被检测到(私有继承无法通过隐式转换检测,符合C++的访问规则)。
内容的提问来源于stack exchange,提问作者AMDG
相关产品推荐
相关产品推荐

