Не используйте `union` для каламбура типов
Причина
Чтение члена union с типом, отличным от типа, с которым он был записан, является неопределённым поведением. Такой каламбур незаметен или, по крайней мере, труднее обнаруживается, чем при использовании явного именованного приведения. Каламбур типов через union — источник ошибок.
Пример (плохой)
union Pun {
int x;
unsigned char c[sizeof(int)];
};
Идея Pun — получить доступ к побайтовому представлению int.
void bad(Pun& u)
{
u.x = 'x';
cout << u.c[0] << '\n'; // неопределённое поведение
}
Если нужно посмотреть байты int, используйте явное (именованное) приведение:
void if_you_must_pun(int& x)
{
auto p = reinterpret_cast<std::byte*>(&x);
cout << to_integer<unsigned>(p[0]) << '\n'; // OK; лучше
// ...
}
Доступ к результату reinterpret_cast от объявленного типа объекта к char*, unsigned char* или std::byte* является определённым поведением. (Использование reinterpret_cast не приветствуется, но хотя бы видно, что происходит что-то хитрое.)
Примечание
К сожалению, union широко применяется для каламбура типов. Аргумент «иногда это работает так, как ожидается» мы не считаем убедительным.
В современном C++ появились std::byte (C++17) и std::bit_cast (C++20) для работы с сырыми представлениями объектов. Для таких операций используйте reinterpret_cast совместно с std::byte вместо unsigned char или char.
Контроль
???
Enum: Перечисления
Перечисления используются для определения наборов целочисленных значений и типов для таких наборов. Существует два вида перечислений: «обычные» enum и enum class.
Сводка правил для перечислений:
- Enum.1: Предпочитайте перечисления макросам
- Enum.2: Используйте перечисления для представления наборов связанных именованных констант
- Enum.3: Предпочитайте
enum class«обычным»enum - Enum.4: Определяйте операции над перечислениями для безопасного и удобного использования
- Enum.5: Не используйте
ALL_CAPSдля значений перечислений - Enum.6: Избегайте безымянных перечислений
- Enum.7: Указывайте базовый тип перечисления только при необходимости
- Enum.8: Указывайте значения элементов перечисления только при необходимости