Question

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!

Was it helpful?

Solution

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

OTHER TIPS

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.

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.

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.

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

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top