我在项目的一部分中有这段代码:
enum myEnum
{
invalid = -1,
val1 = 1,
val2 = 2,
val3 = 4
};
int bitmask = val1 | val3;
if(bitmask & val1)
...
if(bitmask & val2)
...
if(bitmask & val3)
...
这很好,而且效果很好,但我总是想知道是否可以用开关完成。我正在思考这个问题:
int checkMask(int& mask)
{
for(int i = 0; mask; mask &= ~(1 << i++))
{
if(mask & (1 << i))
{
int ret = mask & (1 << i);
mask &= ~ret;
return ret;
}
}
return invalid;
}
#define START_BITMASK_SWITCH(x) int xcopy = x; while(xcopy) { switch(checkMask(xcopy))
#define END_BITMASK_SWITCH };
int bitmask = val1 | val3;
START_BITMASK_SWITCH(bitmask)
{
case val1:
...
break;
case val2:
...
break;
case val3:
...
break;
}
END_BITMASK_SWITCH
所以我的问题是:
答案 0 :(得分:12)
不,它不是一个干净的解决方案,对于您的上下文,您可以避免混合#define
和函数。如果您需要switch()
:
int bitmask = val1 | val3;
int mask = 1;
while(bitmask)
{
switch(bitmask & mask)
{
case val1: ... break;
case val2: ... break;
case val4: ... break;
case val8: ... break;
}
bitmask &= ~mask;
mask <<= 1;
}
答案 1 :(得分:6)
不,它(显然)不是一个干净的解决方案。您的原始代码是直接的,没有循环,并且不涉及为该语言添加奇怪结构的特殊情况“秘密”宏。
通过“奇怪的构造”,我指的是START_BITMASK_SWITCH()
/ END_BITMASK_SWITCH
宏,其中:
对您的解决方案没有任何好处,它所做的只是增加膨胀和开销(在代码大小,复杂性和运行时性能方面),只是为了抓住由于某种原因想要使用{{ 1}}做一些不太适合做的事情。
显然,这是非常主观的,但你确实在问。
答案 2 :(得分:4)
我看到了几个问题:
if ((bitmask & (val2 | val3)) == val2)
)它也可以用更简单的方式完成:
#define START_BITMASK_SWITCH(x) \
for (uint64_t bit = 1; x >= bit; bit *= 2) if (x & bit) switch (bit)
int bitmask = val1 | val3;
START_BITMASK_SWITCH(bitmask)
{
case val1:
...
break;
case val2:
...
break;
case val3:
...
break;
}
答案 3 :(得分:3)
如果需要,位掩码只是一个bool数组,而你的枚举就是索引。你能切换一阵bool吗?不,你不能,因为它可以同时代表多个状态。您只能像使用任何整数一样切换整个位掩码。
答案 4 :(得分:0)
您可以创建一个foreach构造,在其中迭代位掩码的位并提供一个带有switch语句的函数。
答案 5 :(得分:0)
当然可以,如果那是您真正想要的。如前所述,只有少数情况可能需要,也许没有。但是可以。
#include <iostream>
enum myEnum
{
invalid = -1,
val1 = 1,
val2 = 2,
val3 = 4
};
int main()
{
const int bitmask = val1 | val3;
switch (1) {
case (bitmask & val1) : std::cout << "1"; break;
case (bitmask & val2) : std::cout << "2"; break;
case (bitmask & val3) : std::cout << "3"; break;
default: break;
}
}
答案 6 :(得分:-1)
enum Positions {
ALPHA,
BETA,
GAMMA
};
enum Flag {
ALPHA_FLAG == 1 << ALPHA,
BETA_FLAG == 1 << BETA,
GAMMA_FLAG == 1 << GAMMA
};
Position position_of (Flag f) {
unsigned n = f;
unsigned i = 0;
while ((n & 1) == 0) {
++i;
n >>= 1;
}
return Position (i);
}
switch (position_of (flag)) {
case ALPHA:
case BETA:
// ...
};
这对于C++0x strong enums更好,然后您可以Position::ALPHA
和Flag::ALPHA
来获得更清晰的命名。您还可以使用constexpr
安全地对您的标记值进行位掩码。