如何限制嵌套模板参数类型(不使用C++20特性)
解决方案:限制模板类参数的枚举类型匹配
要实现c1<T1, T2>中,若T2是c2<EnumVal>的实例,则EnumVal必须属于T1类型的枚举,同时允许T2为其他任意类型,可以通过类型特性提取+静态断言的方式实现,兼容C17及更早标准(无需C20特性)。
完整实现代码
#include <type_traits> enum class e1 : size_t { a, b }; enum class e2 : size_t { a, b }; // 模板类c2:接收任意枚举值作为模板参数 template <auto EnumVal> struct c2 { }; // 类型特性:判断是否为c2的实例 template <typename T> struct is_c2 : std::false_type {}; template <auto EnumVal> struct is_c2<c2<EnumVal>> : std::true_type {}; template <typename T> constexpr bool is_c2_v = is_c2<T>::value; // 类型特性:从c2实例中提取枚举类型和值 template <typename> struct c2_traits; template <auto EnumVal> struct c2_traits<c2<EnumVal>> { using enum_type = decltype(EnumVal); static constexpr auto enum_value = EnumVal; }; // 模板类c1:添加静态断言限制枚举类型匹配 template <typename T1, typename T2> struct c1 { // 仅当T2是c2实例时,检查枚举类型是否与T1一致 static_assert(!is_c2_v<T2> || std::is_same_v<typename c2_traits<T2>::enum_type, T1>, "错误:c2的枚举值类型必须与c1的第一个模板参数匹配"); }; // 测试案例 c1<e1, c2<e1::a>> o1; // 编译通过 // c1<e1, c2<e2::a>> o2; // 编译报错:触发静态断言 // c1<int, float> o3; // 编译通过(T2为非c2类型,不受限制)
核心逻辑说明
- c2的定义:使用非类型模板参数
auto接收任意枚举值(若需兼容C++11/14,可改为typename EnumType, EnumType EnumVal的显式参数形式)。 - is_c2特性:用于判断
T2是否为c2的实例,避免对非c2类型进行不必要的检查。 - c2_traits特性:从
c2<EnumVal>实例中提取枚举值的类型enum_type,为后续匹配检查提供依据。 - c1的静态断言:仅当
T2是c2实例时,才强制检查其枚举类型是否与c1的第一个参数T1一致,满足“T2可以是其他类型”的需求。
内容的提问来源于stack exchange,提问作者Graznarak
相关产品推荐
相关产品推荐

