Polymorphic bit flags in C++

I often encounter cases in ObjectARX programming where numerous boolean flags need to be persisted as part of an AutoCAD database object. For filing and for passing around to other functions, it’s most efficient to package those bit flags into a single unsigned integer. Below is an example that demonstrates how to use a union inside a containing class that can be simultaneously used as either a single unsigned integer or as individual booleans.


// first declare a compact bitflag structure as bool values
struct FlagsAsBools
{
bool flag1 : 1;
bool flag2 : 1;
bool flag3 : 1;
bool flag4 : 1;
bool flag5 : 1;
bool flag6 : 1;
bool flag7 : 1;
bool flag8 : 1;
bool flag9 : 1;
bool flag10 : 1;
bool flag11 : 1;
bool flag12 : 1;
};

// now the containing class with useful constructors and operators
class Flags
{
protected:
// and the hidden union that actually contains the flags
union _Flags
{
FlagsAsBools asBools;
Adesk::UInt32 asUInt; //space for up to 32 flags
} mFlags;
public:
Flags()
{
mFlags.asUInt = 0;
}
Flags(Adesk::UInt32 flags)
{
mFlags.asUInt = flags;
}
Flags(const FlagsAsBools& flags)
{
mFlags.asBools = flags;
}
operator Adesk::UInt32 () const { return mFlags.asUInt; }
const FlagsAsBools& asBools() const { return mFlags.asBools; }
FlagsAsBools& asBools() { return mFlags.asBools; }
};

// now a class that contains the flags
class Settings
{
AcString msSomeStringSetting;
bool mbSomeBoolSetting;
Flags mFlags;
public:
Settings () : mbSomeBoolSetting(false) {}

LPCTSTR someStringSetting() const { return msSomeStringSetting; }
void setSomeStringSetting(LPCTSTR someStringSetting) { msSomeStringSetting = someStringSetting; }
bool someBoolSetting() const { return mbSomeBoolSetting; }
void setSomeBoolSetting(bool someBoolSetting) { mbSomeBoolSetting = someBoolSetting; }
Flags flags() const { return mFlags; }
void setFlags(Flags flags) { mFlags = flags; }
};

// now use the flags as an argument to a function in different forms
void DoStuffBasedOnFlags( Adesk::UInt32 flags )
{
if( Flags(flags).asBools().flag7 )
{// do something when flag7 is set
}
}

void DoOtherStuffBasedOnFlags( const Flags& flags )
{
if( flags.asBools().flag1 )
{// do something when flag1 is set
}
}

void TestIt()
{
Settings& MySettings = GetSettings();
Flags flags = MySettings.flags();
if( flags.asBools().flag4 )
{// do something when flag4 is set
}
DoStuffBasedOnFlags( flags );
DoOtherStuffBasedOnFlags( flags );
flags.asBools().flag2 = true;
MySettings.setFlags( flags ); //save the new settings
}

One Comment

  1. Nice! I prefer this method over macros + ints, as it make the code much more readable . You can also add the union to the struct, along with handy methods to flip all the bits /on off.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>