Я хочу полностью понять, как компилятор C++ работает с enum, превышающим максимально возможное число, то есть содержащим -1 и UINT64_MAX одновременно, т.е.
enum A {
X = -1,
Y = UINT64_MAX
};
Сначала я подумал, что компилятор не примет этот код. На самом деле он не компилируется, когда enum заменяется enum class, но приведенный выше пример компилируется. Согласно стандарту мы имеем для базового типа:
Объявляет тип перечисления с незаданной областью, базовый тип которого не является фиксированным (в этом случае базовый тип является целочисленным типом, определяемым реализацией, который может представлять все значения перечислителя; этот тип не больше int, если значение перечислителя не может поместиться в int или unsigned int. Если список-перечислитель пуст, базовый тип такой, как если бы перечисление имело единственный перечислитель со значением 0). (https://en.cppreference.com/w/cpp/language/enum)
Но что это значит для моего примера?
Я написал небольшую примерную программу, чтобы узнать, что происходит:
#include <iostream>
#include <cstdint>
enum A {
X = -1,
XX = -1,
Y = UINT64_MAX
};
int main()
{
std::cout << "X unsigned: " << (uint64_t)(X) << ", signed: " << (int64_t)(X) << std::endl;
std::cout << "Y unsigned: " << (uint64_t)(Y) << ", signed: " << (int64_t)(Y) << std::endl;
std::cout << "(X == XX) == " << (X == XX) << std::endl;
std::cout << "(X == Y) == " << (X == Y) << std::endl;
}
Выход:
X unsigned: 18446744073709551615, signed: -1
Y unsigned: 18446744073709551615, signed: -1
(X == XX) == 1
(X == Y) == 0
Теперь я в замешательстве. Очевидно, X и Y представляют одно и то же число, но они все еще различимы, т.е. Сравнение X == Y неверно (но X=XX на самом деле верно). Что здесь происходит?
Я знаю, что лучше использовать не старый enum, а новый enum class. Но все-таки enum широко используется, и я хочу понять, что здесь происходит.