2

我到处看了看,我不敢相信这个问题以前没有被问过。

范围枚举器的顺序是否由标准定义?说如果我有以下

#include <iostream>

enum class Fruits {Apple, Orange, Tomato};

int main(){

   std::cout << (Fruits::Apple < Fruits::Orange);
   std::cout << (Fruits::Orange > Fruits::Tomato);
   return 0;
}


// output:
// 1 0

这在 g++ 中输出 1 0。但是这个标准或编译器是特定的吗?

4

2 回答 2

3

要完成图片并确认是,定义了排序。我们从为什么可以将两个枚举数放在一个关系表达式中开始......

[expr.rel]

2通常的算术转换是在算术或枚举类型的操作数上执行的......

5如果两个操作数(转换后)都是算术或枚举类型,则如果指定的关系为真,则每个运算符都应返回真,如果为假,则返回假。

...其中范围枚举的通常算术转换是无操作的...

[表达式]

9许多期望算术或枚举类型的操作数的二元运算符会导致转换并以类似的方式产生结果类型。目的是产生一个通用类型,这也是结果的类型。这种模式称为通常的算术转换,其定义如下:

  • 如果任一操作数属于范围枚举类型 ([dcl.enum]),则不执行任何转换;如果另一个操作数的类型不同,则表达式格式错误。

所以它们不会转换,只能与相同类型的对象进行比较。给枚举器的值(由另一个答案指定)决定了“如果指定的关系为真,则每个运算符都应产生真,如果为假,则应产生假”。这样比较就完成了。

还值得注意的是,枚举类型变量可以采用未枚举的值!那么例如...

enum class foo {
  min, max = 10
};

foo mid = static_cast<foo>(5);

... 是有效的,并且比较mid > foo::min将保持不变,因为前面的段落被概括为不仅仅包括命名值。

于 2019-05-19T05:46:41.003 回答
2

值的顺序在[dcl.enum] 第 2 点中指定:

如果第一个枚举器没有初始化器,则相应常量的值为零。没有初始化器的枚举器定义为枚举器提供了通过将前一个枚举器的值增加一而获得的值。

因此,它们的值Fruits分别是0, 1, 2,并且由于枚举的比较只不过是类型安全的整数运算,因此它的行为如您所见。

于 2019-05-19T05:31:09.370 回答