Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

An unscoped enumeration is a user-defined type consisting of a set of named integral constants, known as enumerators, whose identifiers are injected directly into the enclosing scope. Unlike scoped enumerations (enum class), unscoped enumerators do not require the scope resolution operator (::) to be accessed, and they permit implicit conversions to standard integral types.

Syntax

// Standard unscoped enumeration (non-fixed underlying type)
enum Identifier {
    Enumerator1,
    Enumerator2 = ConstantExpression
};

// Unscoped enumeration with an explicit/fixed underlying type (C++11)
enum Identifier : IntegralType {
    Enumerator1,
    Enumerator2
};

// Opaque enum declaration / Forward declaration (C++11)
enum Identifier : IntegralType;

// Anonymous unscoped enumeration
enum {
    Enumerator1,
    Enumerator2
} optionalVariableList;

Technical Characteristics

Scope Injection (Leakage) The names of the enumerators are introduced into the same scope that contains the enum declaration. This prevents the reuse of those identifiers for other variables, functions, or enumerators within the same namespace or block. Underlying Type
  • Implicit (Not Fixed): If no underlying type is explicitly specified, the underlying type is not fixed. The compiler chooses an implementation-defined integral type capable of representing all enumerator values. However, the C++ Standard restricts this choice: the compiler cannot select a type larger than int unless the enumerator values cannot fit within an int or unsigned int.
  • Explicit (Fixed, C++11): You can explicitly define the underlying type using a colon followed by an integral type (e.g., std::uint8_t, long). This creates a fixed underlying type, which dictates the exact size of the enumeration and stabilizes the ABI.
Implicit Type Conversion Unscoped enumerators implicitly convert to standard integral types.
  • If the enumeration has a fixed underlying type, its enumerators implicitly convert directly to that specific underlying type first (e.g., an enumerator of enum Flags : std::uint8_t converts to std::uint8_t).
  • If the underlying type is not fixed, the enumerators undergo integral promotion to the first type in the following sequence that can represent all values of the enumeration: int, unsigned int, long, unsigned long, long long, or unsigned long long.
Conversely, converting an integer back to an unscoped enumeration requires an explicit cast (e.g., static_cast<Identifier>(value)). Opaque Enum Declarations (C++11) Unscoped enumerations that possess a fixed underlying type can be forward-declared (opaque declarations). This decouples the enumeration’s type definition from its enumerator values, allowing the type to be used in headers (e.g., for pointers, references, or function signatures) without exposing the enumerators, thereby reducing compilation dependencies. Value Assignment By default, the first enumerator is initialized to 0. Each subsequent enumerator is initialized to the value of the preceding enumerator plus 1. You can explicitly assign values using compile-time constant expressions. Multiple enumerators within the same enumeration can share the same integer value. Anonymous Enumerations The Identifier is optional. While often used to inject compile-time integral constants into the enclosing scope without creating a named type, you can declare variables of an anonymous enumeration type by declaring them in the same statement. Furthermore, subsequent variables of that exact anonymous type can be declared using C++11’s decltype.

Code Visualization

#include <cstdint>

// Opaque enum declaration (Forward declaration) requires a fixed underlying type
enum ForwardEnum : std::uint16_t;

// Standard unscoped enum (Implicit/non-fixed underlying type)
// Compiler will choose an underlying type no larger than 'int' here
enum Status {
    Pending,       // 0
    Active = 5,    // 5
    Suspended      // 6 (Active + 1)
};

// Explicit/fixed underlying type (C++11)
enum Flags : std::uint8_t {
    Read = 1,
    Write = 2,
    Execute = 4
};

// Anonymous enum with immediate variable declaration
enum { MaxRetries = 3 } retryConfig;

void demonstrateMechanics() {
    // Scope injection: Enumerators accessed without Status:: prefix
    Status currentStatus = Active; 
    
    // Implicit conversion for a fixed underlying type
    // Flags::Read converts directly to std::uint8_t first
    std::uint8_t numericFlag = Read; 
    
    // Implicit conversion for a non-fixed underlying type
    // Promotes to int (or larger if values exceeded int/unsigned int limits)
    int numericStatus = Suspended; 
    
    // Explicit cast required from integer to enum
    Status forcedStatus = static_cast<Status>(0); 
    
    // Anonymous enum injecting constants into the block scope
    enum { TimeoutMs = 5000 };
    int currentTimeout = TimeoutMs;

    // Declaring another variable of the anonymous enum type using decltype
    decltype(retryConfig) backupConfig = MaxRetries;
}

// Definition of the previously forward-declared enum
enum ForwardEnum : std::uint16_t {
    ValueA = 10,
    ValueB = 20
};
Master C++ with Deep Grasping Methodology!Learn More