R&D · C++ Templates · Bit Manipulation

Bitmask Class

Bitmask Class

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.

C++ Templates Variadic Constructors Operator Overloads Enum Safety Zero Overhead
What I Built
  • 3-parameter templateMaskType (storage int), OpType (input type for operations), TMax (compile-time bit ceiling); 3 orthogonal parameters give full type and bounds safety with zero overhead.
  • Variadic constructor — N-bit fold — accepts any number of bit positions via 1 variadic fold expression; BitMaskBase(1, 4, 7) sets 3 bits in a single constructor call.
  • 6-operator set|, &, |=, &=, ^=, and implicit bool conversion; all 6 operators implemented with zero runtime cost over raw integer operations.
  • Enummask specialisation — 1-param derivationEnummask<TEnum, MaskType> derives TMax from 1 convention: static_cast<int>(TEnum::MAX); enum values map directly to bit indices.
  • 2 debug utilitiesCountSetBits() (popcount) and toBinaryString() (zero-padded binary); both operate in O(TMax) with 0 heap allocation.

BitMaskBase Template

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.

BitMask.h — BitMaskBase
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; }
};
Enummask — Enum-Safe Specialisation

By convention the enum ends with a MAX value. Enummask uses its cast integer as TMax, preventing any out-of-range bit from compiling.

BitMask.h — Enummask specialisation + usage
// 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)
Language C++17 Template params MaskType · OpType · TMax Specialisation Enummask<TEnum, MaskType> Key features Variadic ctor · Operator overloads · CountSetBits · toBinaryString Category R&D · Systems Programming Source github.com/khaled71612000 ↗
Connect