1

If I wanted to represent states or options or something similar using binary "flags" so that I could pass them and store them to an object like OPTION1 | OPTION2 where OPTION1 is 0001 and OPTION2 is 0010, so that what gets passed is 0011, representing a mix of the options.

How would I do this in C++? I was thinking something like

enum Option {
    Option_1 = 0x01,
    Option_2 = 0x02,
    Option_3 = 0x04,
    //...
}

void doSomething(Option options) {
    //...
}

int main() {
    doSomething(Option_1|Option_2);
}

But then ideally, doSomething knows how to interpret the given Option.

Am I on the right track? Is there a better way?

Update

And wouldn't I have to define an Option for every possible combination, also?

Austin Hyde
  • 26,347
  • 28
  • 96
  • 129

4 Answers4

6

This is a common way these things are done. doSomething can use bitwise and operator to see if an option is selected:

if (options & Option_1){ 
  // option 1 is selected
}

Alternatively, you can consider using bit fields:

struct Options {
    unsigned char Option_1 : 1;
    unsigned char Option_2 : 1;
};

Options o;
o.Option_1 = 1;
o.Option_2 = 0;
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
4

That'd be the way I'd do it. However there are many tricks you can use to make the enumeration a little more readable:

enum Option {
    Option1 = 1 /*<< 0*/,
    Option2 = 1 << 1,
    Option3 = 1 << 2,
    // etc.
};

What is more, you'll need to specify bitwise operators for your enumeration. Consider something like ASL's enum_ops utilities to help out with this.

fbrereto
  • 35,429
  • 19
  • 126
  • 178
3

Its worth noting that the way people usually use such flags is to define the function as follows:

void doSomething( unsigned int options ) 
{
    //...
}

everything else will work exactly as you want :)

The other way is to create your own "Flags" class. Then you have a couple of functions as follows in the class:

bool GetOption( Option option )
{
    return (m_Option & option) > 0;
}

void SetOption( Option option )
{
    m_Option |= option;
}

void ClearOption( Option option )
{
    m_Option &= ~option;
}

or even overload the operators to do exactly as you'd like e.g:

Flags( unsigned int options ) :
   m_Option( options )
{
}

Flags operator|( const Flags& flags )
{
    return Flags( m_Option | flags.m_Option );
}

and so on.

Goz
  • 61,365
  • 24
  • 124
  • 204
  • Not ideal in the spirit of data hiding, however. If your number of options later exceeds 32, you'd be forced to change your code. – no-op Sep 10 '09 at 19:53
  • True ... the version i wrote of this actually used a template parameter – Goz Sep 10 '09 at 20:15
1

You may want to check out the stl bitset. Some people would preach that you should always use those instead of C-style bitflags. However, both solutions are fine IMO.

StackedCrooked
  • 34,653
  • 44
  • 154
  • 278