如何针对继承自Number类的类型特化NumberValue模板?
解决NumberValue模板特化问题
针对继承自Number的类特化NumberValue,有两种常用实现方式:
方式一:C++17及更早版本(SFINAE + is_base_of)
利用std::enable_if和std::is_base_of实现条件特化,代码如下:
#include <type_traits> // 原类定义保持不变 class Number {}; class One: public Number { static constexpr int value = 1; }; class Two: public Number { static constexpr int value = 2; }; class Three: public Number { static constexpr int value = 3; }; class NotANumber {}; template <typename T> struct NumberValue { static constexpr int value = -1; }; // 针对继承自Number的类型的特化 template <typename T> struct NumberValue<T, std::enable_if_t<std::is_base_of_v<Number, T>>> { static constexpr int value = T::value; }; // 静态断言验证 static_assert(NumberValue<std::string>::value == -1); static_assert(NumberValue<NotANumber>::value == -1); static_assert(NumberValue<One>::value == 1); static_assert(NumberValue<Two>::value == 2); static_assert(NumberValue<Three>::value == 3);
原理:通过std::is_base_of_v<Number, T>判断T是否继承自Number,std::enable_if_t会在条件为真时启用这个特化版本,覆盖默认模板逻辑。
方式二:C++20及以上版本(Concepts)
使用C++20的concept语法,代码更简洁直观:
#include <concepts> // 原类定义保持不变 class Number {}; class One: public Number { static constexpr int value = 1; }; class Two: public Number { static constexpr int value = 2; }; class Three: public Number { static constexpr int value = 3; }; class NotANumber {}; template <typename T> struct NumberValue { static constexpr int value = -1; }; // 定义concept,限定必须是Number的派生类 template <typename T> concept NumberDerived = std::derived_from<T, Number>; // 针对符合NumberDerived概念的类型特化 template <NumberDerived T> struct NumberValue<T> { static constexpr int value = T::value; }; // 静态断言验证 static_assert(NumberValue<std::string>::value == -1); static_assert(NumberValue<NotANumber>::value == -1); static_assert(NumberValue<One>::value == 1); static_assert(NumberValue<Two>::value == 2); static_assert(NumberValue<Three>::value == 3);
原理:NumberDerived概念直接约束模板参数必须是Number的派生类,特化版本会自动匹配符合条件的类型。
注意:两种方式都需要包含对应的头文件(type_traits或concepts),否则编译会报错。
内容的提问来源于stack exchange,提问作者DanielZitoli
相关产品推荐
相关产品推荐

