【问题标题】:Check if enum class contains a specific identfier检查枚举类是否包含特定标识符
【发布时间】:2021-07-21 15:34:27
【问题描述】:

我在 SO 上搜索了一下,很惊讶我没有找到任何类似的问题。很高兴有任何提示,以防万一这已经得到回答。

我有一个定义了很多枚举类的代码库。其中一些指定了一个 totalNum 常量,例如

enum class Foo : int
{
    a,
    b,
    c,

    totalNum
}

别人没有这样的

enum class Bar : bool
{
    oneOption,
    otherOption
}

那我有一个基本是这样的功能

template <class EnumClassType>
EnumClassType typeToEnum (typename std::underlying_type<EnumClassType>::type value)
{
    // If you hit this assertion, the value is outside of the valid enum range
    assert (isPositiveAndBelow (value, decltype (value) (EnumClassType::totalNum)));

    return EnumClassType (value);
}

虽然这对指定 totalNum 的枚举有效并且有意义,但如果枚举中没有这样的标识符,我想跳过这个断言。有没有办法做到这一点?代码库目前使用 C++ 14,但由于即将发生编译器更改,也欢迎使用 C++ 17 解决方案。

【问题讨论】:

  • 您可以使用 SFINAE 到 provide an overload,如果一个项目是 enum 并且具有 ::totalNum,那么它会执行静态断言。

标签: c++ c++17 c++14 enum-class


【解决方案1】:

与此同时,我自己找到了答案,使用了 cmets 中提到的 @jfh 之类的方法。

首先这是一种检查枚举类是否包含具有特定名称的标识符的方法

template <class EnumToTest>
class EnumConstantDefined_totalNum
{
private:
    using Yes = int8_t;
    using No = int16_t;

    template <class E>
    static Yes test (decltype (E::totalNum)*);

    template <class E>
    static No test (...);

public:
    static constexpr bool value = sizeof (test<EnumToTest> (0)) == sizeof (Yes);
};

然后我们可以使用 SFINAE 为这两种枚举指定两个重载。

template <class EnumType>
std::enable_if_t<EnumConstantDefined_totalNum<EnumType>::value, void> assertValueIsInRange (typename std::underlying_type<EnumType>::type value)
{
    assert (isPositiveAndBelow (value, decltype (value) (EnumType::totalNum)));
}

template <class EnumType>
std::enable_if_t<! EnumConstantDefined_totalNum<EnumType>::value, void> assertValueIsInRange (typename std::underlying_type<EnumType>::type)
{
    // do nothing
}

然后在实际的转换函数中使用这个断言函数

/**
   Casts a value matching an enum class underlying type to an enum class constant and asserts that the
   value is inside the valid enum range
 */
template <class EnumClassType>
EnumClassType typeToEnum (typename std::underlying_type<EnumClassType>::type value)
{
    assertValueIsInRange<EnumClassType> (value);

    return EnumClassType (value);
}

【讨论】:

  • 比我快 15 秒。 ;-)
猜你喜欢
  • 1970-01-01
  • 2011-06-23
  • 1970-01-01
  • 2016-06-04
  • 1970-01-01
  • 2012-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多