Flags

Flags provides a type-safe wrapper around enum values that allows you to easily perform bitwise operations without explicit casting to integers. This makes working with bit flags more convenient and less error-prone.

Basic usage

When using raw C++ enums, combining flags requires cumbersome casting:

enum class MyFlag
{
	Flag1 = 1 << 0,
	Flag2 = 1 << 1,
	Flag3 = 1 << 2
};

// Cumbersome casting required
MyFlag combined = (MyFlag)((u32)MyFlag::Flag1 | (u32)MyFlag::Flag2);

With Flags, this becomes much simpler. To create a Flags type for an enum, define a typedef with your enum type as the template parameter, then use the B3D_FLAGS_OPERATORS macro to define all necessary operators:

enum class MyFlag
{
	Flag1 = 1 << 0,
	Flag2 = 1 << 1,
	Flag3 = 1 << 2
};

typedef Flags<MyFlag> MyFlags;
B3D_FLAGS_OPERATORS(MyFlag)

Now you can use the flags naturally:

MyFlags combined = MyFlag::Flag1 | MyFlag::Flag2;

Operations

Flags supports all standard bitwise operations:

// Combining flags
MyFlags flags = MyFlag::Flag1 | MyFlag::Flag2;

// Adding more flags
flags |= MyFlag::Flag3;

// Removing flags
flags &= ~MyFlag::Flag1;

// Checking if specific flags are set
if(flags & MyFlag::Flag2)
{
	// Flag2 is set
}

// XOR operation
MyFlags toggled = flags ^ MyFlag::Flag3;

Checking flag status

The Flags class provides several methods for checking flag status:

MyFlags flags = MyFlag::Flag1 | MyFlag::Flag2;

// Check if all specified flags are set
bool hasAllFlags = flags.IsSet(MyFlag::Flag1 | MyFlag::Flag2); // true
bool hasFlag3 = flags.IsSet(MyFlag::Flag3); // false

// Check if any of the specified flags are set
bool hasAnyFlag = flags.IsSetAny(MyFlag::Flag1 | MyFlag::Flag3); // true (Flag1 is set)

// Check using another Flags object
MyFlags testFlags = MyFlag::Flag2 | MyFlag::Flag3;
bool hasAnyTestFlag = flags.IsSetAny(testFlags); // true (Flag2 is set)
bool hasAllTestFlags = flags.IsSetAll(testFlags); // false (Flag3 is not set)

Setting and unsetting flags

MyFlags flags = MyFlag::Flag1;

// Set additional flags
flags.Set(MyFlag::Flag2);
flags.Set(MyFlag::Flag3);

// Unset specific flags
flags.Unset(MyFlag::Flag1);

// Now flags contains only Flag2 and Flag3

Comparison

Flags supports equality comparison:

MyFlags flags1 = MyFlag::Flag1 | MyFlag::Flag2;
MyFlags flags2 = MyFlag::Flag1 | MyFlag::Flag2;
MyFlags flags3 = MyFlag::Flag1;

bool areEqual = (flags1 == flags2); // true
bool areDifferent = (flags1 != flags3); // true

// Can also compare with individual enum values
bool isSingleFlag = (flags3 == MyFlag::Flag1); // true

Custom storage type

By default, Flags uses u32 for storage. You can specify a different storage type if needed:

enum class LargeFlag : u64
{
	Flag1 = 1ULL << 0,
	Flag2 = 1ULL << 32,
	Flag3 = 1ULL << 63
};

typedef Flags<LargeFlag, u64> LargeFlags;
B3D_FLAGS_OPERATORS(LargeFlag)

LargeFlags flags = LargeFlag::Flag1 | LargeFlag::Flag2;