通常,在编写简单的状态机时,您有一个总顺序,如:
State {
initial,
connecting,
established,
ready,
closed,
failed
}您可以很容易地测试给定值的等效性:
if (state == State::established)但是如果你的状态已经准备好了--这个测试会失败,即使准备好意味着已经建立起来了?另一种选择是添加另一个子句,但是随着列表的延长,或者需求的改变,这可能会变得更长。
if (state == State::established || state == State::ready || ...)使用C样式枚举,您甚至可以通过转换为整数来确定相对顺序:
if (state > State::established && state <= State::closed)但是,如果您想要享受类型安全枚举类,除了添加operator<之外,您似乎运气不佳。这个是可能的吗?
发布于 2016-08-04 23:21:20
如您所知,作用域枚举提供类型安全性,因为它们不能隐式转换为整数。
但是,没有什么可以阻止您将枚举转换为整数:
if ((int)state > (int)State::established && (int)state <= (int)State::closed)您可以使用static_cast的C样式强制转换。
发布于 2021-04-21 13:53:17
我倾向于将我需要的操作符定义为内联函数,并根据需要使用static_cast来获得要比较的值:
enum class MyEnum : unsigned { ALPHA, BETA, DELTA, EPSILON };
inline bool operator<(MyEnum a, MyEnum b) { return static_cast<unsigned>(a) < static_cast<unsigned>(b); }
inline bool operator>(MyEnum a, MyEnum b) { return static_cast<unsigned>(a) > static_cast<unsigned>(b); }
inline bool operator<=(MyEnum a, MyEnum b) { return static_cast<unsigned>(a) <= static_cast<unsigned>(b); }
inline bool operator>=(MyEnum a, MyEnum b) { return static_cast<unsigned>(a) >= static_cast<unsigned>(b); }(注意:在C++20中,这会变得更简单,因为您只需定义一个操作符"<=>“操作符,然后自动生成其他操作符)。
在需要执行更复杂技巧的情况下,可以使用静态std::unordered_map将值(或值对)映射到所需的任何值:
#include <unordered_map>
const std::string& getName(MyEnum e)
{
static const std::string UNKNOWN = "???";
static const std::unordered_map<MyEnum, std::string> NAMES = {
{MyEnum::ALPHA, "ALPHA"},
{MyEnum::BETA, "BETA"},
{MyEnum::DELTA, "DELTA"},
{MyEnum::EPSILON, "EPSILON"},
};
const auto it = NAMES.find(e);
return ((it != NAMES.end()) ? it->second : UNKNOWN);
}发布于 2016-08-04 22:55:45
人们可能会认为这是一个有缺陷的请求,因为对枚举值进行总体排序是一个历史性的实现方法意外,或者状态机很少是线性的(失败意味着关闭,但失败并不一定意味着连接已经准备好)。
然而,我发现它经常出现,直到您转移到更复杂的东西(或者您的状态机增长)为止。我想出了以下解决方案,它不需要将枚举转换为整数值。
bool has_reached(State current, State condition)
{
bool reached = false;
switch (condition)
{
case State::initial: reached |= current == State::initial;
case State::connecting: reached |= current == State::connecting;
case State::established: reached |= current == State::established;
case State::ready: reached |= current == State::ready;
case State::closed: reached |= current == State::closed;
case State::failed: reached |= current == State::failed;
};
return reached;
}用途如下:
if (has_reached(state, State::established)) // State::ready returns true在现代系统中,它应该是快速的,并且很难出错--只要你不把申报的命令和转换的命令混淆在一起。
https://stackoverflow.com/questions/38778553
复制相似问题