如何在C++模板函数编译期判断类型是基础类型或底层为基础类型的枚举
编译期判断类型为基础类型或底层是基础类型的枚举
问题核心在于:当T不是枚举类型时,std::underlying_type<T>::type会触发编译错误——因为该模板仅对枚举类型有效,编译器会尝试实例化它,导致失败。要解决这个问题,关键是仅当T是枚举类型时,才去检查其底层类型是否为基础类型,避免非枚举类型下的无效实例化。
以下是几种无需修改函数签名的解决方案:
方法1:C++17及以上使用if constexpr(最简洁)
利用if constexpr的编译期分支特性,非枚举类型时会直接丢弃分支内的代码,不会实例化std::underlying_type:
#include <type_traits> template <typename T> bool foo(T& input) { bool isPrimitive = std::is_fundamental_v<T>; // 仅当T是枚举时,才编译分支内的代码 if constexpr (std::is_enum_v<T>) { isPrimitive = isPrimitive || std::is_fundamental_v<std::underlying_type_t<T>>; } // 后续使用isPrimitive的逻辑 return isPrimitive; }
方法2:C++14及以下自定义类型Trait(SFINAE实现)
对于不支持if constexpr的旧标准,可通过SFINAE编写自定义类型判断Trait:
首先定义Trait:
#include <type_traits> // 主模板:默认判断是否为基础类型 template <typename T, typename = void> struct is_fundamental_or_enum_with_fundamental_underlying : std::is_fundamental<T> {}; // 特化版本:仅当T是枚举类型时,判断其底层类型是否为基础类型 template <typename T> struct is_fundamental_or_enum_with_fundamental_underlying<T, std::enable_if_t<std::is_enum<T>::value>> : std::integral_constant<bool, std::is_fundamental<typename std::underlying_type<T>::type>::value> {}; // 辅助变量模板,简化使用 template <typename T> constexpr bool is_fundamental_or_enum_with_fundamental_underlying_v = is_fundamental_or_enum_with_fundamental_underlying<T>::value;
然后在函数中使用:
template <typename T> bool foo(T& input) { bool isPrimitive = is_fundamental_or_enum_with_fundamental_underlying_v<T>; // 后续使用isPrimitive的逻辑 return isPrimitive; }
测试验证
以下测试代码均可正常编译:
enum class Bar : int { DUMMYCASE, }; int main() { int test1; Bar test2; foo(test1); // 返回true(基础类型) foo(test2); // 返回true(枚举底层为int,基础类型) struct CustomType {}; CustomType test3; foo(test3); // 返回false(既非基础类型也非符合条件的枚举) }
内容的提问来源于stack exchange,提问作者Justin
相关产品推荐
相关产品推荐

