Читать «Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14» онлайн - страница 54
Скотт Мейерс
indeterminate = 0xFFFFFFFF
};
то, вероятно, придется перекомпилировать всю систему полностью, даже если только одна подсистема — возможно, одна-единственная функция! — использует это новое значение. Это одна из тех вещей, которые программисты просто enum
в С++11. Например, вот совершенно корректное объявление enum
с областью видимости, и функции, которая получает его в качестве параметра:
enum class Status; // Предварительное объявление
void continueProcessing(Status s); // и его использование
Заголовочный файл, содержащий эти объявления, не требует перекомпиляции при пересмотре определения Status
. Кроме того, если изменено перечисление Status
(например, добавлено значение audited
), но поведение continueProcessing
не изменилось (например, потому что continueProcessing
не использует значение audited
), то не требуется и перекомпиляция реализации continueProcessing
.
Но если компилятор должен знать размер enum
до использования, то как могут перечисления С++ 11 быть предварительно объявлены, в то время как перечисления С++98 этого не могут? Ответ прост: базовый тип перечислений с областью видимости всегда известен, а для перечислений без областей видимости вы можете его указать.
По умолчанию базовым типом для enum
с областью видимости является int
:
enum class Status; // Базовый тип — int
Если вас не устраивает значение по умолчанию, вы можете его перекрыть:
enum class Status: std::uint32_t; // Базовый тип для Status -
// std::uint32_t (из <cstdint>)
В любом случае компиляторы знают размер перечислителей в перечислении с областью видимости.
Чтобы указать базовый тип для перечисления без области видимости, вы делаете то же, что и для перечисления с областью видимости, и полученный результат может быть предварительно объявлен:
enum Color: std::uint8_t; // Предварительное объявление
// перечисления без области видимости;
// базовый тип - std::uint8_t
Спецификация базового типа может быть указана и в определении enum
:
enum class Status: std::uint32_t { good = 0,
failed = 1,
incomplete = 100,
corrupt = 200,
audited = 500,
indeterminate = 0xFFFFFFFF
};
С учетом того факта, что enum
с областью видимости устраняет загрязнение пространства имен и невосприимчиво к бессмысленным преобразованиям типов, вас может удивить тот факт, что имеется как минимум одна ситуация, в которой могут быть полезны перечисления без области видимости, а именно — при обращении к полям в кортежах C++11 std::tuple
. Предположим, например, что у нас есть кортеж, содержащий имя, адрес электронной почты и значение репутации пользователя на сайте социальной сети:
using UserInfo = // Псевдоним типа; см. раздел 3.3
std::tuple<std::string, // Имя