An Enum is a way of expressing a [[Type]] with a finite amount of valid states ([[Sum Type]]). For example, if we wanted to have some function that takes in a cardinal direction and prints it out as a string, you could do something like this: ```cpp void print_cardinal(int x) { switch x { case 0: std::cout << "North"; break; case 1: std::cout << "East"; break; case 2: std::cout << "South"; break; case 3: std::cout << "West"; break; default: return; } } ``` While this works, there are two major issues with this. The first of which is that you need to know what each $\color{lightyellow}\text{int}$ corresponds to each direction, which is impossible to know without looking *inside* the function. A way we could rectify this is having public constants for what numbers correspond to what direction. ```cpp const int NORTH = 0; const int EAST = 1; const int SOUTH = 2; const int WEST = 3; void print_cardinal(int x) { switch x { case NORTH: std::cout << "North"; break; case EAST: std::cout << "East"; break; case SOUTH: std::cout << "South"; break; case WEST: std::cout << "West"; break; default: return; } } int main() { print_cardinal(NORTH); print_cardinal(SOUTH); // ... } ``` While this works, this still isn't an ideal, because if you look at the function signature: ```cpp void print_cardinal(int x) ``` Without reading any comments, what this function signature tells us is that this function takes in *any* integer, even though we know that isn't true. Although you can give any integer, not every integer is a valid input ($\set{0 ,1, 2 ,3}$). An extension of [[The Goal]] that relates to this problem is being able to [[Make Invalid States Unrepresentable]]. A common way to do this is encode any constraints / [[Invariant|Invariants]] within the [[Type System]]. Looking at the problem, notice how there is nothing special about the integers $\set{0, 1, 2, 3}$, the only property we care about is that they they are distinct - and we give meaning to each number by associating it to a cardinal direction. If we changed $\color{lightblue} \text{NORTH}$ to be $420$ instead of $0$, our program would still work (assuming we are using the NORTH constant and not manually using 0 anywhere). What this means is that our input, an integer that represents a cardinal direction, has *$4$* valid states: - An *integer* that maps to $\color{lightblue}\text{NORTH}$ - An *integer* that maps to $\color{lightblue}\text{EAST}$ - An *integer* that maps to $\color{lightblue}\text{SOUTH}$ - An *integer* that maps to $\color{lightblue}\text{WEST}$ The actual *value* behind these states are only used to distinguish the different states from one another, as if two states have the same underlying *integer value*, it would be impossible to distinguish between them. In contrast, if we look at our current function signature, the inputs we can give it are *not* the $4$ valid $\color{lightyellow}\text{Cardinal}$ directions, but any valid $\color{lightyellow}\text{int}$. This is where Enums come into play. Enums in C-like languages (C, [[C++]], [[Rust]], etc) allow us to define a type that is constrained to a finite number of states. Using an Enum for our `print_cardinal` implementation would look like this: ```cpp enum class Cardinal { NORTH, EAST, SOUTH, WEST }; void print_cardinal(Cardinal x) { switch x { case Cardinal::NORTH: std::cout << "North"; break; case Cardinal::EAST: std::cout << "East"; break; case Cardinal::SOUTH: std::cout << "South"; break; case Cardinal::WEST: std::cout << "West"; break; default: return; } } int main() { print_cardinal(Cardinal::NORTH); print_cardinal(Cardinal::SOUTH); print_cardinal(5); // Compiler Error, cannot impliciticly cast an 'int' -> Cardinal // ... } ``` Using an Enum allows us to define a [[Type]] with the [[Invariant]] that a value of this Enum is one of those 4 states we defined, meaning we have changed our function signature to only be able to take an instance of a [[Validity|Valid]] instance of type $\color{lightyellow}\text{Cardinal}$ ($\color{lightblue}\text{NORTH}$, $\color{lightblue}\text{EAST}$, $\color{lightblue}\text{SOUTH}$, $\color{lightblue}\text{WEST}$).