[2026] C++ enum class | Scoped Enumerations Explained
이 글의 핵심
Strongly typed scoped enums in C++11: no implicit int conversion, explicit underlying types, switch hygiene, and bit flags with constexpr helpers.
What is enum class?
Scoped enumeration (enum class) is a strongly typed enum: enumerators live under the enum’s scope and do not implicitly convert to integers.
아래 코드는 cpp를 사용한 구현 예제입니다. 에러 처리를 통해 안정성을 확보합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
enum class Status { OK, Error, Pending };
Status s = Status::OK;
// int x = s; // error
int x = static_cast<int>(s);
Compared to plain enum
| Feature | enum | enum class |
|---|---|---|
| Implicit int conversion | Yes | No |
| Scoped enumerators | No | Yes |
| Name clashes | Common | Rare |
Basic usage
아래 코드는 cpp를 사용한 구현 예제입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
enum class Color { Red, Green, Blue };
Color c = Color::Red;
if (c == Color::Red) { /* ....*/ }
switch (c) {
case Color::Red: break;
case Color::Green: break;
case Color::Blue: break;
}
Underlying type
enum class Small : std::uint8_t { A, B, C };
enum class Flags : std::uint32_t { Read = 1 << 0, Write = 1 << 1 };
Bit flags
enum class does not enable | by default; overload operators or use std::to_underlying (C++23) / static_cast for masks.
Implementing bitwise operators
다음은 cpp를 활용한 상세한 구현 코드입니다. 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
enum class Permission : uint32_t {
None = 0,
Read = 1 << 0,
Write = 1 << 1,
Execute = 1 << 2,
Delete = 1 << 3
};
// Overload operators for type-safe bit manipulation
constexpr Permission operator|(Permission lhs, Permission rhs) {
return static_cast<Permission>(
static_cast<uint32_t>(lhs) | static_cast<uint32_t>(rhs)
);
}
constexpr Permission operator&(Permission lhs, Permission rhs) {
return static_cast<Permission>(
static_cast<uint32_t>(lhs) & static_cast<uint32_t>(rhs)
);
}
constexpr Permission operator~(Permission p) {
return static_cast<Permission>(~static_cast<uint32_t>(p));
}
constexpr bool hasPermission(Permission flags, Permission check) {
return (flags & check) == check;
}
// Usage
Permission userPerms = Permission::Read | Permission::Write;
if (hasPermission(userPerms, Permission::Read)) {
// Can read
}
Real-world use cases
1. State machines
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
enum class ConnectionState {
Disconnected,
Connecting,
Connected,
Reconnecting,
Failed
};
class NetworkClient {
ConnectionState state_ = ConnectionState::Disconnected;
public:
void connect() {
if (state_ == ConnectionState::Disconnected) {
state_ = ConnectionState::Connecting;
// ....connection logic
}
}
bool isConnected() const {
return state_ == ConnectionState::Connected;
}
std::string_view stateString() const {
switch (state_) {
case ConnectionState::Disconnected: return "Disconnected";
case ConnectionState::Connecting: return "Connecting";
case ConnectionState::Connected: return "Connected";
case ConnectionState::Reconnecting: return "Reconnecting";
case ConnectionState::Failed: return "Failed";
}
return "Unknown";
}
};
2. Configuration options
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
enum class LogLevel : uint8_t {
Trace,
Debug,
Info,
Warning,
Error,
Fatal
};
class Logger {
LogLevel minLevel_ = LogLevel::Info;
public:
void setLevel(LogLevel level) { minLevel_ = level; }
template<typename....Args>
void log(LogLevel level, Args&&....args) {
if (level >= minLevel_) {
// Output log message
}
}
};
// Usage
Logger logger;
logger.setLevel(LogLevel::Debug);
logger.log(LogLevel::Info, "Application started");
3. Error codes
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
enum class ErrorCode : int32_t {
Success = 0,
InvalidArgument = 1,
FileNotFound = 2,
PermissionDenied = 3,
NetworkError = 4,
Timeout = 5
};
struct Result {
ErrorCode code;
std::string message;
explicit operator bool() const {
return code == ErrorCode::Success;
}
};
Result openFile(const std::string& path) {
if (path.empty()) {
return {ErrorCode::InvalidArgument, "Path is empty"};
}
// ....file opening logic
return {ErrorCode::Success, ""};
}
Common pitfalls and solutions
Pitfall 1: Forgetting scope
아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
enum class Color { Red, Green, Blue };
// ❌ Error: 'Red' not declared
Color c = Red;
// ✅ Correct: use scope
Color c = Color::Red;
Pitfall 2: Implicit conversion expectations
아래 코드는 cpp를 사용한 구현 예제입니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
enum class Status { OK, Error };
// ❌ Error: no implicit conversion
int x = Status::OK;
// ✅ Explicit cast
int x = static_cast<int>(Status::OK);
// Better: use std::to_underlying (C++23)
int x = std::to_underlying(Status::OK);
Pitfall 3: Switch without all cases
아래 코드는 cpp를 사용한 구현 예제입니다. 조건문으로 분기 처리를 수행합니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
enum class State { Idle, Running, Paused, Stopped };
void handleState(State s) {
switch (s) {
case State::Idle: break;
case State::Running: break;
// ⚠️ Missing Paused and Stopped
}
}
Fix: Enable compiler warnings: 아래 코드는 bash를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요.
# GCC/Clang
-Wswitch-enum # Warn on missing cases
# MSVC
/Wall # Enables C4062 warning
Performance considerations
Memory layout: Underlying type controls size:
enum class Tiny : uint8_t { A, B, C }; // 1 byte
enum class Normal { A, B, C }; // int (4 bytes on most platforms)
enum class Large : uint64_t { A, B, C }; // 8 bytes
Benchmark (GCC 13, -O3):
| Type | Size | Switch performance |
|---|---|---|
enum | 4 bytes | Identical |
enum class | 4 bytes | Identical |
enum class : uint8_t | 1 byte | Identical |
Key insight: enum class has zero runtime overhead compared to enum. The type safety is compile-time only. |
Serialization patterns
JSON conversion
아래 코드는 cpp를 사용한 구현 예제입니다. 필요한 모듈을 import하고. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
#include <nlohmann/json.hpp>
enum class Priority { Low, Medium, High };
NLOHMANN_JSON_SERIALIZE_ENUM(Priority, {
{Priority::Low, "low"},
{Priority::Medium, "medium"},
{Priority::High, "high"}
})
// Usage
nlohmann::json j = Priority::High; // "high"
Priority p = j.get<Priority>();
String conversion helper
다음은 cpp를 활용한 상세한 구현 코드입니다. 클래스를 정의하여 데이터와 기능을 캡슐화하며, 반복문으로 데이터를 처리합니다, 조건문으로 분기 처리를 수행합니다. 각 부분의 역할을 이해하면서 코드를 살펴보시기 바랍니다.
template<typename E>
struct EnumTraits;
template<>
struct EnumTraits<Color> {
static constexpr std::array names = {"Red", "Green", "Blue"};
static std::string_view toString(Color c) {
return names[static_cast<size_t>(c)];
}
static std::optional<Color> fromString(std::string_view s) {
for (size_t i = 0; i < names.size(); ++i) {
if (names[i] == s) {
return static_cast<Color>(i);
}
}
return std::nullopt;
}
};
Compiler support
| Compiler | Version | enum class | enum class : type |
|---|---|---|---|
| GCC | 4.4+ | ✅ | ✅ |
| Clang | 2.9+ | ✅ | ✅ |
| MSVC | 2012+ | ✅ | ✅ |
C++23 addition: std::to_underlying simplifies casting: | |||
| 아래 코드는 cpp를 사용한 구현 예제입니다. 코드를 직접 실행해보면서 동작을 확인해보세요. |
// C++11-20
auto val = static_cast<std::underlying_type_t<Status>>(Status::OK);
// C++23
auto val = std::to_underlying(Status::OK);
Related posts
Keywords
C++, enum class, scoped enum, strong typing, C++11, type safety, bit flags, state machine