#pragma once #include namespace metaforce { template class Flags { public: using MaskType = std::underlying_type_t; // constructors constexpr Flags() noexcept : m_mask(0) {} constexpr Flags(BitType bit) noexcept : m_mask(static_cast(bit)) {} constexpr Flags(Flags const& rhs) noexcept : m_mask(rhs.m_mask) {} constexpr explicit Flags(MaskType flags) noexcept : m_mask(flags) {} [[nodiscard]] constexpr bool IsSet(Flags const bit) const noexcept { return bool(*this & bit); } // relational operators bool operator==(Flags const& rhs) const noexcept { return m_mask == rhs.m_mask; } // logical operator constexpr bool operator!() const noexcept { return !m_mask; } // bitwise operators constexpr Flags operator&(Flags const& rhs) const noexcept { return Flags(m_mask & rhs.m_mask); } constexpr Flags operator|(Flags const& rhs) const noexcept { return Flags(m_mask | rhs.m_mask); } constexpr Flags operator^(Flags const& rhs) const noexcept { return Flags(m_mask ^ rhs.m_mask); } // assignment operators constexpr Flags& operator=(Flags const& rhs) noexcept { m_mask = rhs.m_mask; return *this; } constexpr Flags& operator|=(Flags const& rhs) noexcept { m_mask |= rhs.m_mask; return *this; } constexpr Flags& operator&=(Flags const& rhs) noexcept { m_mask &= rhs.m_mask; return *this; } constexpr Flags& operator^=(Flags const& rhs) noexcept { m_mask ^= rhs.m_mask; return *this; } // cast operators explicit constexpr operator bool() const noexcept { return m_mask != 0; } explicit constexpr operator MaskType() const noexcept { return m_mask; } private: MaskType m_mask; }; } // namespace metaforce