Using binary flags to represent states, options, etc
Question
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?
Solution
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;
OTHER TIPS
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.
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.
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.