是否有一种类型特征或者可以编写一种类型特征is_scoped_enum<T>
,使得:
- 如果
T
是一个作用域枚举,则is_scoped_enum<T>::value
为true
,并且 - 如果
T
是任何其他类型,则is_scoped_enum<T>::value
为false
是否有一种类型特征或者可以编写一种类型特征is_scoped_enum<T>
,使得:
T
是一个作用域枚举,则is_scoped_enum<T>::value
为true
,并且T
是任何其他类型,则is_scoped_enum<T>::value
为false我认为测试它是否是枚举类型并且不能隐式转换为基础类型就可以解决问题。
template <typename T, bool B = std::is_enum<T>::value>
struct is_scoped_enum : std::false_type {};
template <typename T>
struct is_scoped_enum<T, true>
: std::integral_constant<bool,
!std::is_convertible<T, typename std::underlying_type<T>::type>::value> {};
std::underlying_type<T>
而不是int
。在C++11中,enum class
可以基于某些不可转换为int
的东西。 - kennytmint
的整数类型? - James McNellisusing
语句(模板别名)来实现,就像这里所建议的那样。但是,这样会对所有类型进行std::underlying_type
的评估,而一些编译器在使用underlying_type
与非枚举类型时会生成错误(没有SFINAE)。因此,这个解决方案可能是最好的。 - Excelciusstd::underlying_type
与非枚举类型是未定义的行为,这不需要诊断,因此编译器不必报告误用,这将导致您的程序出现UB。我没有查看常见实现,但推测标准允许UB以便在有效的用例中更容易实现。 - underscore_dC++23将提供is_scoped_enum,一旦实现就可以使用。请参阅此链接以获取文档:is_scoped_enum。我认为clang目前还不支持这个功能(请参阅clang status以获取最新的支持功能信息)。
目前,我正在使用上面答案的稍微简化版本(使用_v和_t),以及is_underlying的实现:
// C++ 23 should include 'is_scoped_enum' and 'to_underlying' so the following
// code can be removed:
template<typename T, bool B = std::is_enum_v<T>>
struct is_scoped_enum : std::false_type {};
template<typename T>
struct is_scoped_enum<T, true>
: std::integral_constant<
bool, !std::is_convertible_v<T, std::underlying_type_t<T>>> {};
template<typename T>
inline constexpr bool is_scoped_enum_v = is_scoped_enum<T>::value;
template<typename T, std::enable_if_t<is_scoped_enum_v<T>, int> = 0>
[[nodiscard]] constexpr auto to_underlying(T x) noexcept {
return static_cast<std::underlying_type_t<T>>(x);
}
enum class
。 - James McNellis