问题
I recently came across some functions where you can pass multiple enums like this:
myFunction(One | Two);
Since I think this is a really elegant way I tried to implement something like that myself:
void myFunction(int _a){
switch(_a){
case One:
cout<<"!!!!"<<endl;
break;
case Two:
cout<<"?????"<<endl;
break;
}
}
now if I try to call the function with One | Two, I want that both switch cases get called. I am not really good with binary operators so I dont really know what to do. Any ideas would be great!
Thanks!
回答1:
For that you have to make enums like :
enum STATE {
STATE_A = 1,
STATE_B = 2,
STATE_C = 4
};
i.e. enum element value should be in power of 2 to select valid case or if statement.
So when you do like:
void foo( int state) {
if ( state & STATE_A ) {
// do something
}
if ( state & STATE_B ) {
// do something
}
if ( state & STATE_C ) {
// do something
}
}
int main() {
foo( STATE_A | STATE_B | STATE_C);
}
回答2:
Bitwise operators behave well only with powers of 2:
0010
| 0100
------
0110 // both bits are set
0110
& 0100
------
0100 // nonzero, i.e. true: the flag is set
If you try to do the same with arbitrary numbers, you'll get unexpected results:
0101 // 5
| 1100 // 12
------
1101 // 13
Which contains the possible (arbitrary) numbers as set flags: 0001
(1), 0100
(4), 0101
(5), 1000
(8), 1001
(9), 1100
(12), 1101
(13)
So instead of giving two options, you just gave six.
回答3:
Usually arguments that are combined that way are flags (a value with a single bit set) with a decimal value of 1, 2, 4, 8, etc. Assuming that One and Two follow this rule, you cannot use a switch to check for both. Switches only follow one path. Your combined argument does not equal One or Two, but a combination of them (1 | 2 == 3). You can check to see if One or Two is set like this:
if (_a & One)
{
}
if (_a & Two)
{
}
Remember that a standard enum without explicit values will just count upwards, not use the next bit. If your next defined value is Three, it will likely equal 3 which is not a value of a single bit, and will then act as if you had passed both flags (One | Two) to the function. You'll need to set the values of the enum yourself.
回答4:
You must split the possible "tokens" (non-overlapping of course... use power of 2):
if (_a & One) { ... }
Not elegant really do what you want with 1 switch statement: split using if
statements.
回答5:
You are better off doing it with a set of if statements ...
ie
if ( _a & ONE )
{
// Do stuff.
}
if ( _a & TWO )
{
// Do other stuff.
}
edit: You could also do it in a switch statement but it would be a nightmare. Youd need something like this
switch( _a )
{
case ONE:
// Handle ONE.
break;
case TWO:
// Handle TWO.
break;
case ONE | TWO:
// Handle ONE.
// Handle TWO.
break;
};
Its relatively sane for only 2 options but once you get more than that it starts to balloon out of control. If you have 32-options you'd have a switch statement that would be unlikely to fit on any machine. All in the "if" solution is much cleaner and far more sane :)
来源:https://stackoverflow.com/questions/1874051/c-multiple-enums-in-one-function-argument-using-bitwise-or