2015-07-06 2 views
2

Это тесно связано с Are C++ enums signed or unsigned?. Согласно ответу JavaMan, enum не является ни signed, ни unsigned. Но он соответствует целым правилам продвижения.Как переопределить интегральное правило для перечисления?

Я работаю с библиотекой, которая использует enums и затем передает их на другие объекты класса, которые ожидают в основном unsigned типов (как unsigned int и size_t). Включение предупреждения -Wsign-conversion в попытке поймать законные ошибки вызывает количество ложных срабатываний из-за правил языка.

Тип правила создает ситуацию, когда ее трудно обеспечить безопасность типа и уловить распространенные ошибки. Это сложно, потому что я хочу избегать таких вещей, как static_cast.

Есть ли способ переопределить поведение по умолчанию для продвижения enums на бетон signed или unsigned? (Аналогично тому, как вы можете указать char, подписан или без знака).


См. Также: библиотека была написана в 1990-х годах, поэтому она поддерживает множество старых компиляторов. Было бы замечательно, если бы решение касалось даже C++ 03 и, возможно, раньше.

От How to guard move constructors for C++03 and C++11?, я знаю, что на практике нет надежного способа определить, когда действуют другие варианты языка C++. Он упал на лицо во время тестирования с помощью Clang 3.5, используя -std=c++03 и -std=c++11.

+1

Можно ли использовать C++ 11, и вы можете изменить определение перечислений в этой библиотеке? – Praetorian

+0

@Praetorian - К сожалению, нет, мы не можем зависеть от C++ 11. Нам еще нужно поддерживать C++ 03 (и, возможно, раньше). С другой стороны, я могу изменить определения перечислений в библиотеке. При необходимости библиотека является [Crypto ++] Вэй Дай (http://www.cryptopp.com/). Извините, что не предоставил эту информацию раньше. – jww

ответ

1

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

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

+0

пришлось почесать голову, что приведет к «-1u», это помогло мне: http://brnz.org/hbr/?p=1433 – user2950911

+0

@ user2950911 Да, и важно, чтобы '-1u' был положительным номер. Все значения счетчика должны быть положительными, чтобы это работало, или компилятор будет вынужден выбрать 'signed long' или' signed long long', который может содержать как '-1u', так и правильные отрицательные числа. – Potatoswatter

Смежные вопросы