在枚举中设置位标志的最简方法是什么?如何批量声明位标志枚举
解决方案
方法1:使用宏批量生成位标志枚举项
C++原生没有自动按位递推枚举类值的语法,最常用的简化方案是自定义宏实现批量生成,你后续新增枚举项不需要手动写1 << n:
// 先定义位标志生成宏 #define BIT_FLAG_ENUM_ITEM(name, index) name = 1ULL << index enum class GUIEventEnum : uint64 { NONE = 0, BIT_FLAG_ENUM_ITEM(CURSOR_LMB_DOWN, 1), BIT_FLAG_ENUM_ITEM(CURSOR_LMB_UP, 2), BIT_FLAG_ENUM_ITEM(CURSOR_LMB_CLICK, 3), BIT_FLAG_ENUM_ITEM(CURSOR_RMB_DOWN, 4), BIT_FLAG_ENUM_ITEM(CURSOR_RMB_UP, 5), BIT_FLAG_ENUM_ITEM(CURSOR_RMB_CLICK, 6), BIT_FLAG_ENUM_ITEM(CURSOR_MMB_DOWN, 7), BIT_FLAG_ENUM_ITEM(CURSOR_MMB_UP, 8), BIT_FLAG_ENUM_ITEM(CURSOR_MMB_CLICK, 9), BIT_FLAG_ENUM_ITEM(CURSOR_SCROLL, 10), // 后续新增只需按顺序填序号即可 BIT_FLAG_ENUM_ITEM(CURSOR_MOVE, 11), }; #undef BIT_FLAG_ENUM_ITEM // 用完取消宏定义,避免命名冲突
如果连序号都不想手动维护,可以用主流编译器(GCC、Clang、MSVC)都支持的__COUNTER__宏,实现完全按列表顺序自动分配位偏移:
// 自动递推位序号的版本 #define AUTO_BIT_FLAG(name) name = 1ULL << __COUNTER__ // 先重置偏移,跳过0位,和你原有定义的位偏移兼容 constexpr int __reset_counter = __COUNTER__; constexpr int __skip_zero_bit = __COUNTER__; enum class GUIEventEnum : uint64 { NONE = 0, AUTO_BIT_FLAG(CURSOR_LMB_DOWN), // 自动对应1<<1 AUTO_BIT_FLAG(CURSOR_LMB_UP), // 自动对应1<<2 AUTO_BIT_FLAG(CURSOR_LMB_CLICK), // 自动对应1<<3 AUTO_BIT_FLAG(CURSOR_RMB_DOWN), AUTO_BIT_FLAG(CURSOR_RMB_UP), AUTO_BIT_FLAG(CURSOR_RMB_CLICK), AUTO_BIT_FLAG(CURSOR_MMB_DOWN), AUTO_BIT_FLAG(CURSOR_MMB_UP), AUTO_BIT_FLAG(CURSOR_MMB_CLICK), AUTO_BIT_FLAG(CURSOR_SCROLL), // 后续新增直接往下列即可,不需要手动管序号 AUTO_BIT_FLAG(CURSOR_MOVE), AUTO_BIT_FLAG(WINDOW_RESIZE), }; #undef AUTO_BIT_FLAG
方法2:C++20及以上版本用constexpr实现无宏方案
如果你使用C++20及更高标准,可以用编译期constexpr计算实现和普通枚举完全一致的声明方式,不需要引入宏:
#include <array> #include <cstdint> // 声明和普通枚举完全一致,不需要手动赋值 enum class GUIEventEnum : uint64 { NONE = 0, CURSOR_LMB_DOWN, CURSOR_LMB_UP, CURSOR_LMB_CLICK, CURSOR_RMB_DOWN, CURSOR_RMB_UP, CURSOR_RMB_CLICK, CURSOR_MMB_DOWN, CURSOR_MMB_UP, CURSOR_MMB_CLICK, CURSOR_SCROLL, // 后续新增直接往下列即可 _COUNT // 最后加一个计数项用于编译期计算 }; // 编译期自动生成所有位值查找表 constexpr std::array<uint64, static_cast<size_t>(GUIEventEnum::_COUNT)> event_bit_values = [](){ std::array<uint64, static_cast<size_t>(GUIEventEnum::_COUNT)> arr{}; for (size_t i = 1; i < arr.size(); i++) { arr[i] = 1ULL << i; } return arr; }(); // 工具函数获取枚举对应的位值 constexpr uint64 get_event_bit(GUIEventEnum e) { return event_bit_values[static_cast<size_t>(e)]; }
配套优化建议
可以额外重载枚举类的位运算符,避免使用时每次都手动转底层类型:
constexpr GUIEventEnum operator|(GUIEventEnum a, GUIEventEnum b) { return static_cast<GUIEventEnum>(static_cast<uint64>(a) | static_cast<uint64>(b)); } constexpr GUIEventEnum operator&(GUIEventEnum a, GUIEventEnum b) { return static_cast<GUIEventEnum>(static_cast<uint64>(a) & static_cast<uint64>(b)); } // 其他位运算符按需重载即可
内容的提问来源于stack exchange,提问作者Zebrafish
相关产品推荐
相关产品推荐

