微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

检查枚举类是否包含特定标识符

如何解决检查枚举类是否包含特定标识符

我在 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 解决方案。

解决方法

同时使用评论中提到的@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);
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。