C++ 在C+中键入定义位字段/掩码+;
我在C++中遇到了这个问题:我可以键入一个值来自枚举的位字段吗 代码将更具解释性:C++ 在C+中键入定义位字段/掩码+;,c++,enums,typedef,bit-fields,C++,Enums,Typedef,Bit Fields,我在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( unsigne
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) );
但我觉得这很可怕,我甚至不确定它是否合法(它会截断值吗??。你有解决办法吗当你执行逐位操作时,编译器将视频音频数据作为一个整数值,所以你必须用*MyOxEngE**./P>< P>来分析它:如何实现一个特殊的函数来处理这个问题:
template <typename Enum>
Enum bitField(unsigned bits) {
return static_cast<Enum>(bits);
}
模板
枚举位字段(无符号位){
返回静态_-cast(位);
}
它为您的工作增添了表现力:
myFunction(bitField<my_enum_e>(VIDEO|AUDIO|DATA));
myFunction(位域(视频|音频|数据));
如果您想要更复杂,您可以这样做:
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;
}
}
模板
结构位域{
枚举值;
位字段(枚举值):值(值){}
位域运算符|(枚举更多){
返回位字段(值|更多);
}
位域运算符&(枚举更多){
返回位字段(值及更多);
}
位域运算符(){
返回位字段(~value);
}
运算符Enum(){
返回值;
}
}
这样你就可以写作了
myFunction(BitField<my_enum_e>(VIDEO) | AUDIO | DATA);
myFunction(位域(视频)|音频|数据);
一种解决方法是typedefint MY_标志编码>然后#定义所有值:
#定义音频0x01
等。这样编译器就不会抱怨了,您的函数调用中仍然会得到类型:
int myFunction( MY_FLAGS mask );
myFunction( VIDEO|AUDIO|DATA );
为|
和其他运算符添加显式重载
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) ...
我建议您查看以下线程:-在[Boost Vault](filenameenum_rev4.6.zip
)中提到的实现。还可以声明一个BOOST\u位字段
:
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 );
}
void callerFunction()
{
我的数字面具;
mask.set(my_enum_e::AUDIO);
mask.set(my_enum_e::VIDEO | my_enum_e::SUBTITLE);
在代码< > TyPulf< /Cord>故意之后,你是否省略了<代码> EnUM <代码>关键字?有,是的,我不知道它是否危险。我的所有类型都使用“未命名的”结构/EnUM。相关的用户名的UpDebug。@ Gui13,在C++中,你最好是<代码> EnUM E{};< /> > > <代码> TyPulfEnUM {}E;
不管怎样。是我的旧C行李又来敲门了吗?:)我刚刚意识到,如果你的函数采用枚举,并且你要组合值,那么每次组合都需要在该枚举中包含一些内容,否则就是UB。@chris:嗯,是的,当然。我怎么会错过它呢?!让我来修复它。尽管你的解决方案很优雅,但我还是会采用n.m.的解决方案在C++的头文件中定义< <代码> >是邪恶的。永远不要这样做,它会使范围混乱,而且会适得其反。为什么?它是一个干净清晰的解决方案,不像有些……哦,你的!太好了!只是一个小提示:你必须把代码< < < />代码>和<代码> B/C> >其他东西(如<代码>未签名< /代码>)为了避免无休止的递归。哦,是的。对不起。我确实进行了强制转换,但在尝试缩短代码时删除了它,并且没有检查它:(