Enumeration Scoping in C++

C++
Author

Jim Carr

Published

August 5, 2021

The Problem

I spent way too much time trying to figure out what was wrong with this code:

#include <iostream>
 
using namespace std;
 
enum enum_1 { ok, warning, error };
 
enum enum_2 { ok, warning, error };
 
int main() {
  enum_1 my_value1 = enum_1::ok;
  enum_2 my_value2 = enum_2::error;
 
  if (my_value1 == enum_1::ok) {
    cout << "my_value1 is OK!" << endl;
  } else {
    cout << "my_value1 is not OK!" << endl;
  }
 
  if (my_value2 == enum_2::ok) {
    cout << "my_value2 is OK!" << endl;
  } else {
    cout << "my_value2 is not OK!" << endl;
  }
 
  return (0);
}

Trying to build this code produces the following errors:

main.cpp:9:15: error: redefinition of enumerator 'ok'
enum enum_2 { ok, warning, error };
              ^
main.cpp:6:15: note: previous definition is here
enum enum_1 { ok, warning, error };
              ^
main.cpp:9:19: error: redefinition of enumerator 'warning'
enum enum_2 { ok, warning, error };
                  ^
main.cpp:6:19: note: previous definition is here
enum enum_1 { ok, warning, error };
                  ^
main.cpp:9:28: error: redefinition of enumerator 'error'
enum enum_2 { ok, warning, error };
                           ^
main.cpp:6:28: note: previous definition is here
enum enum_1 { ok, warning, error };
                           ^
main.cpp:13:30: error: no member named 'error' in 'enum_2'
enum_2 my_value2 = enum_2::error;
                   ~~~~~~~~^
main.cpp:21:20: error: no member named 'ok' in 'enum_2'; did you mean simply 'ok'?
if (my_value2 == enum_2::ok) {
                 ^~~~~~~~~~
                 ok
main.cpp:6:15: note: 'ok' declared here
enum enum_1 { ok, warning, error };
              ^

A quick search of StackOverflow, and I learned that “old style” enumerations in C++ are unscoped. Since the individual members in enums are global, the member names have to be unique.

Solution 1 (C++11)

If your compiler supports the C++11 standard, the fix is easy. Just add “class” to your enum declarations:

#include <iostream>
 
using namespace std;
 
enum class enum_1 { ok, warning, error };
 
enum class enum_2 { ok, warning, error };
 
int main() {
  enum_1 my_value1 = enum_1::ok;
  enum_2 my_value2 = enum_2::error;
 
  if (my_value1 == enum_1::ok) {
    cout << "my_value1 is OK!" << endl;
  } else {
    cout << "my_value1 is not OK!" << endl;
  }
 
  if (my_value2 == enum_2::ok) {
    cout << "my_value2 is OK!" << endl;
  } else {
    cout << "my_value2 is not OK!" << endl;
  }
 
  return (0);
}

Solution 2

Alternatively, you can wrap your enums in namespaces:

namespace scope1 {
  enum enum_1 { ok, warning, error };
}
 
namespace scope2 {
  enum enum_2 { ok, warning, error };
}

Then, you can access the members as scope1::enum_1::ok, scope2::enum_2::warning, etc.