Search code examples
c++switch-statementbitwise-operatorsbitmaskbit-masks

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?


  • Solution

  • I see several problems:

    • it adds preprocessor cruft with no real benefit
    • it adds a lot of slow code (shifts, loops, tests)
    • it prevents you from adding special cases such as "if bit 2 is on and bit 3 is off" (if ((bitmask & (val2 | val3)) == val2))
    • the compiler will miss almost every possibility to optimise the generated code

    It can also be done in a much, much simpler way:

    #define START_BITMASK_SWITCH(x) \
        for (uint64_t bit = 1; x >= bit; bit *= 2) if (x & bit) switch (bit)
    
    int bitmask = val1 | val3;
    
    START_BITMASK_SWITCH(bitmask)
    {
        case val1:
            ...
            break;
        case val2:
            ...
            break;
        case val3:
            ...
            break;
    }