Enumerations
2 min read
Enumerations
An enumeration defines a type whose values are a fixed set of named constants. Enumerations make code more readable and prevent magic numbers from spreading through a codebase.
Scoped enumerations (enum class)
C++11 introduced scoped enumerations, which are the modern default:
#include <iostream>
enum class Direction {
North,
South,
East,
West
};
void move(Direction d) {
if (d == Direction::North) std::cout << "Moving north\n";
else if (d == Direction::South) std::cout << "Moving south\n";
else if (d == Direction::East) std::cout << "Moving east\n";
else std::cout << "Moving west\n";
}
int main() {
Direction dir = Direction::North;
move(dir);
// Direction::North == 0 would be a compile error — no implicit int conversion
}
The Direction:: prefix is required for every value. This prevents name collisions and accidental comparisons against raw integers.
Underlying type
By default the underlying type is int, but you can specify any integer type:
enum class Status : uint8_t {
OK = 0,
NotFound = 1,
Error = 2
};
Status s = Status::OK;
std::cout << static_cast<int>(s) << "\n"; // 0
Explicit values make the integers stable across versions, which matters when they are stored on disk or sent over a network.
switch with enum class
switch is a natural match for enumerations. A compiler warning will tell you if you miss a case:
enum class Season { Spring, Summer, Autumn, Winter };
std::string describe(Season s) {
switch (s) {
case Season::Spring: return "flowers";
case Season::Summer: return "heat";
case Season::Autumn: return "leaves";
case Season::Winter: return "snow";
}
return "unknown"; // unreachable, but satisfies the compiler
}
Unscoped enumerations (enum)
The original C-style enum is still available. Its values are injected directly into the enclosing scope and implicitly convert to int:
enum Color { Red, Green, Blue };
Color c = Green;
int n = c; // implicit conversion: n == 1
bool b = (c == 1); // compares with int — allowed but messy
Unscoped enums cause problems when the same name appears in two enums in the same scope, or when implicit integer conversions produce unexpected results. Prefer enum class in new code.
Iterating over enum values
There is no built-in way to iterate over enum values. The common pattern is a sentinel value at the end:
enum class Suit { Clubs, Diamonds, Hearts, Spades, COUNT };
for (int i = 0; i < static_cast<int>(Suit::COUNT); i++) {
Suit s = static_cast<Suit>(i);
// process s
}
Or maintain a separate array of all values:
constexpr Suit all_suits[] = {
Suit::Clubs, Suit::Diamonds, Suit::Hearts, Suit::Spades
};
for (Suit s : all_suits) { /* ... */ }
Learn modern C++ through working code. Each chapter introduces one concept — variables, functions, classes, templates, smart pointers, concurrency — with a clear example, a line-by-line explanation, and notes on how it applies in real programs.
View book →