Traditional enum in C++

1
2
3
4
5
6
7
8
enum Week        {Mon   ,Tue   ,Wed  ,Thu  };
enum Season      {Sprint,Summer,Fall ,Winter};

Week w = Tue;
Season s = Summer;

bool isEqual = (w == s); // isEqual is true
}

Problem

非类型安全,比如对Week wSeason s两个逻辑意义上不同类型的变量作比较,会产生不合逻辑的结果:w == strue

It’s not safe, the result of w == s is true is not reasonalbe.

不同类型的 enum 比较会有编译警告warning,但只是警告:

1
2
3
warning: comparison between ‘enum Week’ and ‘enum Season’ [-Wenum-compare]
      |   bool isEqual = (w == s);
      |                        ^

Scoped enum

  • enum class and enum struct are the same
  • enum class is not a class
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <iostream>

using namespace std;

namespace EnumOnly {
enum Week { Mon, Tue, Wed, Thu };
enum Season { Sprint, Summer, Fall, Winter };
} // namespace EnumOnly

namespace EnumClass {
enum class Month { Jan, Feb, Mar, Apr };
enum class Num { One=1, Two, Three, Four };

} // namespace EnumClass

int main() {
  cout << "EnumOnly::Week::Mon = " << EnumOnly::Week::Mon << endl;
  cout << "EnumClass::Month::Jan = " << static_cast<int>(EnumClass::Month::Jan) << endl;

  cout << "Is EnumOnly::Week a class : " << std::is_class<EnumOnly::Week>::value << endl;
  cout << "Is EnumOnly::Week a enum : " << std::is_enum<EnumOnly::Week>::value << endl;

  cout << "Is EnumClass::Month a class : " << std::is_class<EnumClass::Month>::value << endl;
  cout << "Is EnumClass::Month a enum : " << std::is_enum<EnumClass::Month>::value << endl;


  EnumOnly::Week w = EnumOnly::Tue;
  EnumOnly::Season s = EnumOnly::Summer;

  EnumClass::Month m = EnumClass::Month::Feb;
  EnumClass::Num n = EnumClass::Num::Two;
  EnumClass::Num n2 = static_cast<EnumClass::Num>(2);
  EnumClass::Num n3 = EnumClass::Num::Three;

  if (w == s) {
    cout << "w == s, ohh!" << endl;  // unmeaningful
  } else {
    cout << "w != s" << endl;
  }
  
  if (n == n2) {
    cout << "n == n2, yes" << endl;
  } else {
    cout << "n != n2, why" << endl;
  }

  if (n == n3) {
    cout << "n == n3" << endl;
  } else {
    cout << "n != n3, yes" << endl;
  }
/*
  if (w == m) {
    cout << "w == m";
  } else {
    cout << "w != m";
  }
*/
  return 0;
}

输出如下:

1
2
3
4
5
6
7
8
9
EnumOnly::Week::Mon = 0
EnumClass::Month::Jan = 0
Is EnumOnly::Week a class : 0
Is EnumOnly::Week a enum : 1
Is EnumClass::Month a class : 0
Is EnumClass::Month a enum : 1
w == s, ohh!
n == n2, yes
n != n3, yes

如果用 == 比较两个不同类型的 enum class 对象会产生编译错误。 比如用if (w == m)比较 enum Week 类型的 wenum class Month 类型的 m 会产生如下错误 error

1
2
3
4
5
6
error: no match for ‘operator==(operand types are ‘EnumOnly::Week’ and ‘EnumClass::Month’)
      |   if (w == m) {
      |       ~ ^~ ~
      |       |    |
      |       |    EnumClass::Month
      |       EnumOnly::Week

== 比较两个不同的 enum class 对象也会产生相同的编译错误。