是否可以确定一个类型是否是作用域枚举类型?

Posted

技术标签:

【中文标题】是否可以确定一个类型是否是作用域枚举类型?【英文标题】:Is it possible to determine if a type is a scoped enumeration type? 【发布时间】:2012-05-23 17:15:30 【问题描述】:

是否有类型特征,或者是否可以编写一个类型特征is_scoped_enum<T> 这样:

如果T 是范围枚举,则is_scoped_enum<T>::valuetrue 并且 如果T 是任何其他类型,则is_scoped_enum<T>::value 为假

【问题讨论】:

你所说的scoped enum,是指C++11的枚举吗? @Nawaz:作用域枚举是在 C++11 中调用的 enum class,是的。 只是出于好奇,这个有什么实际应用? @Xeo:我正在为一组范围枚举类型重载按位运算符。 bitbucket.org/martinhofernandes/wheels/src/353fc67489dc/include/… 【参考方案1】:

我认为测试它是否是一个枚举并且不能隐式转换为底层类型应该可以解决问题。

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&lt;T&gt; 而不是int。 C++11 中的 enum class 可以基于不能转换为 int 的东西。 @KennyTM:什么类型的? C++11 §7.2/2 声明“enum-base 应命名为整数类型;”是否有不可转换为int 的整数类型? @JamesMcNellis:你是对的。很抱歉造成混乱。 (我在想is_convertible 做隐式转换。) 这是一个很好的解决方案,除了在最新的编辑中,逻辑现在倒退了:如果T 是一个无范围的枚举,则::value 为真。 :-) @Excelcius 这比是否出现错误的可能性更糟糕:将std::underlying_type 与非枚举类型一起使用是未定义的行为,不需要诊断,因此编译器不需要报告误用,然后给你的程序UB。我没有查看常见的实现,但假设标准允许 UB 在有效用例中促进更轻松的实现。【参考方案2】:

C++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 和 enum比较

是否可以在 Typescript 中定义没有显式类型的枚举?

动手动脑

是否可以在 postgresql 的另一个模式中使用一个模式的枚举类型

是否可以在枚举中保存类型(使用“typeof()”)?

怎么比较两个枚举类型是不是相等