Перечисление или перечисляемый тип - это тип данных, где любое значение (перечислитель) определяется как символьная константа.

Объявляется перечисляемый тип с помощью ключевого слова enum.

// Объявление перечисляемого типа
enum Level
{
    LEVEL_LOW,
    LEVEL_MEDIUM,
    LEVEL_HIGH
};

Level level = LEVEL_MEDIUM;    // Объявление и инициализация переменной перечисляемого типа

Все перечисления и перечислители находятся в одном пространстве имен, поэтому повторение перечислителей не допускается.

// Объявление перечисляемого типа
enum SoundLevel { LOW, MEDIUM, HIGH };
enum BrightLevel { LOW, MEDIUM, HIGH };    // Ошибка

Значения перечислителей - это целые числа, присваиваемые в зависимости от позиции перечислителя в списке значений. Присваиание начинается с нуля.

enum Level
{
    LEVEL_LOW,      // значение 0
    LEVEL_MEDIUM,   // значение 1
    LEVEL_HIGH      // значение 2
};

Можно указывать значения перечислителей самостоятельно. В этом случае любые не определенные перечислители будут иметь значения на единицу больше, чем значения предыдущих перечислителей. Указанные значения могут повторяться.

enum Color
{
    COLOR_RED = -3,
    COLOR_BLUE,       // значение -2
    COLOR_GREEN,      // значение -1
    COLOR_WHITE = 5,
    COLOR_YELLOW = 5, // значения могут повторяться
    COLOR_BLACK       // значение 6
};

При объявлении перечислимого типа можно задать тип его перечислителей (позволяются только целочисленные типы). В этом случае заданные значения перечислителей будут преобразованы в значения указанного типа.

enum Level : short
{
    LEVEL_LOW = 100,
    LEVEL_MEDIUM = 0x12345678,    // будет значение 0x5678, так как преобразуется к типу short размером 16 бит
    LEVEL_HIGH
};

Значения перечислений неявно преобразуются к целочисленном типу. Однако преобразовать число в перечислимый тип можно только явно. Также явное преобразование потребуется при присвоении значений из других перечислений.

enum Color
{
    COLOR_RED,
    COLOR_GREEN,
    COLOR_BLUE
};
int color_index = COLOR_RED;
Color color1 = 1;              // Ошибка
Color color2 = static_cast<Color>(1);

Также явное преобразование потребуется при присвоении значений из других перечислений.

enum Color { COLOR_RED, COLOR_GREEN, COLOR_BLUE };
enum Level { LEVEL_LOW, LEVEL_MEDIUM, LEVEL_HIGH };

Color color = COLOR_RED;
Level level1 = COLOR_BLUE;    // Ошибка
Level level2 = static_cast(COLOR_BLUE);

Перечисления с собственной областью видимости

У обычных перечислений есть один недостаток. Например можно сравнить значения из различных перечислений и получить истину. Это происходит из-за того, что при сравнении перечислители преобразуются к целочисленному типу.

Для исправления такого поведения, в стандарте C++11 добавили возможность задавать перечисления с собственной областью видимости. Такие перечисления задаются с помощью конструкции enum class.

enum class Color
{
    RED,
    GREEN,
    BLUE
};

Поскольку у перечислений теперь есть собственная область видимости, то позволяется использование повторяющихся перечислителей в разных перечислимых типах.

enum class PrimaryColor { RED, GREEN, BLUE };
enum class SecondaryColor { RED, GREEN, BLUE };   // нет ошибки

Обращаться к перечислителям с собственной областью видимости следует через оператор разрешения области видимости :: .

enum class Color { RED, GREEN, BLUE };
Color color = Color::RED;

Для перечислений с областью видимости неявное преобразование к целому числу не работает. Вместо этого следует использовать явное преобразование с помощью static_cast.

enum class Color
{
    RED,
    GREEN,
    BLUE
};

Color color = Color::RED;
int color_index = static_cast<int>(color);      // color_index = 0

Также с помощью static_cast можно преобразовать значение одного перечислимого типа к значению другого перечислимого типа.

enum class Color { RED, GREEN, BLUE };
enum class Level { LOW, MEDIUM, HIGH };

Color color = Color::RED;
Level level = Level::LOW;

if(color == static_cast<Color>(level))   // true
{
    return true;
}