enum class in C++ is a scoped and strongly typed enumeration introduced in modern C++. It solves several problems of the traditional enum, especially name pollution and weak type safety. With enum class, the enumerator names stay inside the enum type scope, and accidental implicit conversions to integers are not allowed in the same loose way as ordinary enums.
This makes enum class a better choice in many modern C++ programs, especially larger codebases where clear scoping and safer type rules matter. It is commonly used for states, modes, levels, protocol options, status values, and other fixed sets of named choices. In this article, we will understand what enum class is, how it differs from ordinary enum, how to declare and use it, and where it improves code quality.
What Is Enum Class in C++?
enum class defines an enumeration type whose members are scoped inside the enum name. That means enumerators are accessed using the scope resolution operator ::. This prevents enumerator names from leaking into the surrounding scope.
enum class Color
{
Red,
Green,
Blue
};After this declaration, you do not write Red directly. You write Color::Red. That small syntactic difference is one of the main reasons enum class is safer and clearer.
enum classkeeps names inside the enum and forces the programmer to be explicit about which enum value is being used.
Why Enum Class Was Introduced in C++
Traditional enums are useful, but they have weaknesses. Their enumerator names enter the surrounding scope, and their values can often convert to integers too easily. In small examples this may seem harmless, but in larger programs it can create ambiguity and bugs. enum class was introduced to give enumerations stronger scoping and better type discipline.
- It prevents enumerator name conflicts in larger programs.
- It improves type safety by reducing accidental implicit conversions.
- It makes code more explicit and easier to understand.
- It fits modern C++ design better than old unscoped enums for many cases.
- It helps separate related fixed choices without polluting global or local scope.
Syntax of Enum Class in C++
The syntax is similar to ordinary enums, but it uses the keywords enum class instead of only enum.
enum class Direction
{
North,
South,
East,
West
};Once declared, the type name is Direction, and the values are accessed as Direction::North, Direction::South, and so on.
| Feature | Ordinary enum | enum class |
|---|---|---|
| Enumerator scope | Surrounding scope | Inside enum type scope |
| Access style | Red | Color::Red |
| Implicit integer conversion | More permissive | More restricted |
| Type safety | Lower | Higher |
How to Declare and Use Enum Class Variables
You can declare a variable of an enum class type in the same way as other user-defined types. The important part is that assignment uses scoped enumerators.
enum class TrafficLight
{
Red,
Yellow,
Green
};
int main()
{
TrafficLight signal = TrafficLight::Green;
return 0;
}Here, signal is of type TrafficLight, and the assigned value is written as TrafficLight::Green. This avoids confusion with other variables or enumerators that might also be named Green.
Enum Class Members Are Scoped in C++
The scoping behavior is one of the most important advantages of enum class. With ordinary enums, names like Red and Green are injected into the surrounding scope. With enum class, the names stay under the enum type.
| Declaration Style | How Member Is Accessed |
|---|---|
enum Color { Red, Green }; | Red, Green |
enum class Color { Red, Green }; | Color::Red, Color::Green |
This scoping makes code easier to read because the type is always visible where the enumerator is used. It also reduces accidental collisions between unrelated enums.
Enum Class Prevents Easy Implicit Conversion to int
Traditional enum values can often be used like integers without much resistance. enum class does not allow that same easy implicit conversion. If you want the underlying integral value, you must convert it explicitly. This makes intent clearer and prevents careless mixing with ordinary numeric expressions.
enum class Status
{
Success,
Failure
};
int main()
{
Status result = Status::Success;
// int x = result; // invalid without explicit conversion
int x = static_cast<int>(result);
return 0;
}This is a very useful safety rule. It stops programmers from accidentally treating enum values as ordinary integers when the code should remain type-aware.
Assigning Custom Underlying Values in Enum Class
Like ordinary enums, enum class members can have custom values. This is useful when the numeric value matters, such as protocol fields, hardware registers, network commands, or application-defined status codes.
enum class ErrorCode
{
Ok = 0,
InvalidInput = 1,
Timeout = 2,
NotReady = 3
};The named values still stay scoped, but their numeric values are fully defined by the programmer. This lets the code stay expressive without giving up control over the underlying representation.
Choosing an Underlying Type for Enum Class
You can also specify the underlying integral type explicitly. This is useful when memory layout, binary compatibility, protocol requirements, or storage size matters.
enum class Mode : unsigned char
{
Idle = 0,
Run = 1,
Sleep = 2
};Here, the underlying type is explicitly chosen as unsigned char. That can matter in embedded systems, file formats, message packets, and other situations where representation details are important.
Using Enum Class in Switch Statements
enum class works very well with switch statements. The scoped member names make branch logic explicit and readable.
#include <iostream>
enum class GameState
{
Start,
Pause,
End
};
int main()
{
GameState state = GameState::Pause;
switch (state)
{
case GameState::Start:
std::cout << "Game started" << std::endl;
break;
case GameState::Pause:
std::cout << "Game paused" << std::endl;
break;
case GameState::End:
std::cout << "Game ended" << std::endl;
break;
}
return 0;
}Because each case uses the full scoped form, the code remains descriptive even when many enums exist in the same program.
Enum Class vs Enum in C++
The most practical way to understand enum class is to compare it directly with ordinary enum. Both represent fixed sets of named values, but their safety and scoping behavior differ in important ways.
| Point | enum | enum class |
|---|---|---|
| Name visibility | Enumerator names enter surrounding scope | Enumerator names stay scoped |
| Access style | Red | Color::Red |
| Implicit conversion to integer | More permissive | Requires explicit cast in ordinary use |
| Chance of name conflicts | Higher | Lower |
| Modern code preference | Useful, but older style | Often preferred for stronger safety |
If you need plain named constants with simple legacy behavior, ordinary enum may still be enough. But if you want better scoping and clearer type boundaries, enum class is usually the better tool.
Enum Class in Larger Codebases
One of the strongest arguments for enum class appears when a project grows. In a larger codebase, many subsystems may define members such as Start, Stop, Error, or None. Ordinary enums can push all of those names into the same scope and create confusion or direct name conflicts. With enum class, values remain attached to their own type, such as MotorState::Start and NetworkState::Start. That extra qualification improves readability and keeps unrelated domains separate.
This also helps function interfaces. When a function accepts enum class parameters, the caller must pass values from the correct enum type instead of mixing in raw integers or unrelated enumeration values by accident. That makes APIs easier to use correctly and harder to misuse silently.
Common Uses of Enum Class in C++
- Application states such as loading, ready, paused, and closed
- Menu actions and command identifiers
- Protocol operation codes
- Device modes in embedded and systems programming
- Permission levels, severity levels, and feature flags
- Finite state machines where strong typing helps prevent logic errors
These situations benefit from explicit naming and restricted mixing with plain integers. That is exactly where enum class shines.
How to Convert Enum Class to Its Integer Value
Since enum class does not freely convert to integer, you must use an explicit cast when you really need the underlying number. This usually happens while printing numeric codes, storing data in low-level interfaces, or matching protocol values.
enum class Level
{
Low = 1,
Medium = 2,
High = 3
};
int code = static_cast<int>(Level::High);That explicit cast acts as a signal to the reader: the code is intentionally leaving the enum type and using the numeric representation.
Common Mistakes with Enum Class in C++
- Trying to use enumerator names without the enum type scope.
- Forgetting that implicit conversion to integer is restricted.
- Using
enum classvalues in old code that expects plain integers without adding explicit casts. - Assuming
std::coutwill print the enumerator name automatically. - Choosing
enum classbut then repeatedly converting it to integers everywhere, which weakens its safety benefits.
If explicit casts appear everywhere, that can be a sign that the surrounding design still expects old unscoped enum behavior. In that case, the programmer should check whether the design or the chosen enum style really fits the problem.
Best Practices for Using Enum Class in C++
- Use
enum classwhen you want stronger type safety and cleaner scoping. - Choose descriptive enum type names and enumerator names.
- Specify an underlying type only when representation details matter.
- Use
static_castdeliberately when numeric conversion is really required. - Prefer
switchor helper functions for readable handling and output.
Frequently Asked Questions about Enum Class in C++
Why is enum class safer than enum?
Because its members are scoped and it does not allow the same loose implicit conversions to integers. This reduces naming conflicts and accidental misuse.
Can enum class have custom values?
Yes. You can assign explicit integral values to enum class members just like ordinary enums.
Do I always need to write the enum type before each member?
Yes, in normal use you write the scoped form such as Color::Red. That is part of what keeps the names organized and safe.
Should I always use enum class in modern C++?
Not always, but it is often a strong default when you want clearer scoping and stricter type behavior. Ordinary enums still have valid uses, especially in simple or legacy-oriented code.
Continue learning C++ in order
Follow the topic sequence with the previous and next lesson.