简体   繁体   中英

Scoped Enums (enum class) relational operators

I've looked all over the place and I can't believe this question has not been asked before.

Is the ordering of scoped enumerators defined by the standard? Say if I have the following

#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

This outputs 1 0 in g++. But is this standard or compiler specific?

The ordering of the values is specified in [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.

Therefore the values of Fruits are 0, 1, 2 respectively and since comparisons on enums are little more than type safe integer operations it behaves as you see.

To complete the picture and confirm that yes, the ordering is defined. We start with why one may put two enumerators in a relational expression...

[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.

... where the usual arithmetic conversion for a scoped enumeration is a 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.

So they do not convert, and may only be compared to an object of the same exact type. The values given to the enumerators (as specified by the other answer) are what determines if "each of the operators shall yield true if the specified relationship is true and false if it is false" . That's how the comparison is done.

It's also worth noting that enumeration type variables can take values that are not enumerated! So for instance...

enum class foo {
  min, max = 10
};

foo mid = static_cast<foo>(5);

... is valid, and the comparison mid > foo::min will hold just the same, because the preceding paragraph is generalized to include more than just the named values.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM