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

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

如果我有一个这样的枚举类:

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

我有一个从 intWeekday 的转换:

Weekday day = static_cast<int>(value);

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

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

太丑了。有什么好的方法吗?

最佳答案

从表面上看,这可能使事情过于复杂,但它很好地概括了模板巫术可以隐藏在标题中远离视线。

#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 和 Last。如果给定值在 (First, Last] 范围内,则分配该值。如果不在范围内,则抛出异常。异常可能不是正确的做法,具体取决于无效输入的频率,如果错误输入很常见,则几乎不异常(exception),但在这里它有助于保持示例简单。

现在调用是一件简单的事情

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

以后

Weekday day = do_conversion<Weekday>(value);

转换产生的所有噪音都不会影响转换所需的任何内容,因此无论谁正在阅读或编写那段代码,都可以继续他们的工作。

但是,如果您在没有FirstLastenum 上使用它会怎样?编译器消息可能会变得奇怪,所以帮助用户解决问题是个好主意。以下内容已从 How to detect whether there is a specific member variable in class? 中抢走使它更容易使用。一定要花时间阅读答案以了解发生了什么。我还没有想出一个合适的方法来组合 HasFirstHasLast。请发表评论,如果您有任何意见,请告诉我。

#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");
}

现在,如果 enum 缺少所有重要的元值,编译器可以通过简单的错误消息告诉它们。

Test case

关于c++ - 如何限制从 int 到 enum 类的转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58724004/

相关文章:

c++ - 仅当语句匹配时如何将参数发送给函数?

C++ 迭代器比索引慢得多?

c++ - 没有先定义 (#define) 宏就使用 #undefine 的效果

c++ - 带有对象的初始化列表是不可移植的?

c++ - 封闭类的当前对象的概念

java - 在Java中,变量应该在函数的顶部声明,还是在需要时声明?

coding-style - 装饰器中的 Python 命名约定

coding-style - 在线条件表达式或函数 - Pythonic?

C++、xcode 和终端,绝对基础

C++Concurrency in action :Can the Listing7. 6(使用危险指针的 pop() 实现)真的检测到无法回收的节点吗?