Читать «Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14» онлайн - страница 52

Скотт Мейерс

enum Color {black, white, red}; // black, white, red находятся

                                // в той же области видимости,

                                // что и Color

auto white = false;             // Ошибка! white уже объяв-

                                // лено в этой области видимости

Тот факт, что эти имена перечисления “вытекают” в область видимости, содержащую определение их enum, приводит к официальному термину для данной разновидности перечислений: без области видимости (unscoped). Их новый аналог в С++11, перечисления с областью видимости (scoped enum), не допускает такой утечки имен:

enum class Color

 { black, white, red }; // black, white, red принадлежат

                        // области видимости Color

auto white = false;     // OK, других white нет

Color с = white;        // Ошибка! Нет имени перечисления

                        // "white" в этой области видимости

Color с = Color::white; // OK

auto с = Color::white;  // OK (и соответствует совету

                        // из раздела 2.1)

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

Снижение загрязнения пространства имен, обеспечиваемое применением перечислений с областью видимости, само по себе является достаточной причиной для предпочтения таких перечислений их аналогам без областей видимости. Однако перечисления с областью видимости имеют и второе убедительное преимущество: они существенно строже типизированы. Значения в перечислениях без областей видимости неявно преобразуются в целочисленные типы (а оттуда — в типы с плавающей точкой). Поэтому вполне законными оказываются такие семантические карикатуры:

enum Color {black, white, red}; // Перечисление без

                                // области видимости

std::vector<std::size_t>        // Функция, возвращающая

primeFactors(std::size_t x);    // простые делители x

Color с = red;

if (с < 14.5) {                 // Сравнение Color и double (!)

 auto factors =                 // Вычисление простых делителей

  primeFactors(c);              // значения Color (!)

}

Добавление простого ключевого слова class после enum преобразует перечисление без области видимости в перечисление с областью видимости, и это — совсем другая история. Не имеется никаких неявных преобразований элементов перечисления с областью видимости в любой другой тип:

enum class Color      // Перечисление с областью видимости

 {black, white, red};

Color с = Color::red; // Как и ранее, но с квалификатором

                      // области видимости

if (с < 14.5) {       // Ошибка! Нельзя сравнивать

                      // Color и double

 auto factors =       // Ошибка! Нельзя передавать Color в