Namensräume
Varianten
Aktionen

Enumeration declaration

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Eine Aufzählung ist ein eigener Typ, dessen Werte auf einen Wertebereich beschränkt sind (Details siehe unten), der mehrere explizit benannte Konstanten („Aufzählungswerte“) enthalten kann.

Die Werte der Konstanten sind Werte eines ganzzahligen Typs, der als zugrundeliegender Typ der Aufzählung bekannt ist. Eine Aufzählung hat die gleiche Größe, Wertdarstellung und Ausrichtungsvoraussetzungen wie ihr zugrundeliegender Typ. Darüber hinaus hat jeder Wert einer Aufzählung die gleiche Darstellung wie der entsprechende Wert des zugrundeliegenden Typs.

Eine Aufzählung wird mit der folgenden Syntax (neu) deklariert:

enum-key attr (optional) enum-head-name (optional) enum-base (optional)
{ enumerator-list (optional) }
(1)
enum-key attr (optional) enum-head-name (optional) enum-base (optional)
{ enumerator-list , }
(2)
enum-key attr (optional) enum-head-name enum-base (optional) ; (3) (seit C++11)
1) enum-specifier, der in decl-specifier-seq der Deklarationssyntax vorkommt: Definiert den Aufzählungstyp und seine Aufzählungswerte.
2) Ein nachfolgendes Komma kann der enumerator-list folgen.
3) Opaque enum declaration: Definiert den Aufzählungstyp, aber nicht seine Aufzählungswerte. Nach dieser Deklaration ist der Typ ein vollständiger Typ und seine Größe ist bekannt.
enum-key -

enum

(bis C++11)

eines von enum, enum class oder enum struct

(seit C++11)
attr - (seit C++11) optionale Sequenz beliebig vieler Attribute
enum-head-name -

der Name der zu deklarierenden Aufzählung, er kann weggelassen werden.

(bis C++11)

der Name der zu deklarierenden Aufzählung, optional vorangestellt von einem nested-name-specifier: Eine Sequenz von Namen und Scope-Auflösungsoperatoren ::, endend mit einem Scope-Auflösungsoperator. Er kann nur in nicht-scoped, nicht-opaken Aufzählungsdeklarationen weggelassen werden.
nested-name-specifier kann nur erscheinen, wenn der Aufzählungsname vorhanden ist und diese Deklaration eine Neudeklaration ist. Bei opaken Aufzählungsdeklarationen kann nested-name-specifier nur vor dem Namen der Aufzählung in expliziten Spezialisierungsdeklarationen erscheinen.
Wenn nested-name-specifier vorhanden ist, kann der enum-specifier keine Aufzählung referenzieren, die lediglich geerbt oder durch eine using Deklaration eingeführt wurde, und der enum-specifier kann nur in einem Namespace erscheinen, der die vorherige Deklaration umschließt. In solchen Fällen kann nested-name-specifier nicht mit einem decltype-Spezifizierer beginnen.

(seit C++11)
enum-base - (seit C++11) Ein Doppelpunkt (:), gefolgt von einer type-specifier-seq, die einen ganzzahligen Typ benennt (wenn er cv-qualifiziert ist, werden die Qualifizierer ignoriert), der als fester zugrundeliegender Typ für diesen Aufzählungstyp dient.
enumerator-list - eine durch Kommas getrennte Liste von Aufzählungswerte-Definitionen, die jeweils entweder einfach ein eindeutiger identifier ist, der zum Namen des Aufzählungswerts wird, oder ein eindeutiger Bezeichner mit einem konstanten Ausdruck: identifier = constant-expression. In beiden Fällen kann der identifier optional von einer Attributspezifikationssequenz gefolgt werden.(seit C++17)

Es gibt zwei verschiedene Arten von Aufzählungen: nicht-scoped Aufzählungen (deklariert mit dem enum-key enum) und scoped Aufzählungen (deklariert mit dem enum-key enum class oder enum struct).

Inhalt

[bearbeiten] Nicht-scoped Aufzählungen

enum name (optional) { enumerator = constant-expression , enumerator = constant-expression , ... } (1)
enum name (optional) : type { enumerator = constant-expression , enumerator = constant-expression , ... } (2) (seit C++11)
enum name : type ; (3) (seit C++11)
1) Deklariert einen nicht-scoped Aufzählungstyp, dessen zugrundeliegender Typ nicht festgelegt ist (in diesem Fall ist der zugrundeliegende Typ ein implementierungsdefinierter ganzzahliger Typ, der alle Aufzählungswerte darstellen kann; dieser Typ ist nicht größer als int, es sei denn, der Wert eines Aufzählungswerts passt nicht in einen int oder unsigned int. Wenn die enumerator-list leer ist, ist der zugrundeliegende Typ so, als hätte die Aufzählung einen einzigen Aufzählungswert mit dem Wert 0. Wenn kein ganzzahliger Typ alle Aufzählungswerte darstellen kann, ist die Aufzählung fehlerhaft).
2) Deklariert einen nicht-scoped Aufzählungstyp, dessen zugrundeliegender Typ festgelegt ist.
3) Eine opake Aufzählungsdeklaration für eine nicht-scoped Aufzählung muss den Namen und den zugrundeliegenden Typ angeben.

Jeder enumerator wird zu einer benannten Konstanten des Aufzählungstyps (d. h. name), die im umschließenden Geltungsbereich sichtbar ist und immer dann verwendet werden kann, wenn Konstanten benötigt werden.

enum Color { red, green, blue };
Color r = red;
 
switch(r)
{
    case red  : std::cout << "red\n";   break;
    case green: std::cout << "green\n"; break;
    case blue : std::cout << "blue\n";  break;
}

Jeder Aufzählungswert wird einem Wert des zugrundeliegenden Typs zugeordnet. Wenn = in einer enumerator-list angegeben ist, werden die Werte der Aufzählungswerte durch die zugehörigen constant-expression definiert. Wenn der erste Aufzählungswert kein = hat, ist der zugehörige Wert null. Für jeden anderen Aufzählungswert, dessen Definition kein = hat, ist der zugehörige Wert der Wert des vorherigen Aufzählungswerts plus eins.

enum Foo { a, b, c = 10, d, e = 1, f, g = f + c };
//a = 0, b = 1, c = 10, d = 11, e = 1, f = 2, g = 12

Der name einer nicht-scoped Aufzählung kann weggelassen werden: Eine solche Deklaration führt lediglich die Aufzählungswerte in den umschließenden Geltungsbereich ein.

enum { a, b, c = 0, d = a + 2 }; // defines a = 0, b = 1, c = 0, d = 2

Wenn eine nicht-scoped Aufzählung ein Klassenmitglied ist, können ihre Aufzählungswerte mit den Member-Zugriffsoperatoren . und -> zugegriffen werden.

struct X
{
    enum direction { left = 'l', right = 'r' };
};
X x;
X* p = &x;
 
int a = X::direction::left; // allowed only in C++11 and later
int b = X::left;
int c = x.left;
int d = p->left;

In den Deklarationsspezifizierern einer Mitgliedsdeklaration wird die Sequenz

enum enum-head-name :

immer als Teil einer Aufzählungsdeklaration interpretiert.

struct S
{
    enum E1 : int {};
    enum E1 : int {}; // error: redeclaration of enumeration,
                      // NOT parsed as a zero-length bit-field of type enum E1
};
 
enum E2 { e1 };
 
void f()
{
    false ? new enum E2 : int(); // OK: 'int' is NOT parsed as the underlying type
}
(seit C++11)

[bearbeiten] Aufzählungsname für Linkage-Zwecke

Eine unbenannte Aufzählung, die keinen typedef-Namen für Linkage-Zwecke hat und einen Aufzählungswert besitzt, wird für Linkage-Zwecke durch ihren zugrundeliegenden Typ und ihren ersten Aufzählungswert bezeichnet; eine solche Aufzählung hat einen Aufzählungswert als Namen für Linkage-Zwecke.

[bearbeiten] Scoped Aufzählungen

enum struct|class name { enumerator = constant-expression , enumerator = constant-expression , ... } (1)
enum struct|class name : type { enumerator = constant-expression , enumerator = constant-expression , ... } (2)
enum struct|class name ; (3)
enum struct|class name : type ; (4)
1) Deklariert einen scoped Aufzählungstyp, dessen zugrundeliegender Typ int ist (die Schlüsselwörter class und struct sind exakt äquivalent)
2) Deklariert einen scoped Aufzählungstyp, dessen zugrundeliegender Typ type ist.
3) Opaque enum declaration für eine scoped Aufzählung, deren zugrundeliegender Typ int ist.
4) Opaque enum declaration für eine scoped Aufzählung, deren zugrundeliegender Typ type ist.

Jeder enumerator wird zu einer benannten Konstanten des Aufzählungstyps (d. h. name), die sich im Geltungsbereich der Aufzählung befindet und mit dem Scope-Auflösungsoperator zugegriffen werden kann. Es gibt keine impliziten Konvertierungen von den Werten eines scoped Aufzählungswerts in ganzzahlige Typen, obwohl static_cast verwendet werden kann, um den numerischen Wert des Aufzählungswerts zu erhalten.

#include <iostream>
 
int main()
{
    enum class Color { red, green = 20, blue };
    Color r = Color::blue;
 
    switch(r)
    {
        case Color::red  : std::cout << "red\n";   break;
        case Color::green: std::cout << "green\n"; break;
        case Color::blue : std::cout << "blue\n";  break;
    }
 
    // int n = r; // error: no implicit conversion from scoped enum to int
    int n = static_cast<int>(r); // OK, n = 21
    std::cout << n << '\n'; // prints 21
}
(seit C++11)

Eine Aufzählung kann ohne Cast aus einer ganzen Zahl initialisiert werden, indem List-Initialisierung verwendet wird, wenn alle folgenden Bedingungen erfüllt sind:

  • Die Initialisierung ist eine direkte Listeninitialisierung.
  • Die Initialisierungsliste enthält nur ein einziges Element.
  • Die Aufzählung ist entweder scoped oder nicht-scoped mit festem zugrundeliegendem Typ.
  • Die Konvertierung ist nicht-verengend.

Dies ermöglicht die Einführung neuer ganzzahliger Typen (z. B. SafeInt), die die gleichen bestehenden Aufrufkonventionen wie ihre zugrundeliegenden ganzzahligen Typen genießen, selbst auf ABIs, die die Übergabe/Rückgabe von Strukturen per Wert bestrafen.

enum byte : unsigned char {}; // byte is a new integer type; see also std::byte (C++17)
byte b{42};        // OK as of C++17 (direct-list-initialization)
byte c = {42};     // error
byte d = byte{42}; // OK as of C++17; same value as b
byte e{-1};        // error
 
struct A { byte b; };
A a1 = {{42}};     // error (copy-list-initialization of a constructor parameter)
A a2 = {byte{42}}; // OK as of C++17
 
void f(byte);
f({42}); // error (copy-list-initialization of a function parameter)
 
enum class Handle : std::uint32_t { Invalid = 0 };
Handle h{42}; // OK as of C++17
(seit C++17)


using enum Deklaration

using enum using-enum-declarator ; (seit C++20)
Deklarator - ein (möglicherweise qualifizierter) Bezeichner oder einfache Template-Bezeichner


declarator muss einen nicht-abhängigen Aufzählungstyp benennen. Die Aufzählungsdeklarationen werden durch typbasierte gewöhnliche qualifizierte oder unqualifizierte Suche gefunden, je nachdem, ob declarator qualifiziert ist.

enum E { x };
 
void f()
{
    int E;
    using enum E; // OK
}
 
using F = E;
using enum F; // OK
 
template<class T>
using EE = T;
 
void g()
{
    using enum EE<E>; // OK
}

Eine using enum Deklaration führt die Aufzählungswerte des benannten Aufzählungstyps ein, als ob durch eine using Deklaration für jeden Aufzählungswert. Wenn sie im Klassenbereich (class scope) vorkommt, fügt eine using enum Deklaration die Aufzählungswerte der benannten Aufzählung als Mitglieder zum Bereich hinzu und macht sie für die Mitgliedssuche zugänglich.

enum class fruit { orange, apple };
 
struct S
{
    using enum fruit; // OK: introduces orange and apple into S
};
 
void f()
{
    S s;
    s.orange;  // OK: names fruit::orange
    S::orange; // OK: names fruit::orange
}

Zwei using enum Deklarationen, die zwei Aufzählungswerte mit demselben Namen einführen, kollidieren.

enum class fruit { orange, apple };
enum class color { red, orange };
 
void f()
{
    using enum fruit;    // OK
    // using enum color; // error: color::orange and fruit::orange conflict
}
(seit C++20)

[bearbeiten] Hinweise

Werte eines nicht-scoped Aufzählungstyps können hochgestuft oder in ganzzahlige Typen konvertiert werden.

enum color { red, yellow, green = 20, blue };
color col = red;
int n = blue; // n == 21

Werte von ganzzahligen, Gleitkomma- und Aufzählungstypen können durch Verwendung von static_cast in jeden Aufzählungstyp konvertiert werden. Beachten Sie, dass der Wert nach einer solchen Konvertierung nicht notwendigerweise einem der benannten Aufzählungswerte entsprechen muss, die für die Aufzählung definiert wurden.

enum access_t { read = 1, write = 2, exec = 4 }; // enumerators: 1, 2, 4 range: 0..7
access_t rwe = static_cast<access_t>(7);
assert((rwe & read) && (rwe & write) && (rwe & exec));
 
access_t x = static_cast<access_t>(8.0); // undefined behavior since CWG 1766
access_t y = static_cast<access_t>(8);   // undefined behavior since CWG 1766
 
enum foo { a = 0, b = UINT_MAX }; // range: [0, UINT_MAX]
foo x = foo(-1); // undefined behavior since CWG 1766,
                 // even if foo's underlying type is unsigned int
Feature-Testmakro Wert Std Feature
__cpp_enumerator_attributes 201411L (C++17) Attribute für Aufzählungswerte
__cpp_using_enum 201907L (C++20) using enum

[bearbeiten] Schlüsselwörter

enum, struct, class, using

[bearbeiten] Beispiel

#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();
}

Mögliche Ausgabe

col = red
a = l
f = 3
C++20 `using enum`: __cpp_using_enum == 201907; x

[bearbeiten] Fehlerberichte

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 377 C++98 das Verhalten war nicht spezifiziert, wenn kein ganzzahliger
Typ alle Aufzählungswerte darstellen kann
ist die Aufzählung fehler-
formt in diesem Fall
CWG 518 C++98 ein nachfolgendes Komma war nach der Aufzählungswerte-Liste nicht erlaubt erlaubt
CWG 1514 C++11 eine Neudefinition einer Aufzählung mit festem zugrundeliegendem Typ
konnte als Bitfeld in einer Klassenmitgliedsdeklaration interpretiert werden
wird immer als Neudefinition interpretiert
CWG 1638 C++11 Grammatik der opaken Aufzählungsdeklaration
verbotene Verwendung für Templatespezialisierungen
nested-name-specifier
erlaubt
CWG 1766 C++98 das Umwandeln eines Werts außerhalb des gültigen Bereichs in eine Aufzählung
ohne festen zugrundeliegenden Typ hatte ein nicht spezifiziertes Ergebnis
das Verhalten ist undefiniert
CWG 1966 C++11 die Auflösung des CWG-Problems 1514 machte den :
eines bedingten Ausdrucks Teil von enum-base
wenden Sie die Auflösung nur auf
Mitgliedsdeklarationsspezifizierer an
CWG 2156 C++11 Aufzählungsdefinitionen konnten
Aufzählungstypen durch using-Deklarationen definieren
verboten
CWG 2157 C++11 die Auflösung des CWG-Problems 1966 hat
qualifizierte Aufzählungsnamen nicht abgedeckt
abgedeckt
CWG 2530 C++98 eine Aufzählungswerte-Liste konnte mehrere
Aufzählungswerte mit demselben Bezeichner enthalten
verboten
CWG 2590 C++98 die Größe, Wertdarstellung und Ausrichtungsvoraussetzungen
einer Aufzählung hingen nicht von ihrem zugrundeliegenden Typ ab
alle von ihnen sind identisch mit
denen des zugrundeliegenden Typs
CWG 2621 C++20 die Namenssuche für Aufzählungen, die in
using enum Deklarationen verwendet wird, war unklar
wurde klargestellt
CWG 2877 C++20 die Namenssuche für Aufzählungen, die in
using enum Deklarationen waren nicht nur typbasiert
wurde typbasiert gemacht

[bearbeiten] Referenzen

  • C++23 Standard (ISO/IEC 14882:2024)
  • 9.7.1 Enumeration declarations [dcl.enum]
  • C++20 Standard (ISO/IEC 14882:2020)
  • 9.7.1 Enumeration declarations [dcl.enum]
  • C++17 Standard (ISO/IEC 14882:2017)
  • 10.2 Enumeration declarations [dcl.enum]
  • C++14 Standard (ISO/IEC 14882:2014)
  • 7.2 Enumeration declarations [dcl.enum]
  • C++11 Standard (ISO/IEC 14882:2011)
  • 7.2 Enumeration declarations [dcl.enum]
  • C++03-Standard (ISO/IEC 14882:2003)
  • 7.2 Enumeration declarations [dcl.enum]
  • C++98 Standard (ISO/IEC 14882:1998)
  • 7.2 Enumeration declarations [dcl.enum]

[bearbeiten] Siehe auch

(C++11)
prüft, ob ein Typ ein Aufzählungstyp ist
(Klassenvorlage) [bearbeiten]
prüft, ob ein Typ ein namensgebender Aufzählungstyp ist
(Klassenvorlage) [bearbeiten]
erhält den zugrundeliegenden ganzzahligen Typ für einen gegebenen Aufzählungstyp
(Klassenvorlage) [bearbeiten]
konvertiert eine Aufzählung in ihren zugrundeliegenden Typ
(Funktionsvorlage) [edit]
C-Dokumentation für Aufzählungen