Как переопределить интегральное правило продвижения для enum?

Это тесно связано с Перечисления 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,

2

Решение

Базовый тип перечисления 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

2

Другие решения

Вы можете свернуть свой собственный 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.

1

По вопросам рекламы [email protected]