Чи може розмір (enum) відрізнятися від sizeof (std :: underlying_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). Чи можливо, що вони коли-небудь можуть відрізнятися? У когось є цитата стандартів, яка це гарантує?


Пов’язання, який розмір даних типу enum в 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 або неподписаний int. Якщо список перелічувачів порожній, базовий тип є таким, як якщо б у перерахунку був один нумератор зі значенням 0. Значення, sizeof()застосоване до типу перерахування, об'єкта типу перерахування або перелічувача, є значенням, sizeof()застосованим до базовий тип .

Потім вийшов n2347 , папір, яка була прийнята для сильно набраних перерахувань ( enum class) та інших удосконалень для незаписаних перерахувань, і було вилучено речення жирним шрифтом. Цікаво, що попередня версія пропозиції, n2213 , мала заміну вилученого вироку. Але це не ввійшло у прийняту версію.

Так що в сучасному C ++ немає жодних зобов'язань щодо розмірів, які мають бути однаковими. Хоча з практичної точки зору, реалізація навряд чи змінила поведінку, прописану C ++ 03 для розмірів перерахування.

Можна вважати це дефектом стандарту.


2
Як можна щось гарантувати в C ++ 03 для функції, яка не існувала в мові? oO
Гонки легкості на орбіті

4
@LightnessRaceswithMonica - Поняття основного типу не нове. Просто C ++ 11 дозволив вам вказати це самостійно.
StoryTeller - Невідповідна Моніка

Я знаю це. Поняття про масштабний перелік ( enum class) нове.
Гонки легкості на орбіті

@LightnessRaceswithMonica - Я думаю, що тут потенційно можна помилитися з пропозицією. Це здійснило дві речі, запровадило перелік обчислень і дозволило всім перерахункам (не лише масштабним) встановити базовий тип. Звідси "гарантоване" в C ++ 03.
StoryTeller - Невідповідна Моніка

1
@ StoryTeller-UnslanderMonica Так, питання те саме, я думаю, розмахував чи не вирішив.
Фантастичний містер Фокс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.