std::conditional_t搭配std::is_enum_v与std::underlying_type_t编译报错如何解决
问题原因
你遇到的编译错误是因为std::conditional_t的两个分支类型会被无条件全部实例化后再按条件选择结果。当判断的类型T不是枚举时,std::underlying_type_t<T>仍然会被实例化,而C++标准明确要求std::underlying_type只能作用于枚举类型,因此直接触发编译错误。
解决方案
我们可以通过偏特化实现一个辅助萃取,把「判断是否为枚举」和「获取底层类型」的逻辑拆分,确保只有枚举类型才会触发std::underlying_type的实例化:
// 辅助萃取:是枚举则返回底层类型,否则返回原类型 template<typename T, typename = void> struct underlying_if_enum { using type = T; }; template<typename T> struct underlying_if_enum<T, std::enable_if_t<std::is_enum_v<T>>> { using type = std::underlying_type_t<T>; }; template<typename T> using underlying_if_enum_t = typename underlying_if_enum<T>::type;
把原来is_index特化版本里的std::conditional_t替换成上面的underlying_if_enum_t即可满足需求。
完整可运行代码
#include <iostream> #include <type_traits> #include <cinttypes> #include <vector> #include <utility> template<typename T> struct is_unsigned_integral : std::integral_constant< bool, std::is_integral<T>::value && std::is_unsigned<T>::value > {}; template<typename T> inline constexpr auto is_unsigned_integral_v = is_unsigned_integral<T>::value; // 新增辅助萃取 template<typename T, typename = void> struct underlying_if_enum { using type = T; }; template<typename T> struct underlying_if_enum<T, std::enable_if_t<std::is_enum_v<T>>> { using type = std::underlying_type_t<T>; }; template<typename T> using underlying_if_enum_t = typename underlying_if_enum<T>::type; template<typename, typename = void> struct is_index : std::false_type {}; template<typename T> struct is_index< T, std::enable_if_t< is_unsigned_integral_v< underlying_if_enum_t<T> // 替换原来的conditional_t逻辑 > > > : std::true_type {}; template<typename T> inline constexpr auto is_index_v = is_index<T>::value; enum class idx : unsigned int {}; // 反例测试:有符号枚举 enum class bad_idx : int {}; int main() { static_assert(is_index_v<unsigned int>, "普通无符号整型应符合要求"); static_assert(is_index_v<idx>, "无符号底层类型的枚举应符合要求"); static_assert(!is_index_v<int>, "有符号整型应不符合要求"); static_assert(!is_index_v<bad_idx>, "有符号底层类型的枚举应不符合要求"); static_assert(!is_index_v<std::string>, "非算数类型应不符合要求"); return 0; }
内容的提问来源于stack exchange,提问作者Symlink
相关产品推荐
相关产品推荐

