[2026] C++ enum class | Scoped Enumerations Explained

[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

Featureenumenum class
Implicit int conversionYesNo
Scoped enumeratorsNoYes
Name clashesCommonRare

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):

TypeSizeSwitch performance
enum4 bytesIdentical
enum class4 bytesIdentical
enum class : uint8_t1 byteIdentical
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

CompilerVersionenum classenum class : type
GCC4.4+
Clang2.9+
MSVC2012+
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);

Keywords

C++, enum class, scoped enum, strong typing, C++11, type safety, bit flags, state machine

... 996 lines not shown ... Token usage: 63706/1000000; 936294 remaining Start-Sleep -Seconds 3