如何在不转换为基础类型的情况下查询用作位掩码的枚举 class 的有效性
How to query validity of enum class used as bit mask without casting to underlying type
我有一个枚举 class 用于位掩码,就像这样(在 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
方法 as suggested in a similar question 之类的调用一样清楚。添加 == Level::Debug
代码当然也可以,但不会缩短使用的代码。更改运算符的 return 类型有效,但基本上将问题转移到 Level myLevel = Level::Debug | Level::Warning
之类的赋值,所以我不会整体改进我的代码 imo。
您需要 operator bool - 但只能为 class 类型定义 operator bool。所以 - 定义 class - 并将你的枚举放入其中,如下所示:
class Level
{
public:
enum Value : std::uint8_t
{
None = 0x0,
Debug = 0x1,
Info = 0x2,
Warning = 0x4,
Error = 0x8
};
constexpr Level(Value value) noexcept : value(value) {}
friend constexpr bool operator == (Level lhs, Level rhs)
{ return lhs.value == rhs.value; }
friend constexpr bool operator != (Level lhs, Level rhs)
{ return lhs.value != rhs.value; }
friend constexpr Level operator & (Value lhs, Value rhs)
{
return Value(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
}
friend constexpr Level operator & (Level lhs, Level rhs)
{
return lhs.value & rhs.value;
}
constexpr explicit operator bool() const noexcept { return value != Value::None; }
private:
Value value;
};
工作demo。
这样使用:
int main() {
Level l = Level::None;
if (l & Level::Info) return -1;
}
我有一个枚举 class 用于位掩码,就像这样(在 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
方法 as suggested in a similar question 之类的调用一样清楚。添加 == Level::Debug
代码当然也可以,但不会缩短使用的代码。更改运算符的 return 类型有效,但基本上将问题转移到 Level myLevel = Level::Debug | Level::Warning
之类的赋值,所以我不会整体改进我的代码 imo。
您需要 operator bool - 但只能为 class 类型定义 operator bool。所以 - 定义 class - 并将你的枚举放入其中,如下所示:
class Level
{
public:
enum Value : std::uint8_t
{
None = 0x0,
Debug = 0x1,
Info = 0x2,
Warning = 0x4,
Error = 0x8
};
constexpr Level(Value value) noexcept : value(value) {}
friend constexpr bool operator == (Level lhs, Level rhs)
{ return lhs.value == rhs.value; }
friend constexpr bool operator != (Level lhs, Level rhs)
{ return lhs.value != rhs.value; }
friend constexpr Level operator & (Value lhs, Value rhs)
{
return Value(static_cast<uint8_t>(lhs) & static_cast<uint8_t>(rhs));
}
friend constexpr Level operator & (Level lhs, Level rhs)
{
return lhs.value & rhs.value;
}
constexpr explicit operator bool() const noexcept { return value != Value::None; }
private:
Value value;
};
工作demo。
这样使用:
int main() {
Level l = Level::None;
if (l & Level::Info) return -1;
}