C++14下模板类如何实现适配不同枚举类的可选激活构造函数
C++14 下实现适配多枚举类的可选构造模板类
你当前遇到的编译错误本质是:模板类实例化时会实例化所有非模板成员函数,当 T 不存在 EnumType 或 Type2 嵌套类型时,对应构造函数的参数类型直接非法,导致编译失败。我们可以通过 SFINAE(替换失败不是错误) 机制实现构造函数的可选启用:只有当 T 存在对应嵌套枚举类型时,对应构造函数才会参与重载决议。
步骤1:实现辅助编译期检测工具
#include <type_traits> #include <cstdint> // C++14 未提供标准 void_t,自行实现 template<typename...> using void_t = void; // 检测 T 是否存在嵌套类型 EnumType template<typename T, typename = void> constexpr bool has_enum_type_v = false; template<typename T> constexpr bool has_enum_type_v<T, void_t<typename T::EnumType>> = true; // 检测 T 是否存在嵌套类型 Type2 template<typename T, typename = void> constexpr bool has_type2_v = false; template<typename T> constexpr bool has_type2_v<T, void_t<typename T::Type2>> = true;
步骤2:修改模板类的构造函数为受约束的模板构造函数
template<typename T, typename U> class EnumClassHandler { public: EnumClassHandler() : value(0) {} // 仅当 T 存在 EnumType 时启用该构造函数 template<typename E = typename T::EnumType, std::enable_if_t<has_enum_type_v<T> && std::is_same<E, typename T::EnumType>::value, int> = 0> EnumClassHandler(const E& v) { value = static_cast<U>(v); } // 仅当 T 存在 Type2 时启用该构造函数 template<typename E = typename T::Type2, std::enable_if_t<has_type2_v<T> && std::is_same<E, typename T::Type2>::value, int> = 0> EnumClassHandler(const E& v) { value = static_cast<U>(v); } U value; };
完整可运行测试代码
// 原枚举类,无需修改 class MyEnumClass { public: enum Type { Example0, Count }; using EnumType = Type; }; class MyEnumClass2 { public: enum Type2 { Example0, Count }; }; // 类型别名 using MyEnumClassHandler = EnumClassHandler<MyEnumClass, uint32_t>; using MyEnumClass2Handler = EnumClassHandler<MyEnumClass2, uint32_t>; int main() { MyEnumClassHandler example = MyEnumClass::Example0; MyEnumClass2Handler example2 = MyEnumClass2::Example0; return 0; }
上述代码在C++14标准下可正常编译运行:
- 实例化
EnumClassHandler<MyEnumClass, uint32_t>时,仅EnumType版本的构造函数会被启用,Type2版本的构造函数会被自动排除,不会触发编译错误 - 实例化
EnumClassHandler<MyEnumClass2, uint32_t>时同理,仅Type2版本的构造函数生效
如果后续需要支持更多不同命名的枚举类型,只需要新增对应的检测变量模板和构造函数即可。
内容的提问来源于stack exchange,提问作者Iñigo
相关产品推荐
相关产品推荐

