Определение размера перечисления

Хотя каждое перечисление определяет уникальный тип, оно представляется одним из встроенных целочисленных типов. По новому стандарту можно указать, что следует использовать тип, заданный за именем перечисления и двоеточием:

enum intValues : unsigned long long {

 charTyp = 255, shortTyp = 65535, intTyp = 65535,

 longTyp = 4294967295UL,

 long_longTyp = 18446744073709551615ULL

};

Если базовый тип не задан, то по умолчанию перечисления с ограниченной областью видимости имеют базовый тип int. Для перечислений с не ограниченной областью видимости типа по умолчанию нет; известно только то, что базовый тип достаточно велик для содержания значения перечислителя. Когда базовый тип определяется (включая неявное определение для перечисления с ограниченной областью видимости), попытка создания перечислителя, значение которого превосходит заданный тип, приведет к ошибке.

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

Предварительные объявления для перечислений

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

// предварительное объявление перечисления с не ограниченной областью

// видимости intValues

enum intValues : unsigned long long; // перечисление с не ограниченной

                           // областью видимости должно определять тип

enum class open_modes; // перечисление с ограниченной областью

          // видимости может использовать по умолчанию тип int

Поскольку для перечисления с не ограниченной областью видимости нет размера по умолчанию, каждое объявление должно включить его размер. Перечисление с ограниченной областью видимости можно объявить, не определяя размер, тогда размер неявно определяется как int.

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

// ошибка: в объявлении и определении должно совпадать, ограничена ли

// область видимости перечисления

enum class intValues;

enum intValues; // ошибка: intValues ранее объявлено как перечисление с

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

enum intValues : long; // ошибка: intValues ранее объявлено как int

Соответствие параметров и перечисления

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

// перечисление с не ограниченной областью видимости;

// базовый тип зависит от машины

enum Tokens {INLINE = 128, VIRTUAL = 129};

void ff(Tokens);

void ff(int);

int main() {

 Tokens curTok = INLINE;

 ff(128);    // точно соответствует ff(int)

 ff(INLINE); // точно соответствует ff(Tokens)

 ff(curTok); // точно соответствует ff(Tokens)

 return 0;

}

Хоть и нельзя передать целочисленное значение параметру перечислимого типа, вполне можно передать объект или перечислитель перечисления с неограниченной областью видимости параметру целочисленного типа. При этом значение перечислителя преобразуется в тип int или больший целочисленный тип. Фактический тип преобразования зависит от базового типа перечисления:

void newf(unsigned char);

void newf(int);

unsigned char uc = VIRTUAL;

newf(VIRTUAL); // вызов newf(int)

Перейти на страницу:

Похожие книги