Les classes d'énumérations ("new enums", "strong enums") permettent de résoudre trois problèmes liés aux énumérations traditionnelles du C++ :
- conventionnel
enums
convertissent implicitement en int
ce qui provoque des erreurs lorsque l'on ne veut pas qu'une énumération se comporte comme un nombre entier.
- conventionnel
enums
exportent leurs énumérateurs dans la portée environnante, ce qui entraîne des conflits de noms.
- Le type sous-jacent d'un
enum
ne peut pas être spécifié, ce qui entraîne des confusions, des problèmes de compatibilité et rend la déclaration préalable impossible.
enum class
("strong enums") sont fortement typés et cadrés :
enum Alert { green, yellow, orange, red }; // traditional enum
enum class Color { red, blue }; // scoped and strongly typed enum
// no export of enumerator names into enclosing scope
// no implicit conversion to int
enum class TrafficLight { red, yellow, green };
Alert a = 7; // error (as ever in C++)
Color c = 7; // error: no int->Color conversion
int a2 = red; // ok: Alert->int conversion
int a3 = Alert::red; // error in C++98; ok in C++11
int a4 = blue; // error: blue not in scope
int a5 = Color::blue; // error: not Color->int conversion
Color a6 = Color::blue; // ok
Comme indiqué, les enums traditionnels fonctionnent comme d'habitude, mais vous pouvez maintenant, de manière facultative, qualifier le nom de l'enum.
Les nouvelles énumérations sont des "classes d'énumérations" parce qu'elles combinent des aspects des énumérations traditionnelles (noms, valeurs) avec des aspects des classes (membres délimités et absence de conversions).
La possibilité de spécifier le type sous-jacent permet de simplifier l'interopérabilité et de garantir la taille des énumérations :
enum class Color : char { red, blue }; // compact representation
enum class TrafficLight { red, yellow, green }; // by default, the underlying type is int
enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U }; // how big is an E?
// (whatever the old rules say;
// i.e. "implementation defined")
enum EE : unsigned long { EE1 = 1, EE2 = 2, EEbig = 0xFFFFFFF0U }; // now we can be specific
Il permet également de déclarer les enums à l'avance :
enum class Color_code : char; // (forward) declaration
void foobar(Color_code* p); // use of forward declaration
// ...
enum class Color_code : char { red, yellow, green, blue }; // definition
Le type sous-jacent doit être l'un des types d'entiers signés ou non signés ; la valeur par défaut est int
.
Dans la bibliothèque standard, enum
sont utilisées :
- Cartographie des codes d'erreur spécifiques aux systèmes : En
<system_error>
: enum class errc
;
- Indicateurs de sécurité des pointeurs : En
<memory>
: enum class pointer_safety { relaxed, preferred, strict };
- Erreurs de flux d'E/S : En
<iosfwd>
: enum class io_errc { stream = 1 };
- Gestion des erreurs de communication asynchrones : En
<future>
: enum class future_errc { broken_promise, future_already_retrieved, promise_already_satisfied };
Plusieurs d'entre eux ont des opérateurs, tels que ==
définis.