You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

enum class与enum(uint8_t)使用位运算符为何编译结果不同?

问题描述

我编写了如下代码:

enum class MouseState : uint8_t
{
    kLeft = 0x01,
    kRight = 0x02,
    kMiddle = 0x04,
};

uint8_t mouseState { 0 };

if ((mouseState & MouseState::kLeft) != 0) {
    std::cerr << "okay\n";
}

编译时出现如下错误:

error: invalid operands to binary expression ('uint8_t' (aka 'unsigned char') and 'MouseState')
                        if ((mouseState & MouseState::kLeft) != 0) {
                             ~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~

但如果移除class关键字,使用普通枚举定义:

enum MouseState : uint8_t
{
    kLeft = 0x01,
    kRight = 0x02,
    kMiddle = 0x04,
};

则编译正常(使用C++20标准与clang编译器)。请问这是为什么?

原因解析

这事儿的本质是普通枚举(enum)和强类型枚举(enum class)的设计差异:

  • 普通枚举的枚举值会自动隐式转换成它的底层整数类型(这里就是uint8_t)。所以你写mouseState & MouseState::kLeft时,MouseState::kLeft会悄悄转成uint8_t,和mouseState类型对上,按位与操作自然合法。

  • 强类型枚举(enum class)从设计上就主打强类型隔离,它不会自动转成整数类型。MouseState::kLeft的类型是MouseState,而mouseState是uint8_t,两种完全不同的类型不能直接做按位与,编译器当然要报错。

如果想保留enum class的类型安全特性,同时完成这个操作,有两个常用办法:

  1. 手动把枚举值转成整数类型:
if ((mouseState & static_cast<uint8_t>(MouseState::kLeft)) != 0) {
    std::cerr << "okay\n";
}
  1. 给enum class重载按位与运算符,让它支持和整数的操作(不过这么做会削弱强类型的隔离性,得按需使用)。

内容的提问来源于stack exchange,提问作者user18490

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 02:58:22