• entries
    626
  • comments
    1446
  • views
    1008182

Free code!

Sign in to follow this  
ApochPiQ

97 views

I originally dropped this in a thread in For Beginners, but after thinking about it for a minute I decided maybe someone else could find it handy too, so I'll stick a copy here where it will get a little better visibility.


This is a simple C++ wrapper class for handling bitmasks. It's missing a few more-or-less non-critical features (like the ability to test two Bitmask objects against each other, for instance) but the basics are there, and it works pretty well. It's certainly safer than just globbing some &|^ operator cruft all through the code, and definitely more readable. With a couple of exceptions (mainly tweaked comments) it's straight from the code library I use at work.

/*
* bitmask.h
*
* This wrapper provides a checked, typesafe mechanism for
* storing bitmasks. Each bit's value is defined in an enum
* separately, and the enum is provided to the template.
* The storage size of the bitmask can be explicitly set as
* well using template parameters.
*
* Note that this object has literally no overhead versus
* simply writing the bitfield ops by hand in raw code: the
* storage of each instance is minimal and controlled by the
* templated storage type; there are no virtual members and
* therefore no vtabl for the objects; and all operations
* are inlined by the compiler so there is no function call
* overhead for manipulating or checking the bitmask.
*
*/


#pragma once


template
class Bitmask
{
public:
Bitmask(Holder defval = 0) : Bitfield(defval) { }

// Sets all bitmask bits which are set in "flags"
inline void Set(FlagEnum flags)
{ Bitfield |= flags; }

// Clears all bitmask bits which are set in "flags"
inline void Clear(FlagEnum flags)
{ Bitfield &= (~flags); }

// Return true if ANY of the bits set in "flags" are
// also set for the bitmask
inline bool Test(FlagEnum flags) const
{ return ((Bitfield & flags) != 0); }

// Return true only if ALL bits set in "flags" are
// also set for the bitmask
inline bool TestAllFlags(FlagEnum flags) const
{ return ((Bitfield & flags) == flags); }

protected:
Holder Bitfield;
};






Here's a quick sample usage, adapting nobodynews' example from the original thread:
#include "bitmask.h"

enum WindowAppearanceFlags : unsigned
{
WA_FullScreen = 0x001,
WA_ScrollBarX = 0x002,
WA_ScrollBarY = 0x004,
WA_NoResize = 0x008,
WA_NoMinimize = 0x010
};

typedef Bitmask<unsigned, WindowAppearanceFlags> WindowAppearanceBitmask;

void Foo()
{
WindowAppearanceBitmask foomask;
foomask.Set(WA_FullScreen | WA_NoResize);

// Do stuff

if(foomask.Test(WA_NoMinimize))
{
// etc.
}
}





No idea if anyone will find that useful or not, but hey, can't hurt [smile]
Sign in to follow this  


4 Comments


Recommended Comments

Guest Anonymous Poster

Posted


foomask.Set(WA_FullScreen | WA_NoResize);


won't compile without warnings, since 'WA_FullScreen | WS_NoResize' is of type unsigned, not of your enumeration type. But if you accept these kinds of warnings, you're basically accepting the same kind of unsafety as when using the holder data type directly. (Hint: what you need to do is overload | etc. for your enumeration type).

Share this comment


Link to comment
Good catch - that was an oversight in my translation of the example usage.

I personally just use multiple Set() calls, since overloading | for all the dozens of enums in practical use is just annoying.


Also, in the places I use it, combinations of fields usually have specific meanings - so e.g. if I need to test FlagA and FlagB at the same time, there's a good reason why. In that case, I just set up an additional enum constant FlagAB that has the bits set for both A and B. That way I can descriptively refer to the combination, rely on type safety, and don't have to mess with lots of operator overloads. The only downside to that trick is that you have to be careful when shuffling the constants around.

Share this comment


Link to comment
Neat trick, but I've tended to solve the readability of such constructs (often used when checking D3D caps bits) via macros. Yes, I know thats A Bad Thing™, but it works [razz]

Cheers,
Jack

Share this comment


Link to comment
Holy crap. I'm not sure what's more surprising: that I'm referenced in someone's journal or that I actually have been reading that journal off and on for a few weeks.

Edit: Like the code, by the way. I'm definately saving this post for future reference.

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now