
A production-grade C++ bitmask template library. BitMaskBase<MaskType, OpType, TMax> provides a fully type-safe, variadic-constructor bitmask with operator overloads and a debug toBinaryString(). The Enummask specialisation derives TMax from TEnum::MAX, giving zero-overhead enum-flag sets without manual bit counting.
MaskType (storage int), OpType (input type for operations), TMax (compile-time bit ceiling); 3 orthogonal parameters give full type and bounds safety with zero overhead.BitMaskBase(1, 4, 7) sets 3 bits in a single constructor call.|, &, |=, &=, ^=, and implicit bool conversion; all 6 operators implemented with zero runtime cost over raw integer operations.Enummask<TEnum, MaskType> derives TMax from 1 convention: static_cast<int>(TEnum::MAX); enum values map directly to bit indices.CountSetBits() (popcount) and toBinaryString() (zero-padded binary); both operate in O(TMax) with 0 heap allocation.
The core class. Variadic fold expression in the constructor means BitMaskBase<uint32, int, 32>(1, 4, 7) sets bits 1, 4, and 7 with a single constructor call.
template<typename MaskType, typename OpType, int TMax>
class BitMaskBase
{
public:
MaskType Value = 0;
// Variadic constructor: BitMaskBase(1, 4, 7) sets bits 1, 4, 7
template<typename... Bits>
explicit BitMaskBase(Bits... bits)
{ ((SetBit(static_cast<OpType>(bits))), ...); }
void SetBit (OpType Bit) { Value |= (MaskType(1) << static_cast<int>(Bit)); }
void ClearBit (OpType Bit) { Value &= ~(MaskType(1) << static_cast<int>(Bit)); }
void ToggleBit(OpType Bit) { Value ^= (MaskType(1) << static_cast<int>(Bit)); }
bool TestBit (OpType Bit) const
{ return (Value & (MaskType(1) << static_cast<int>(Bit))) != 0; }
int CountSetBits() const {
MaskType v = Value; int c = 0;
while (v) { c += v & 1; v >>= 1; }
return c;
}
std::string toBinaryString() const {
std::string s;
for (int i = TMax - 1; i >= 0; --i)
s += (TestBit(static_cast<OpType>(i))) ? '1' : '0';
return s;
}
// Operator overloads
BitMaskBase operator|(const BitMaskBase& o) const { BitMaskBase r; r.Value = Value | o.Value; return r; }
BitMaskBase operator&(const BitMaskBase& o) const { BitMaskBase r; r.Value = Value & o.Value; return r; }
explicit operator bool() const { return Value != 0; }
};
By convention the enum ends with a MAX value. Enummask uses its cast integer as TMax, preventing any out-of-range bit from compiling.
// Enummask: TMax derived automatically from TEnum::MAX
template<typename TEnum, typename MaskType = uint32>
using Enummask = BitMaskBase<MaskType, TEnum,
static_cast<int>(TEnum::MAX)>;
// Example usage —————————————————————————————
enum class EAbilityFlag : uint8 {
CanJump = 0, CanSprint = 1, CanDodge = 2, CanAttack = 3, MAX
};
Enummask<EAbilityFlag> Abilities(EAbilityFlag::CanJump, EAbilityFlag::CanAttack);
// Test a specific flag — zero overhead at runtime
if (Abilities.TestBit(EAbilityFlag::CanAttack))
ExecuteAttack();
Abilities.ToggleBit(EAbilityFlag::CanSprint);
UE_LOG(LogTemp, Log, TEXT("Ability flags: %s"),
*FString(Abilities.toBinaryString().c_str()));
// Output: "0101" (CanJump + CanAttack set, index 0 and 3)