简体   繁体   English

在C ++中键入一个bitfield / mask

[英]Typedef a bitfield / mask in C++

I have this problem in C++: can I typedef a bitfield whose values come from an enum? 我在C ++这样的问题:我可以的typedef位字段的值来自枚举?

Code will be more explainatory: 代码将更具说明性:

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 );

In the prototype of the function, I'd like to use my_enum_e as an input value type, so that when exploring the code, you can immediately know which values you're supposed to put in there. 在函数原型中,我想使用my_enum_e作为输入值类型,这样在探索代码时,您可以立即知道应该放在哪里的值。

Now, changing the prototype to 现在,将原型更改为

int myFunction( my_enum_e mask );

makes the compiler whine about a cast error. 让编译器抱怨一个强制转换错误。 I cant fix it by casting the function calls like this: 我无法通过强制转换函数调用来修复它:

int myFunction( my_enum_e mask )
{
    // code
}

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

But I find this quite horrible, and I'm not even sure it is legal (could it truncate the value??). 但我发现这非常可怕,我甚至不确定它是否合法(它能否截断值?)。
Do you have a solution? 你有解决方案吗?

Add an explicit overload for | |添加显式重载 and possibly other operators. 可能还有其他运营商。

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

One can write a macro that defines all needed operators for a given bitmask type. 可以编写一个宏来定义给定位掩码类型的所有所需操作符。

#define BITMASK_OPERATORS(T)   T operator|(T a, T b) { return T(unsigned(a)|unsigned(b)); } \
                                 T operator^(T a, T b) ...

How about implementing a special function to deal with this: 如何实现一个特殊的功能来处理这个问题:

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

It adds expressiveness to what you're doing: 它增加了你正在做的事情的表现力:

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

If you want more sophistication, you can do this: 如果你想要更复杂,你可以这样做:

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;
  }
}

Which will allow you to write 这将允许你写

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

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

I recommend that you look at this thread: Which Typesafe Enum in C++ Are You Using? 我建议您查看此主题: 您使用的C ++中哪个Typesafe枚举? - The mentioned implemention in the [Boost Vault] (filename enum_rev4.6.zip ). - [Boost Vault]中提到的实现(文件名enum_rev4.6.zip )。 1 provides also the possibility to declare a BOOST_BITFIELD : 1还提供了声明BOOST_BITFIELD的可能性:

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

you can then declare your function: 然后你可以声明你的功能:

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

The usage is then 然后使用

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 );

}

The documentation of the api is not that good. api的文档不是那么好。 But the packages comes with a test that shows several usages. 但是这些软件包附带了一个显示几种用法的测试。

One way around it is to typedef int MY_FLAGS; 解决这个问题的一种方法是typedef int MY_FLAGS; and then #define all your values instead: #define AUDIO 0x01 etc. That way the compiler won't moan and you still get types in your function calls: 然后#define你的所有值: #define AUDIO 0x01等。这样编译器不会呻吟,你仍然在函数调用中得到类型:

int myFunction( MY_FLAGS mask );

myFunction( VIDEO|AUDIO|DATA );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM