在c++11开始引入了枚举类型enum class,在此之前enum关键字所声明的枚举更像是一个普通的常量集合,会将当前作用域视为访问空间,而enum class解决了这一问题。但作为类型也失去了像数字一样的位运算,尤其在使用Flags时会尤为困难,这里将会编写宏定义,自动生成完成运算符的重载。
enum class可以有一个明确的类型,可以是int32_t、int64_t等等,在运算符时要将枚举强制转换回本身整数类型时才可以进行运算,这里将会使用标准库提供的std::underlying_type_t(cppreference),即std::underlying_type_t<Enum>
#pragma once #define ENUM_CLASS_FLAGS(Enum) \ inline constexpr Enum& operator|=(Enum& x, Enum y) { \ return x = static_cast<Enum>( \ static_cast<std::underlying_type_t<Enum>>(x) | static_cast<std::underlying_type_t<Enum>>(y) \ ); } \ inline constexpr Enum& operator&=(Enum& x, Enum y) { \ return x = static_cast<Enum>( \ static_cast<std::underlying_type_t<Enum>>(x) & static_cast<std::underlying_type_t<Enum>>(y) \ ); } \ inline constexpr Enum& operator^=(Enum& x, Enum y) { \ return x = static_cast<Enum>( \ static_cast<std::underlying_type_t<Enum>>(x) ^ static_cast<std::underlying_type_t<Enum>>(y) \ ); } \ inline constexpr Enum operator| (Enum x, Enum y) { \ return static_cast<Enum>( \ static_cast<std::underlying_type_t<Enum>>(x) | static_cast<std::underlying_type_t<Enum>>(y) \ ); } \ inline constexpr Enum operator& (Enum x, Enum y) { \ return static_cast<Enum>( \ static_cast<std::underlying_type_t<Enum>>(x) & static_cast<std::underlying_type_t<Enum>>(y) \ ); } \ inline constexpr Enum operator^ (Enum x, Enum y) { \ return static_cast<Enum>( \ static_cast<std::underlying_type_t<Enum>>(x) ^ static_cast<std::underlying_type_t<Enum>>(y) \ ); } \ inline constexpr bool operator! (Enum x) { \ return !static_cast<std::underlying_type_t<Enum>>(x); \ } \ inline constexpr Enum operator~ (Enum x) { \ return static_cast<Enum>(~static_cast<std::underlying_type_t<Enum>>(x)); \ } template<typename Enum> inline constexpr bool EnumHasFlag(Enum a, Enum b) { return static_cast<bool>( static_cast<std::underlying_type_t<Enum>>(a & b) ); }
同时对于if来说该枚举值是无法直接使用的,最后添加一个EnumHasFlag来帮助枚举位运算。
枚举属于编译期的常量,靠编译期的常量计算与内联可以忽略该定义所带来的开销。
文章评论