У меня есть класс enum, который я использую для маскировки битов, например (в Unreal Engine, поэтому тип uint8)
enum class Level : uint8
{
None = 0x0,
Debug = 0x1,
Info = 0x2,
Warning = 0x4,
...
}
Я добавил встроенные операторы для |
, &
и ^
, так что я могу использовать элемент в качестве фактической битовой маски (например, mask = Level::Warning | Level::Debug
), например:
inline Level operator&(const Level& lhs, const Level& rhs)
{
return (Level)((uint8)lhs & (uint8)rhs);
}
Теперь в какой-то момент я хочу запросить, установлен ли бит или нет. Однако это не работает без приведения к uint8
:
if(mask & Level::Debug) //does not work, C2451
if((uint8)(mask & Level::Debug)) //does work
Есть ли способ заставить запрос работать без необходимости приведения его к базовому типу?
РЕДАКТИРОВАТЬ: цель состоит в том, чтобы код вызова был как можно короче (и читабельнее). Значение &
в этом случае кажется таким же ясным, как использование вызова, такого как дополнительный метод any
как предложено в аналогичном вопросе. Добавление кода == Level::Debug
, конечно, тоже работает, но не сокращает используемый код. Изменение типа возвращаемого значения оператора работает, но в основном проблема смещается к присваиванию типа Level myLevel = Level::Debug | Level::Warning
, поэтому я бы не стал улучшать свой код в целом.
Level myLevel = Level::Debug | Level::Warning
больше не работает. Тогда мне придется решить, от кого из этих двух я больше склонен отказаться, я полагаю? - person Tare   schedule 15.02.2021static_cast
, где это возможно: gcc.godbolt.org/z/qvhq9W - person Simon Kraemer   schedule 15.02.2021(mask & Level::Debug) == Level::Debug
. - person Jarod42   schedule 15.02.2021static_cast
вместо приведения в стиле C. Если вы знаете, что делаете, это не имеет значения, но это может укусить вас за **, если вы не будете осторожны. Кроме того, даже если вы поместите свое перечисление в область: если эта область явно не ограничена вашим перечислением и только вашим перечислением, вы можете столкнуться с такими проблемами. Представьте перечисление в пространстве имен проекта или определенное внутри класса. Если вам нужно определить другое перечисление в том же классе в будущем, вам нужно либо провести рефакторинг (что может быть невозможно сохранить... - person Simon Kraemer   schedule 15.02.2021There is a reason that in legacy code enum value declaration are often prefixed with the enum type.
Причина в том, что в C не было и нет ни пространств имен, ни классов. В этом случае соглашение о префиксах имен позволяет избежать конфликтов имен. C++ решил проблему отсутствия пространств имен, введя пространства имен. - person eerorika   schedule 15.02.2021So far as I understood, plain enums should be avoided (although for lack of research I haven't yet read, why exactly)
. Я никогда не говорил, что этот вариант использования должен избегать простых перечислений. Я никогда не говорил, что простых перечислений следует избегать любой ценой. Я никогда не говорил, что конфликт имен был единственной проблемой с простыми перечислениями. Я дал общее объяснение, основанное на двух наиболее ярких примерах того, почему вообще следует избегать простых перечислений. - person Simon Kraemer   schedule 15.02.2021I answered to OP's statement
И я расширил ваш ответ на это утверждение, чтобы объяснить, почему данная причина избегать перечислений не является причиной избегать перечислений в целом. Это причина избегать перечислений в глобальном (или иным образом переполненном) пространстве имен. - person eerorika   schedule 15.02.2021