Scoped Enums (enum class) 关系运算符

Scoped Enums (enum class) relational operators

我找遍了所有地方,我不敢相信以前没有人问过这个问题。

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

#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。但是这个标准或编译器是特定的吗?

值的顺序在 [dcl.enum] point 2:

中指定

If the first enumerator has no initializer, the value of the corresponding constant is zero. An enumerator-definition without an initializer gives the enumerator the value obtained by increasing the value of the previous enumerator by one.

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

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

[expr.rel]

2 The usual arithmetic conversions are performed on operands of arithmetic or enumeration type...

5 If both operands (after conversions) are of arithmetic or enumeration type, each of the operators shall yield true if the specified relationship is true and false if it is false.

... 其中作用域枚举的常用算术转换是 no-op...

[expr]

9 Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:

  • If either operand is of scoped enumeration type ([dcl.enum]), no conversions are performed; if the other operand does not have the same type, the expression is ill-formed.

因此它们转换,并且只能与完全相同类型的对象进行比较。赋予枚举器的值(由另一个答案指定)决定是否 "each of the operators shall yield true if the specified relationship is true and false if it is false"。这样比较就完成了。

另外值得注意的是,枚举类型变量可以取不被枚举的值!例如...

enum class foo {
  min, max = 10
};

foo mid = static_cast<foo>(5);

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