一、引言
枚举 enum
是我们用的比较多的类型,而枚举通常适用的场景,也是为了我们在业务逻辑处理时,作为不同的逻辑分支的判断条件;比起直接定义1~N
这样魔幻到让人一头雾水的分支 Flag
, 定义完美的枚举类型可以见名知意,简直不要太优雅。
但是,我们偶尔也会面临这样的分支选择,我既要执行状态A,还要执行状态B,(好看的姑娘当然都要,小孩子才做选择),那么,在使用枚举作为分支条件时,该如何处理呢?
以下,抛砖引玉,给出简单的示例。
二、代码示例
1、简单版本
#include <iostream>
// 定义位掩码枚举
enum class MultiState : unsigned int {
NONE = 0,
STATE1 = 1 << 0, // 0001
STATE2 = 1 << 1, // 0010
STATE3 = 1 << 2, // 0100
STATE4 = 1 << 3 // 1000
};
// 定义位运算符重载
inline MultiState operator|(MultiState a, MultiState b) {
return static_cast<MultiState>(static_cast<unsigned int>(a) | static_cast<unsigned int>(b));
}
inline MultiState& operator|=(MultiState& a, MultiState b) {
a = a | b;
return a;
}
inline bool operator&(MultiState a, MultiState b) {
return static_cast<bool>(static_cast<unsigned int>(a) & static_cast<unsigned int>(b));
}
void printMultiState(MultiState state) {
if (state & MultiState::STATE1) std::cout << "STATE1 ";
if (state & MultiState::STATE2) std::cout << "STATE2 ";
if (state & MultiState::STATE3) std::cout << "STATE3 ";
if (state & MultiState::STATE4) std::cout << "STATE4 ";
if (state == MultiState::NONE) std::cout << "NONE";
std::cout << std::endl;
}
int main() {
MultiState state = MultiState::STATE1 | MultiState::STATE3;
printMultiState(state);
state |= MultiState::STATE2;
printMultiState(state);
return 0;
}
如果有试图问 enum class MultiState
语法的朋友,请前往《为何推荐首选enum class 而非 enum》
这里有巧妙使用位运算,保证复合态值的唯一,并在判断每个态是否为真时,起到关键的作用;不过缺点也很明显,如果枚举类型的值很多,
void printMultiState(MultiState state) {
if (state & MultiState::STATE1) std::cout << "STATE1 ";
if (state & MultiState::STATE2) std::cout << "STATE2 ";
if (state & MultiState::STATE3) std::cout << "STATE3 ";
if (state & MultiState::STATE4) std::cout << "STATE4 ";
if (state == MultiState::NONE) std::cout << "NONE";
std::cout << std::endl;
}
这里 if ... else ...
岂不是要写到死?这肯定是不能接受的。
2、进阶版本
#include <iostream>
#include <vector>
// 定义位掩码枚举
enum class MultiState : unsigned int {
NONE = 0,
STATE1 = 1 << 0, // 0001
STATE2 = 1 << 1, // 0010
STATE3 = 1 << 2, // 0100
STATE4 = 1 << 3, // 1000
// 添加更多状态
STATE5 = 1 << 4,
STATE6 = 1 << 5,
// ...
};
// 定义位运算符重载
inline MultiState operator|(MultiState a, MultiState b) {
return static_cast<MultiState>(static_cast<unsigned int>(a) | static_cast<unsigned int>(b));
}
inline MultiState& operator|=(MultiState& a, MultiState b) {
a = a | b;
return a;
}
inline bool operator&(MultiState a, MultiState b) {
return static_cast<bool>(static_cast<unsigned int>(a) & static_cast<unsigned int>(b));
}
// 定义状态和字符串表示的结构体
struct StateInfo {
MultiState state;
const char* name;
// std::function<void()> f;
};
// 定义状态和字符串表示的数组
const StateInfo stateInfos[] = {
{ MultiState::STATE1, "STATE1" },
{ MultiState::STATE2, "STATE2" },
{ MultiState::STATE3, "STATE3" },
{ MultiState::STATE4, "STATE4" },
{ MultiState::STATE5, "STATE5" },
{ MultiState::STATE6, "STATE6" },
// 添加更多状态
};
void printMultiState(MultiState state) {
bool hasState = false;
for (const auto& info : stateInfos) {
if (state & info.state) {
std::cout << info.name << " ";
hasState = true;
}
}
if (!hasState) {
std::cout << "NONE";
}
std::cout << std::endl;
}
int main() {
MultiState state = MultiState::STATE1 | MultiState::STATE3;
printMultiState(state);
state |= MultiState::STATE2;
printMultiState(state);
return 0;
}
这次高级点,用循环处理复合态;当然这里定义StateInfo
结构体中可以增加对应每个enum
处理的函数指针变量,并在for循环中调用,岂不美哉~
这可不就是由处理复合枚举类型,而衍生的一个简单优雅的小框架了么~