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

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

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

【问题讨论】:

标签: c++ enums c++11 metaprogramming typetraits


【解决方案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);
}

【讨论】:

    猜你喜欢
    • 2019-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多