将枚举与整数进行比较

6

我读到过一个观点,即不应该相信枚举的底层实现是有符号还是无符号的。因此,我得出结论,应该始终将枚举值转换为与其进行比较的类型。像这样:

enum MyEnum { MY_ENUM_VALUE = 0 };

int i = 1;
if (i > static_cast<int>(MY_ENUM_VALUE))
{
    // do stuff
}

unsigned int u = 2;
if (u > static_cast<unsigned int>(MY_ENUM_VALUE))
{
    // do more stuff
}

这是最佳实践吗?

编辑:如果枚举是匿名的,情况是否会改变?

3个回答

8

Enum是一个整数,因此您可以将其与任何其他整数甚至浮点数进行比较。编译器会自动将两个整数转换为最大的整数,或将枚举转换为双精度浮点数再进行比较。

现在,如果您的枚举不应该表示一个特定的数字,您可能希望考虑创建一个类:

enum class some_name { MY_ENUM_VALUE, ... };

int i;
if(i == static_cast<int>(some_name::MY_ENUM_VALUE))
{
    ...
}

在这种情况下,您需要进行类型转换,因为默认情况下枚举类不被视为整数。如果您误用枚举值,则这可以很大程度上避免错误...
更新:此外,现在您可以指定enum的整数类型。这在旧编译器中也可用,但在我的经验中常常无法正常工作。
enum class some_name : uint8_t { ... };

这意味着枚举使用 uint8_t 存储这些值。如果你在结构体中使用枚举值发送数据或保存到二进制文件中并需要知道数据的确切大小,那么这是实用的。当没有指定类型时,默认为 int
正如其他人提出的,如果使用枚举的目的仅仅是声明数字,那么使用 constexpr 可能更好。
constexpr int MY_CONSTANT_VALUE = 0;

这个代码与之前的代码相同,只是现在MY_CONSTANT_VALUE的类型变成了int。你还可以进一步使用typedef,如下所示:

typedef int my_type_t;
constexpr my_type_t MY_CONSTANT_VALUE = 0;

即使值通常不被认为是整数,我经常使用enum,即使我只使用单个值。在这种情况下,没有固定的规则。


如果您的枚举并不是用来表示一个数字,您可能需要考虑创建一个类来替代。如何正确理解加粗的文本?即使您没有显式定义,您示例中的 MY_ENUM_VALUE 是否等同于 0 呢? - John
枚举是整数,因此您可以将其与任何其他整数甚至浮点数进行比较。即使使用强类型的“enum”,这仍然是正确的吗? - John
@John 在内部,enum class ... 仍然只是整数。但是,尝试执行 i == some_name::MY_ENUM_VALUE 会失败并出现警告(如果使用 -Werror 则会出现错误)。您可以使用 static_cast 在这些类型之间进行转换。但是,默认情况下(没有强制转换),它允许您更加确定在正确的位置使用了正确的类型(例如,调用一个期望 some_name 的函数时,当您尝试传递 0 而不是 some_name::MY_ENUM_VALUE 时,编译将无法通过——您可以对 0 进行强制转换,但是)。我认为这使您的代码更安全/更不容易出现错误。 - Alexis Wilke

3
简短回答:是的。
枚举类型 enum 是一个有符号整数类型,但它们会被隐式地转换成无符号整数类型 unsigned int。没有显式转换时,编译器可能会给出警告,但这种情况仍然很常见。然而,为了让维护人员更清晰明确,应该显式转换。
当枚举类型是强类型 strongly typed enum 时,必须使用显式转换

1
枚举类型是有符号整型,但它们会被隐式转换为无符号整型,这是错误的。未作用域限定符的枚举类型底层类型是一个整数类型,可以容纳最大的枚举值。这意味着如果它比INT_MAX大,它可以是unsigned intlongunsigned long等类型。并且它会被隐式转换为能够容纳最大枚举值的最小整数类型(这并不总是unsigned int)。 - Simple

0
最佳实践是不要写

标签


int i = 1;
if (i > static_cast<int>(MY_ENUM_VALUE))
{
    // do stuff
}

应该写成

MyEnumValue i = MY_ENUM_VALUE ;
...
if ( i > MY_ENUM_VALUE ) {..}

但是,如果您的枚举中只有一个值,就像您的示例一样,最好将其声明为常量而不是枚举。


我同意,这种情况通常发生在将应该定义为常量的值定义为枚举时。 - khuttun

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接