Это тесно связано с Перечисления C ++ подписаны или не подписаны?. Согласно ответу JavaMan, enum
не является ни signed
ни unsigned
, Но он следует интегральным правилам продвижения.
Я работаю с библиотекой, которая использует enums
а затем передает их другим объектам класса, которые ожидают в основном unsigned
типы (как unsigned int
а также size_t
). Включение -Wsign-conversion
предупреждение в попытке поймать законные ошибки вызывает ряд ложных срабатываний из-за правил языка.
Правило своего рода создает ситуацию, когда сложно обеспечить безопасность типов и уловить типичные ошибки. Это сложно, потому что я хочу избежать таких вещей, как static_cast
обильно разбросаны по всему коду.
Есть ли способ переопределить поведение языка по умолчанию для продвижения enums
к бетону signed
или же unsigned
типы? (Аналогично тому, как вы можете указать char
подписан или не подписан).
В связи с этим библиотека была написана в 1990-х годах, поэтому она поддерживает ряд старых компиляторов. Было бы здорово, если бы решение было адресовано даже C ++ 03 и, возможно, раньше.
От Как охранять конструкторы перемещения для C ++ 03 и C ++ 11?, Я знаю, что на практике нет надежного способа определить, когда действуют другие варианты языка C ++. Он упал лицом вниз во время тестирования с использованием Clang 3.5 -std=c++03
а также -std=c++11
,
Базовый тип перечисления C ++ 03 зависит от диапазона значений его перечислителей, и он повышается до своего базового типа, а не int
(C ++ 98 [conv.prom] §4.5 / 2).
Грязный способ заставить перечисление вести себя как unsigned int
это добавить значение, которое только unsigned int
может справиться.
enum things {
a, b, c,
force_unsigned = -1U
};
Демо-версия: http://coliru.stacked-crooked.com/a/d3ded108fb5a68bf
Вы можете свернуть свой собственный enum class
:
struct safe_enum {
enum type {
value1, value2, value3
};
type value;
operator unsigned int ()
{ return value; }
};
safe_enum foo = safe_enum::value1;
unsigned bar = safe_enum::value2;
К сожалению, это приводит к потере «незаданного» поведения перечислений C ++ 03, поэтому этот шаблон передовой практики нарушит кодовую базу. Кроме того, меняя enum
в class
сломает ABI, если он был отправлен как DLL.