Enumerations
enum) lets you define a type whose values are
restricted to a named set of options, which makes code far more readable than
using raw integers to represent a fixed set of choices.
Plain enum (C-Style, Unscoped)
enum Color { RED, GREEN, BLUE };
int main() {
Color favorite = GREEN;
if (favorite == GREEN) {
// ...
}
int rawValue = favorite; // implicit conversion to int is allowed: 1
return 0;
}enum's values (RED, GREEN, BLUE) leak into the surrounding scope, so they can collide with other names — you cannot have another enum or constant named RED in the same scope. Plain enums also convert implicitly to int, which means the compiler will not stop you from comparing or mixing unrelated enums, or assigning an out-of-range integer.enum class (Scoped, C++11+)
enum class (also called a scoped enumeration) fixes both
problems: its values live inside the enum's own namespace, and it does not
implicitly convert to int.
enum class Color { Red, Green, Blue };
enum class TrafficLight { Red, Yellow, Green }; // no collision with Color::Red
int main() {
Color favorite = Color::Green; // must qualify with the enum name
if (favorite == Color::Green) {
// ...
}
// int rawValue = favorite; // ERROR: no implicit conversion to int
int rawValue = static_cast<int>(favorite); // must cast explicitly
return 0;
}enum vs enum class
Aspect | enum (unscoped) | enum class (scoped) |
|---|---|---|
Introduced | C (pre-C++) | C++11 |
Namespace pollution | Yes — values leak into enclosing scope | No — values require |
Implicit conversion to int | Yes | No — requires |
Comparing across different enums | Allowed (dangerous) | Not allowed — compile error |
Recommended for new code | No | Yes |
Specifying the Underlying Type
By default the compiler picks an underlying integer type large enough to hold all the enumerators. You can specify it explicitly — useful when the enum is serialized, stored compactly, or needs a predictable size.
#include <cstdint>
enum class Color : uint8_t { Red, Green, Blue }; // guaranteed 1 byte
int main() {
Color c = Color::Blue;
return 0;
}enum class Color : uint8_t;) without listing its enumerators, which can reduce header dependencies in large projects.Using Enums in a switch Statement
switch statements, which we cover in
depth on its own page. Here is a quick preview:
#include <iostream>
enum class Color { Red, Green, Blue };
std::string colorName(Color c) {
switch (c) {
case Color::Red: return "Red";
case Color::Green: return "Green";
case Color::Blue: return "Blue";
}
return "Unknown";
}
int main() {
std::cout << colorName(Color::Green) << std::endl;
return 0;
}Prefer
enum classfor all new code — it is safer with no meaningful downsideUse a plain
enumonly when interoperating with older C-style APIs that expect implicit int conversionA
switchover anenum classstill requires qualifying each case withEnumName::Value