Досі ми переважно працювали з числами та рядками тексту (англ. string). Щоб моделювати реальний світ, нам може знадобитися обмежена кількість значень, яких може набувати змінна. Може виникнути потреба в окремому типі з кількома різними значеннями, кожне зі своєю назвою. Наприклад, на фабриці скейтбордів матеріал дека обирають лише з-поміж клену, бамбуку або пластику.
Ці значення можна закодувати цілими числами, але довелося б писати додатковий код, щоб перевіряти, чи не надходить із системи недопустиме значення для матеріалу.
Сенс цих магічних чисел важко простежити за вихідним кодом, і їх легко переплутати.
А enumerations дають змогу писати виразніший код і обмежувати ненавмисні помилки під час порівняння.
Конкретний термін для такого різновиду перелічень - scoped enumeration.
Наведений нижче фрагмент показує, як записати enumeration із назвою DeckMaterial.
Звернімо увагу на ключове слово enum class і на ; у кінці визначення:
enum class DeckMaterial {
maple,
bamboo,
plastic
};
Тепер розгляньмо функцію ціноутворення в крамниці скейтбордів і звернімо увагу на оператор розвʼязання області видимості (::), який указує enumerator з enumeration:
double deck_price(double base_price, DeckMaterial material) {
if(material == DeckMaterial::plastic) {
return base_price * 0.9;
}
return base_price * 1.3;
}
Уявімо, що в нас є друге enumeration для матеріалу коліс:
enum class WheelMaterial {
steel,
clay,
plastic
};
Хоча і колеса, і дека можуть бути з plastic, їх неможливо переплутати.
Це різні типи: пластик DeckMaterial і пластик WheelMaterial.
Кожне enumeration матиме свої enumerators у власній області видимості, у власному namespace.
Саме тому їх називають scoped enumerations.
Можна подумати, що коли є назва scoped, то мають бути й unscoped перелічення, і це справді так.
Unscoped enumerations втрачають популярність, бо всі вони спільно використовують той самий глобальний простір імен.
Через це не можна мати два unscoped enumerations з однаковими enumerators, як-от plastic у прикладі вище.
Крім того, unscoped enumerations неявно перетворюються на цілі числа.
Погляньмо на приклад нижче, який дає несподіваний результат:
enum CitrusFruits {
lemons, // 0
oranges, //1
};
enum IceCream {
walnut, // 0
apples, // 1
};
bool comparison{apples == oranges};
// => true
// Example from above:
bool comparison{DeckMaterial::plastic == WheelMaterial::plastic};
// => Does not compile!
Щоб перетворити scoped enumerations на цілі числа, можна скористатися static_cast<int>.