C ++从枚举值中获取位移

时间:2015-03-26 16:33:20

标签: c++ enums bit-shift

假设我有一个用于标志的枚举,即

enum Flags { Flag1 = 1 << 0, Flag2 = 1 << 1, Flag3 = 1 << 2 };

如果给出Flags值,我想知道该值的位偏移是什么。基本上,对于Flag1,我想返回0,对于Flag2我想返回1,等等。除了使用带有{{1}的函数之外,是否有人能想到这样做的方法声明。

我想要这个,因为我有一个数据数组,函数的返回值是这个数组的元素之一。要返回的元素取决于将哪个标志传递给函数。

我想要更简洁的方法来执行以下操作。特别是如果我修改枚举,我不需要返回并修改此功能。

switch

3 个答案:

答案 0 :(得分:5)

您需要的是一个计算枚举值中尾随零的函数。有很多方法可以做到这一点(参见https://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightLinear),但大多数现代平台通常都提供专用的CPU指令。由于该语言没有相应的运算符,因此只能通过非标准编译器特定方式访问该指令,例如GCC中的__builtin_ctz或MSVC中的_BitScanReverse

但是,如果您只使用编译时值,那么更好的C ++解决方案将是

template <unsigned N> struct ctz {
  static const unsigned value = ctz<N - 1>::value + 1;
};

template <> struct ctz<1> {
  static const unsigned value = 0;
};

template <> struct ctz<0>; // Left undefined

...
cout << ctz<Flag2>::value << endl;

答案 1 :(得分:2)

最简洁(也许是正确的)方法是重新设计设计。 &#39;标志&#39;并不是真正的旗帜 - 它是一个索引,所以代码就索引而言。

enum Index { I1, I2, I3, INDEX_COUNT };

myobj* objects[INDEX_COUNT] = { obj1, obj2, obj3 };

myobj* GetObj(Index i)
{
    assert(i < INDEX_COUNT);
    return objects[i];
}

答案 2 :(得分:1)

这样的事情应该有效:

int iFlag = (int)FlagValue;
int ix = 0;
while (iFlag > 1) {
  ix++;
  iFlag = iFlag >> 1;
}
return objects[ix];

为安全起见,请添加对FlagValue <= 0FlagValue >= (sizeof(objects) / sizeof(objects[0]))等非法输入的检查。