tags:

views:

423

answers:

4

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?

+4  A: 

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
What are bit fields? How would I use them?
Austin Hyde
Austin: see the link I posted and the sample in my answer.
Mehrdad Afshari
Damn, 4 years of professional C++ development, and I had NEVER even heard or read about bit fields!
StackedCrooked
Gotta be careful about bitfields, though, as outlined here: http://msdn.microsoft.com/en-us/library/ewwyfdbe%28VS.71%29.aspx
fbrereto
+3  A: 

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
I use this style as well, much less confusing and totally nifty!
StackedCrooked
+1  A: 

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
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
True ... the version i wrote of this actually used a template parameter
Goz
+1  A: 

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