如何限制从int到enum类的转换?

时间:2019-11-06 06:07:19

标签: c++ c++11 coding-style

如果我有这样的enum class

enum class Weekday {
  Monday,
  Tuesday,
  Wednesday,
  Thursday,
  Friday,
  Saturday,
  Sunday
}

并且我从int转换为Weekday

Weekday day = static_cast<int>(value);

要检查为转换提供的值是否有效,我应该输入以下代码:

if (value != 0 && value != 1 && value !=2 && value !=3 && value != 4 && value != 5 && value != 6) { 
  do_conversion(value); 
}

好丑。有什么好办法吗?

2 个答案:

答案 0 :(得分:1)

枚举类的默认基础类型是整数。因此,要检查整数是否在可接受的枚举值范围内,可以使用static_cast<int>将其与可接受的枚举值的范围进行比较:

if (value >= static_cast<int>(Weekday::Monday) && value <= static_cast<int>(Weekday::Sunday))
{
    do_conversion(value);
}

答案 1 :(得分:1)

这可能会使表面上的事情变得过于复杂,但是可以很好地泛化,并且可以将模板伏都教隐藏在看不见的标题中。

#include <stdexcept>
template <class TYPE>
TYPE do_conversion(int value)
{
    if (value >= static_cast<int>(TYPE::First) &&
        value < static_cast<int>(TYPE::Last))
    {
        return static_cast<TYPE>(value);
    }
    throw std::out_of_range("Inv value");
}

所有转换都移到一个函数上,以降低噪声。 有效范围是使用额外的枚举值First and Last来抽象的。如果给定值在(FirstLast]范围内,则分配该值。否则,抛出异常。根据无效输入的频率,异常可能不是正确的选择,如果输入错误很常见,这几乎不是例外,但是在这里,这有助于使示例保持简单。

现在调用是一个简单的问题

enum class Weekday
{
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday,
    Last,           // added
    First = Monday  // added
};

及以后

Weekday day = do_conversion<Weekday>(value);

所有来自转换的噪音都不会影响转换的需要,因此,无论是谁读写的代码,都可以继续工作。

但是如果您在没有enumFirst的{​​{1}}上使用它怎么办?编译器消息可能会变得很奇怪,因此最好是帮助用户。 How to detect whether there is a specific member variable in class?抢劫了以下内容,以使其更易于使用。一定要花时间阅读答案,以了解发生了什么。我还没有想办法将LastHasFirst结合起来。请发表评论,让我知道你是否有评论。

HasLast

现在,如果#include <stdexcept> #include <type_traits> template <typename T, typename = int> struct HasFirst : std::false_type { }; template <typename T> struct HasFirst <T, decltype((void) T::First, 0)> : std::true_type { }; template <typename T, typename = int> struct HasLast : std::false_type { }; template <typename T> struct HasLast <T, decltype((void) T::Last, 0)> : std::true_type { }; template <class TYPE> TYPE do_conversion(int value) { static_assert(HasFirst<TYPE>::value, "enum missing First"); static_assert(HasLast<TYPE>::value, "enum missing Last"); if (value >= static_cast<int>(TYPE::First) && value < static_cast<int>(TYPE::Last)) { return static_cast<TYPE>(value); } throw std::out_of_range("Inv value"); } 缺少所有重要的元值,则编译器可以通过简单的错误消息告诉它们。

Test case