Может ли sizeof (enum) отличаться от sizeof (std :: under_type <Enum> :: type)?

16

Недавно появился обзор кода, который в следующем примере:

enum class A : uint8_t
{
    VAL1, VAL2 
};

...
std::vector<A> vOfA; // Assume this is sized and full of some stuff.
std::memcpy(wire_buffer, vOfA.data(), vOfA.size() * sizeof(A));

Мы должны использовать sizeof(std::underlying_type<A>::type)вместо sizeof(A). Возможно ли, что они могут отличаться? У кого-то есть стандартная цитата, которая гарантирует это?

Фантастический мистер Фокс
источник
Каков размер данных перечисления в C ++? (что должно быть сделано так, чтобы охватить и те, которые ограничены :-).
Желудь
3
Даже если они одного размера (что более чем вероятно), какой аргумент против использования sizeof(A)? Кроме того: если они имеют другой размер (маловероятно), использование sizeof(std::underlying_type<A>)будет просто неправильно.
Сандер Де
1
sizeof(std::underlying_type<A>)это наверное 1. Вы имели в виду ::type?
LF
1
@SanderDeDycker Да, когда имеешь дело с As, определенно хочется использовать, sizeof(A)и коду не должно быть никакого значения, что это за тип A.
Желудь
@LF Да, опечатка. Название было правильно.
Фантастический мистер Фокс

Ответы:

12

В C ++ 03 это было гарантировано (ну, для перечислений с незаданной областью в любом случае).

[dcl.enum] Объявления перечисления (выделено мое)

6 Базовый тип перечисления является целочисленным типом, который может представлять все значения перечислителя, определенные в перечислении. Если ни один целочисленный тип не может представлять все значения перечислителя, перечисление неверно сформировано. Это определяется реализацией, какой целочисленный тип используется в качестве базового типа для перечисления, за исключением того, что базовый тип не должен быть больше, чем int, если значение перечислителя не может поместиться в int или unsigned int. Если список перечислителя пуст, базовый тип выглядит так, как если бы перечисление имело один перечислитель со значением 0. Значение, sizeof()примененное к типу перечисления, объекту типа перечисления или перечислителю, является значением, sizeof()примененным к базовый тип .

Затем появился n2347 , документ, который был принят для строго типизированных перечислений ( enum class) и других улучшений перечислений с незаданной областью, и в нем было удалено предложение, выделенное жирным шрифтом. Интересно, что более ранняя версия предложения, n2213 , заменяла удаленное предложение. Но это не вошло в версию, которая была принята.

Таким образом, в современном C ++ нет необходимости, чтобы размеры были одинаковыми. Хотя с практической точки зрения реализации вряд ли изменили поведение, предписанное C ++ 03 для размеров перечисления.

Можно было бы считать это недостатком стандарта.

Рассказчик - Unslander Monica
источник
2
Как можно гарантировать что-то в C ++ 03 для функции, которой нет в языке? oO
Гонки
4
@LightnessRaceswithMonica - понятие базового типа не является новым. Просто C ++ 11 позволил вам указать это самостоятельно.
StoryTeller - Unslander Моника
Я знаю это. Понятие enum ( enum class) с областью видимости ( ) является новым.
Гонки
@LightnessRaceswithMonica - я думаю, что здесь можно обвинить предложение. Он сделал две вещи, ввел перечисления в области и позволил всем перечислениям (не только в области) установить базовый тип. Следовательно, «гарантировано» в C ++ 03.
StoryTeller - Unslander Моника
1
@ StoryTeller-UnslanderMonica Да, вопрос такой же, я думаю, с областью или без области.
Фантастический мистер Фокс