Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bitmask switch statement

I have this code in a section of my project:

enum myEnum
{
    invalid = -1,
    val1 = 1,
    val2 = 2,
    val3 = 4
};

int bitmask = val1 | val3;

if(bitmask & val1)
    ...
if(bitmask & val2)
    ...
if(bitmask & val3)
    ...

This is fine, and it works perfectly, but i've always wondered if it could be done with a switch. I was thinking something along the lines this:

int checkMask(int& mask)
{
    for(int i = 0; mask; mask &= ~(1 << i++))
    {
        if(mask & (1 << i))
        {
            int ret = mask & (1 << i);
            mask &= ~ret;
            return ret;
        }
    }

    return invalid;
}

#define START_BITMASK_SWITCH(x) int xcopy = x; while(xcopy) { switch(checkMask(xcopy))
#define END_BITMASK_SWITCH };

int bitmask = val1 | val3;

START_BITMASK_SWITCH(bitmask)
{
    case val1:
        ...
        break;
    case val2:
        ...
        break;
    case val3:
        ...
        break;
}
END_BITMASK_SWITCH

so my questions are:

  • have i just solved my problem? i suppose i have, but is it a clean solution?
  • is there a simpler way of accomplishing this?
  • is it a bad idea to mix #defines and functions?
  • like image 686
    Tom Avatar asked Jul 07 '11 08:07

    Tom


    2 Answers

    No it's not a clean solution and for your context, you can avoid mixing #define and functions. You can try below solution, if you want switch():

    int bitmask = val1 | val3;
    int mask = 1;
    while(bitmask)
    {
      switch(bitmask & mask)
      {
      case val1: ... break;
      case val2: ... break;
      case val4: ... break;
      case val8: ... break;
      }
      bitmask &= ~mask; 
      mask <<= 1;
    }
    
    like image 179
    iammilind Avatar answered Sep 22 '22 23:09

    iammilind


    No, it is (obviously) not a clean solution. Your original code was straight-forward, didn't loop, and didn't involve special-case "secret" macros that add weird constructs to the language.

    By "weird construct", I meant the START_BITMASK_SWITCH()/END_BITMASK_SWITCH macros, which:

    • Add a loop without using any of the standard keywords to even hint that a loop is happening
    • Clobber names in the current scope more or less silently
    • Include a spurious semi-colon

    There's no benefit to your solution, all it does is add bloat and overhead (both in terms of code size, and complexity, and run-time performance) just to scratch that itch of for some reason wanting to use a switch to do something that it's not very well-suited to do.

    Obviously, this is highly subjective, but you did ask.

    like image 25
    unwind Avatar answered Sep 22 '22 23:09

    unwind