#pragma once #include namespace cru { template struct Bitmask final { using Underlying = TUnderlying; constexpr Bitmask() : value(0) {} constexpr explicit Bitmask(TUnderlying value) : value(value) {} static constexpr Bitmask FromOffset(int offset) { return Bitmask(static_cast(1u << offset)); } constexpr bool Has(Bitmask rhs) const { return (value & rhs.value) != 0; } Bitmask operator|(Bitmask rhs) const { return Bitmask(value | rhs.value); } Bitmask operator&(Bitmask rhs) const { return Bitmask(value & rhs.value); } Bitmask operator^(Bitmask rhs) const { return Bitmask(value ^ rhs.value); } Bitmask operator~() const { return Bitmask(~value); } Bitmask& operator|=(Bitmask rhs) { value |= rhs.value; return *this; } Bitmask& operator&=(Bitmask rhs) { value &= rhs.value; return *this; } Bitmask& operator^=(Bitmask rhs) { value ^= rhs.value; return *this; } bool operator==(Bitmask rhs) const { return this->value == rhs.value; } bool operator!=(Bitmask rhs) const { return this->value != rhs.value; } explicit operator TUnderlying() const { return value; } operator bool() const { return value != 0; } TUnderlying value; }; } // namespace cru namespace std { template struct hash> { using Bitmask = cru::Bitmask; std::size_t operator()(Bitmask bitmask) const { return std::hash{}(bitmask.value); } }; } // namespace std