[enum] (original) (raw)

9.8.1 Enumeration declarations [dcl.enum]

An enumeration is a distinct type ([basic.compound]) with named constants.

Its name becomes an enum-name within its scope.

enum-key:
enum
enum class
enum struct

The optional attribute-specifier-seq in the enum-head and the opaque-enum-declaration appertains to the enumeration; the attributes in that attribute-specifier-seq are thereafter considered attributes of the enumeration whenever it is named.

[Note 1:

This resolves a potential ambiguity between the declaration of an enumeration with an enum-base and the declaration of an unnamed bit-field of enumeration type.

[Example 1: struct S { enum E : int {};enum E : int {}; }; — _end example_]

— _end note_]

The identifier in an enum-head-nameis not looked up and is introduced by the enum-specifier or opaque-enum-declaration.

The enumeration type declared with an enum-keyof only enum is an unscoped enumeration, and its enumerators are unscoped enumerators.

The enum-keys enum class andenum struct are semantically equivalent; an enumeration type declared with one of these is a scoped enumeration, and its enumerators are scoped enumerators.

The optional enum-head-name shall not be omitted in the declaration of a scoped enumeration.

The type-specifier-seq of an enum-baseshall name an integral type; any cv-qualification is ignored.

An opaque-enum-declaration declaring an unscoped enumeration shall not omit the enum-base.

The identifiers in an enumerator-list are declared as constants, and can appear wherever constants are required.

The same identifier shall not appear as the name of multiple enumerators in an enumerator-list.

An enumerator-definition without = gives the associatedenumerator the value zero if it is the first enumerator-definition, and the value of the previous enumeratorincreased by one otherwise.

[Example 2:

enum { a, b, c=0 };enum { d, e, f=e+2 };defines a, c, and d to be zero, b ande to be 1, and f to be 3.

— _end example_]

An opaque-enum-declaration is either a redeclaration of an enumeration in the current scope or a declaration of a new enumeration.

[Note 2:

An enumeration declared by anopaque-enum-declaration has a fixed underlying type and is a complete type.

The list of enumerators can be provided in a later redeclaration with an enum-specifier.

— _end note_]

A scoped enumeration shall not be later redeclared as unscoped or with a different underlying type.

An unscoped enumeration shall not be later redeclared as scoped and each redeclaration shall include an enum-base specifying the same underlying type as in the original declaration.

If an enum-head-name contains anested-name-specifier, the enclosing enum-specifieror opaque-enum-declaration Dshall not inhabit a class scope and shall correspond to one or more declarations nominable in the class, class template, or namespace to which the nested-name-specifier refers ([basic.scope.scope]).

All those declarations shall have the same target scope; the target scope of D is that scope.

Each enumeration defines a type that is different from all other types.

Each enumeration also has an underlying type.

The underlying type can be explicitly specified using an enum-base.

For a scoped enumeration type, the underlying type is int if it is not explicitly specified.

In both of these cases, the underlying type is said to befixed.

Following the closing brace of an enum-specifier, each enumerator has the type of its enumeration.

If the underlying type is fixed, the type of each enumerator prior to the closing brace is the underlying type and the constant-expression in the enumerator-definitionshall be aconverted constant expressionof the underlying type.

If the underlying type is not fixed, the type of each enumerator prior to the closing brace is determined as follows:

An enumeration whose underlying type is fixed is an incomplete type until immediately after itsenum-base (if any), at which point it becomes a complete type.

An enumeration whose underlying type is not fixed is an incomplete type until the closing } of itsenum-specifier, at which point it becomes a complete type.

For an enumeration whose underlying type is not fixed, the underlying type is an integral type that can represent all the enumerator values defined in the enumeration.

If no integral type can represent all the enumerator values, the enumeration is ill-formed.

It is implementation-defined which integral type is used as the underlying type except that the underlying type shall not be larger than intunless the value of an enumerator cannot fit in an int orunsigned int.

If the enumerator-list is empty, the underlying type is as if the enumeration had a single enumerator with value 0.

For an enumeration whose underlying type is fixed, the values of the enumeration are the values of the underlying type.

Otherwise, the values of the enumeration are the values representable by a hypothetical integer type with minimal width Msuch that all enumerators can be represented.

The width of the smallest bit-field large enough to hold all the values of the enumeration type is M.

It is possible to define an enumeration that has values not defined by any of its enumerators.

If the enumerator-list is empty, the values of the enumeration are as if the enumeration had a single enumerator with value 0.82

An enumeration has the same size, value representation, and alignment requirements ([basic.align]) as its underlying type.

Furthermore, each value of an enumeration has the same representation as the corresponding value of the underlying type.

Two enumeration types are layout-compatible enumerationsif they have the same underlying type.

The value of an enumerator or an object of an unscoped enumeration type is converted to an integer by integral promotion.

[Example 3:

enum color { red, yellow, green=20, blue }; color col = red; color* cp = &col;if (*cp == blue) makes color a type describing various colors, and then declarescol as an object of that type, and cp as a pointer to an object of that type.

The possible values of an object of typecolor are red, yellow, green,blue; these values can be converted to the integral values0, 1, 20, and 21.

Since enumerations are distinct types, objects of type color can be assigned only values of type color.

color c = 1; int i = yellow;

Note that this implicit enum to intconversion is not provided for a scoped enumeration:enum class Col { red, yellow, green };int x = Col::red; Col y = Col::red;if (y) { }

— _end example_]

The name of each unscoped enumerator is also bound in the scope that immediately contains the enum-specifier.

An unnamed enumeration that does not have a typedef name for linkage purposes ([dcl.typedef]) and that has a first enumerator is denoted, for linkage purposes ([basic.link]), by its underlying type and its first enumerator; such an enumeration is said to have an enumerator as a name for linkage purposes.

[Note 3:

Each unnamed enumeration with no enumerators is a distinct type.

— _end note_]

[Example 4: enum direction { left='l', right='r' };void g() { direction d; d = left; d = direction::right; } enum class altitude { high='h', low='l' };void h() { altitude a; a = high; a = altitude::low; } — _end example_]

9.8.2 The using enum declaration [enum.udecl]

The using-enum-declaratorshall designate a non-dependent type with a reachable enum-specifier.

[Example 1: enum E { x };void f() { int E;using enum E; } using F = E;using enum F; template<class T> using EE = T;void g() { using enum EE<E>; } — _end example_]

[Note 1:

A using-enum-declaration in class scope makes the enumerators of the named enumeration available via member lookup.

[Example 2: enum class fruit { orange, apple };struct S { using enum fruit; };void f() { S s; s.orange; S::orange; } — _end example_]

— _end note_]

[Note 2:

Two using-enum-declaration_s_that introduce two enumerators of the same name conflict.

[Example 3: enum class fruit { orange, apple };enum class color { red, orange };void f() { using enum fruit; using enum color; } — _end example_]

— _end note_]