Перечисления и бинарные или операторы (MISRA C++ 2008, 4-5-2)

MISRA C++ 2008, 4-5-2 гласит: выражения с типом enum не должны использоваться в качестве операндов для встроенных операторов, кроме оператора нижнего индекса [ ], оператора присваивания =, операторов равенства == и !=, унарный оператор & и операторы отношения ‹, ‹=, ›, ›=.

Если можно использовать и почему нельзя использовать бинарный | с перечислениями?


person Community    schedule 15.06.2020    source источник
comment
Почему вы хотите делать операнды в перечислении? Если вам нужно полагаться на базовые значения, вам не следует использовать перечисление. Используйте константу или #define.   -  person Andrew    schedule 19.06.2020


Ответы (2)


Как указано в другом ответе, вы смешиваете binary & с unary &.

Причина, по которой вы не можете использовать бинарный | и другие побитовые операторы в перечислениях заключается в том, что перечисляемые типы (переменные типа перечисления) имеют размер и подпись, определяемые реализацией. А константы перечисления (значения в списке перечисления) всегда имеют тип signed int.

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

MISRA также запретила обычную арифметику по той же причине: не выполняйте арифметику с типом, размер и знак которого вам неизвестен. Не так вероятно, чтобы вызвать ошибки, но я думаю, что есть место для этого, если вы делаете странные вещи, такие как enum { X=30000 }; ... X + X. Это четко определено, или неявное повышение до int, или не определено из-за целочисленного переполнения? Это может быть любой из этих случаев, и это не обязательно связано с размером данных ЦП.

person Lundin    schedule 15.06.2020
comment
Константы перечисления (значения в списке перечисления) всегда имеют тип со знаком int. Но так ли это? - person Asteroids With Wings; 15.06.2020
comment
@AsteroidsWithWings Я думаю, что это С++ 11 7.2/5 Каждое перечисление определяет тип, отличный от всех других типов. Каждое перечисление также имеет базовый тип. Базовый тип может быть явно указан с помощью enum-base; если не указано явно, базовым типом перечисления с областью действия является int. В C11 это 6.7.2.2/1. Идентификаторы в списке перечислителей объявляются как константы, которые имеют тип int и могут появляться везде, где это разрешено. - person Lundin; 15.06.2020
comment
перечисления с областью действия Существуют и другие перечисления; плюс eel.is/c++draft/dcl.enum#5 не ограничивает типы самих значений (ни, в конечном счете, базового типа) - person Asteroids With Wings; 15.06.2020
comment
@AsteroidsWithWings На самом деле С++ 03 говорит что-то другое, и это актуальная версия для MISRA-C++. - person Lundin; 15.06.2020
comment
Это, конечно, не говорит о перечислениях с областью видимости;) - person Asteroids With Wings; 15.06.2020
comment
Спасибо! Если я перегружу бинарные операторы & и | где я конвертирую перечисления в int, а затем выполняю над ними двоичные операции, должны ли они быть исключены? - person ; 16.06.2020
comment
@ user28458 Необычная перегрузка операторов вызывает большие сомнения в системах с требованиями MISRA, поэтому, вероятно, нет. Я не очень хорошо знаю MISRA-C++, вам нужно поискать другие правила относительно того, какие операторы вам разрешено перегружать, если таковые имеются. - person Lundin; 16.06.2020

Вы проводите ложное сравнение.

Унарный & является оператором "адреса" и не имеет отношения к бинарному оператору & "и".

Правила MISRA запретили все побитовые операции над перечислениями, но по-прежнему разрешают получение адреса объекта такого типа.

person Asteroids With Wings    schedule 15.06.2020