C++ enum class: an Encapsulated Enumeration
Enums, or enumerated types, are user-defined data types in C and C++ that allow the programmer to define a set of named values. These values are fixed and predetermined at the time of declaration. However, traditional / C enums have a big drawback: the names of two enum's (1) may collide --that is, coincide-- and thereby create ambiguity, actually a compilation error, because (2) traditional enum's are not scoped.
The Problem with Tranditional Enumerations
Consider two different enumerations for garment sizes and cooked meat:
enum garment_size {tiny, small, medium, large, extra_large};
enum cooked_meat {rare, medium, well_done};
cooked_meat my_steak = medium; // Fails to compile!
cooked_meat my_steak = rare; // Also ails to compile!
enum garment_size {tiny, small, medium, large, extra_large};
enum cooked_meat {rare, medium, well_done};
cooked_meat my_steak = medium; // Fails to compile!
cooked_meat my_steak = rare; // Also ails to compile!
Now, if I rewrite garment_size::medium as garment_size::medium_size, thereby preventing a name clash, my compiler will still issue an error or a warning if I try to assign the wrong value to a variable:
enum garment_size {tiny, small, medium_size, large, extra_large};
enum cooked_meat {rare, medium, well_done};
cooked_meat my_steak = medium_size; // Fails to compile or a warning is issued!
The Solution: Using enum class
(From https://www.geeksforgeeks.org/cpp/enum-classes-in-c-and-their-advantage-over-enum-datatype/)
C++11 has introduced enum classes (also called scoped enumerations), which makes enumerations both strongly typed and strongly scoped. Class enum doesn't allow implicit conversion to int, and also doesn't compare enumerators from different enumerations.
To define enum class we use class keyword after enum keyword.
Syntax:
// Declaration
enum class EnumName { Value1, Value2, ... ValueN};
// Initialisation
EnumName ObjectName = EnumName::Value;
Example:
// Declaration
enum class Color{ Red, Green, Blue};
// Initialisation
Color col = Color::Red;
Choosing the Underlying Type
Enumerated types declared the enum class also have more control over their underlying type; it may be any integral data type, such as char, short or unsigned int, which essentially serves to determines the size of the type.
This is specified by a colon and underlying type following the enumerated type:
enum class eyecolor : short int {black = -2, brown, green, blue};
Here eyecolor is a distinct type with the same size as an short int.
We can next get the matching integer value through a static cast as in:
cout << "brown colour matches short int: " << static_cast<signed int>(eyecolor::brown) << '\n';
Which will output:
brown colour matches short int: -1
just as expected.