Enumeration declaration

An enumeration is a distinct type whose value is restricted to a range of values (see below for details), which may include several explicitly named constants (“enumerators”).

# Notes

Values of unscoped enumeration type can be promoted or converted to integral types:

Values of integer, floating-point, and enumeration types can be converted to any enumeration type by using static_cast. Note that the value after such conversion may not necessarily equal any of the named enumerators defined for the enumeration:

# Example

#include <cstdint>
#include <iostream>
 
// enum that takes 16 bits
enum smallenum: std::int16_t
{
    a,
    b,
    c
};
 
// color may be red (value 0), yellow (value 1), green (value 20), or blue (value 21)
enum color
{
    red,
    yellow,
    green = 20,
    blue
};
 
// altitude may be altitude::high or altitude::low
enum class altitude: char
{
    high = 'h',
    low = 'l', // trailing comma only allowed after CWG 518
}; 
 
// the constant d is 0, the constant e is 1, the constant f is 3
enum
{
    d,
    e,
    f = e + 2
};
 
// enumeration types (both scoped and unscoped) can have overloaded operators
std::ostream& operator<<(std::ostream& os, color c)
{
    switch(c)
    {
        case red   : os << "red";    break;
        case yellow: os << "yellow"; break;
        case green : os << "green";  break;
        case blue  : os << "blue";   break;
        default    : os.setstate(std::ios_base::failbit);
    }
    return os;
}
 
std::ostream& operator<<(std::ostream& os, altitude al)
{
    return os << static_cast<char>(al);
}
 
// The scoped enum (C++11) can be partially emulated in earlier C++ revisions:
 
enum struct E11 { x, y }; // since C++11
 
struct E98 { enum { x, y }; }; // OK in pre-C++11
 
namespace N98 { enum { x, y }; } // OK in pre-C++11
 
struct S98 { static const int x = 0, y = 1; }; // OK in pre-C++11
 
void emu()
{
    std::cout << (static_cast<int>(E11::y) + E98::y + N98::y + S98::y) << '\n'; // 4
}
 
namespace cxx20
{
    enum class long_long_long_name { x, y };
 
    void using_enum_demo()
    {
        std::cout << "C++20 `using enum`: __cpp_using_enum == ";
        switch (auto rnd = []{return long_long_long_name::x;}; rnd())
        {
#if defined(__cpp_using_enum)
            using enum long_long_long_name;
            case x: std::cout << __cpp_using_enum << "; x\n"; break;
            case y: std::cout << __cpp_using_enum << "; y\n"; break;
#else
            case long_long_long_name::x: std::cout << "?; x\n"; break;
            case long_long_long_name::y: std::cout << "?; y\n"; break;
#endif
        }
    }
}
 
int main()
{
    color col = red;
    altitude a;
    a = altitude::low;
 
    std::cout << "col = " << col << '\n'
              << "a = "   << a   << '\n'
              << "f = "   << f   << '\n';
 
    cxx20::using_enum_demo();
}

# Defect reports

DRApplied toBehavior as publishedCorrect behavior
CWG 377C++98the behavior was unspecified when no integraltype can represent all the enumerator valuesthe enumeration is ill-formed in this case
CWG 518C++98a trailing comma was not allowed after the enumerator listallowed
CWG 1514C++11a redefinition of enumeration with fixed underlying typecould be parsed as a bit-field in a class member declarationalways parsed as a redefinition
CWG 1638C++11grammar of opaque enumeration declarationprohibited use for template specializationsnested-name-specifierpermitted
CWG 1766C++98casting an out-of-range value to an enumerationwithout fixed underlying type had an unspecified resultthe behavior is undefined
CWG 1966C++11the resolution of CWG issue 1514 made the :of a conditional expression part of enum-baseonly apply the resolution tomember declaration specifiers
CWG 2156C++11enum definitions could defineenumeration types by using-declarationsprohibited
CWG 2157C++11the resolution of CWG issue 1966 didnot cover qualified enumeration namescovered
CWG 2530C++98an enumerator list could contain multipleenumerators with the same identifierprohibited
CWG 2590C++98the size, value representation and alignment requirementsof an enumeration did not depend on its underlying typeall of them are identical tothose of the underlying type
CWG 2621C++20the enumeration name lookup used inusing enum declarations was unclearmade clear
CWG 2877C++20the enumeration name lookup used inusing enum declarations was not type-onlymade type-only

# See also