4

我在 C++ 中遇到了这个问题:我可以键入一个其值来自枚举的位域吗

代码将更具解释性:

typedef {
 AUDIO    = 0x01,
 VIDEO    = 0x02,
 SUBTITLE = 0x04,
 DATA     = 0x08,
 GUARD,
 ALL      = 0xFF
} my_enum_e;

// I'd like to replace 'unsigned int' by 'my_enum_e' or similar
int myFunction( unsigned int mask ) 
{
  // code
}

// called like this:
myFunction( AUDIO|VIDEO|DATA );

在函数的原型中,我想将其my_enum_e用作输入值类型,以便在探索代码时,您可以立即知道应该放入哪些值。

现在,将原型更改为

int myFunction( my_enum_e mask );

使编译器抱怨转换错误。我无法通过像这样转换函数调用来修复它:

int myFunction( my_enum_e mask )
{
    // code
}

myFunction( (my_enum_e)(VIDEO|AUDIO|DATA) );

但我觉得这很可怕,我什至不确定它是否合法(它会截断值吗??)。
你有解决方案吗?

4

5 回答 5

4

|为和可能的其他运算符添加显式重载。

my_enum_e operator|(my_enum_e a, my_enum_e b) 
    { return my_enum_e(unsigned(a)|unsigned(b)); }

可以编写一个宏,为给定的位掩码类型定义所有需要的运算符。

#define BITMASK_OPERATORS(T)   T operator|(T a, T b) { return T(unsigned(a)|unsigned(b)); } \
                                 T operator^(T a, T b) ...
于 2012-07-23T14:13:17.287 回答
2

如何实现一个特殊的功能来处理这个:

template <typename Enum>
Enum bitField(unsigned bits) {
  return static_cast<Enum>(bits);
}

它增加了你正在做的事情的表现力:

myFunction(bitField<my_enum_e>(VIDEO|AUDIO|DATA));

如果你想要更复杂,你可以这样做:

template <typename Enum>
struct BitField {
  Enum value;
  BitField(Enum value) : value(value) {}
  BitField operator|(Enum more) {
    return BitField(value | more);
  }
  BitField operator&(Enum more) {
    return BitField(value & more);
  }
  BitField operator~() {
    return BitField(~value);
  }
  operator Enum() {
    return value;
  }
}

这将允许你写

myFunction(BitField<my_enum_e>(VIDEO) | AUDIO | DATA);
于 2012-07-23T14:06:11.070 回答
0

当您执行按位运算时,编译器会将VIDEO|AUDIO|DATA视为整数值,因此您必须使用 *my_enum_e* 对其进行转换。

于 2012-07-23T14:00:29.043 回答
0

我建议您查看此线程:您使用的是 C++ 中的哪个类型安全枚举?enum_rev4.6.zip- [Boost Vault](文件名)中提到的实现。1还提供了声明 a 的可能性BOOST_BITFIELD

BOOST_BITFIELD(my_enum_e, 
  (AUDIO)    (0x01)
  (VIDEO)    (0x02)
  (SUBTITLE) (0x04)
  (DATA)     (0x08)
);

然后你可以声明你的函数:

int myFunction( const my_enum_e & in_enum ) 
{
  if ( in_enum[AUDIO] ) ...
}

那么用法就是

void callerFunction()
{
  my_enum_e mask;
  mask.set(my_enum_e::AUDIO);
  mask.set(my_enum_e::VIDEO | my_enum_e::SUBTITLE );
  cout << mask << " = " << hex << mask.value() << endl; // will print: AUDIO|VIDEO|SUBTITLE = 0x7
  myFunction( mask );

}

api的文档不是很好。但是这些软件包附带了一个显示几种用法的测试。

于 2012-07-23T17:59:40.553 回答
-2

解决它的一种方法是typedef int MY_FLAGS;,然后 #define 你所有的值: #define AUDIO 0x01等等。这样编译器就不会抱怨,你仍然会在函数调用中获得类型:

int myFunction( MY_FLAGS mask );

myFunction( VIDEO|AUDIO|DATA );
于 2012-07-23T14:08:05.047 回答