Enumerations give names to a fixed set of integral values. Prefer the scoped enum class (C++11): its names don't leak and it doesn't convert to int silently.
Unscoped enum (C-style)
#include <iostream>
enum Color { Red, Green, Blue }; // Red=0, Green=1, Blue=2
enum Status { Ok = 200, NotFound = 404 }; // explicit values
int main() {
Color c = Green;
int n = c; // implicit conversion to int
std::cout << n << ' ' << Blue + 1 << ' ' << NotFound << '\n';
}1 3 404Scoped enum class
#include <cstdint>
#include <iostream>
#include <string_view>
enum class Direction : std::uint8_t { North, East, South, West }; // underlying type: 1 byte
std::string_view name(Direction d) {
switch (d) {
case Direction::North: return "North";
case Direction::East: return "East";
case Direction::South: return "South";
case Direction::West: return "West";
}
return "?";
}
Direction turnRight(Direction d) {
return static_cast<Direction>((static_cast<int>(d) + 1) % 4); // explicit conversions
}
int main() {
Direction d = Direction::West;
std::cout << name(d) << " -> " << name(turnRight(d)) << '\n';
std::cout << sizeof(Direction) << ' ' << static_cast<int>(Direction::South) << '\n';
}West -> North
1 2enum class Fruit { Apple, Pear };
int main() {
int x = Fruit::Apple; // error: no implicit conversion to int
return x;
}enum | enum class | |
|---|---|---|
| Names scoped? | No — Red | Yes — Color::Red |
Implicit → int? | Yes | No — needs static_cast |
| Underlying type | Implementation-chosen (can be fixed) | int by default, can be fixed (: std::uint8_t) |
| Forward-declarable | Only with fixed underlying type | Yes |
Why prefer enum class over plain enum?