#pragma once #if !defined(MIJIN_UTIL_FLAG_HPP_INCLUDED) #define MIJIN_UTIL_FLAG_HPP_INCLUDED 1 #include #include "./traits.hpp" #include "./types.hpp" #include "../internal/common.hpp" namespace mijin { // // public defines // #define MIJIN_DEFINE_FLAG(name) \ struct name : mijin::Flag \ { \ private: \ struct Proxy_ { \ uint8_t value; \ }; \ public: \ constexpr name() = default; \ constexpr name(const name&) = default; \ constexpr name(Proxy_ proxy) MIJIN_NOEXCEPT \ : Flag(proxy.value) {} \ constexpr explicit name(bool value) MIJIN_NOEXCEPT \ : Flag(value) {} \ name& operator=(const name&) = default; \ static constexpr Proxy_ YES{1}; \ static constexpr Proxy_ NO{0}; \ } // // public constants // // // public types // struct Flag { std::uint8_t value; Flag() = default; Flag(const Flag&) = default; explicit constexpr Flag(uint8_t value) MIJIN_NOEXCEPT : value(value) {} Flag& operator=(const Flag&) = default; constexpr bool operator ==(const Flag& other) const MIJIN_NOEXCEPT { return value == other.value; } constexpr bool operator !=(const Flag& other) const MIJIN_NOEXCEPT { return value != other.value; } constexpr bool operator !() const MIJIN_NOEXCEPT { return !value; } constexpr operator bool() const MIJIN_NOEXCEPT { return value != 0; } }; template concept FlagType = requires (T& value) { value = T::YES; value = T::NO; }; namespace impl { template class FlagSetStorage; template class FlagSetStorage : public FlagSetStorage { private: using base_t = FlagSetStorage; static constexpr typename base_t::data_t BIT = (1 << offset); public: constexpr void set(TFirst value) MIJIN_NOEXCEPT { if (value) { base_t::data_ |= BIT; } else { base_t::data_ &= ~BIT; } } constexpr bool get(TFirst) MIJIN_NOEXCEPT { return (base_t::data_ & BIT) != 0; } }; template class FlagSetStorage { protected: using data_t = uint_next_t; protected: data_t data_ = data_t(0); }; } // namespace impl template class FlagSet { private: using storage_t = impl::FlagSetStorage<0, TFlags...>; private: storage_t storage_; public: FlagSet() = default; FlagSet(const FlagSet&) = default; template constexpr FlagSet(TFlags2... flags) { (set(flags), ...); } public: FlagSet& operator=(const FlagSet&) = default; template requires is_any_type_v FlagSet& operator=(T flag) MIJIN_NOEXCEPT { reset(flag); return *this; } template requires is_any_type_v FlagSet& operator|=(T flag) MIJIN_NOEXCEPT { set(flag); return *this; } template requires is_any_type_v FlagSet& operator&=(T flag) MIJIN_NOEXCEPT { unset(flag); } }; // // public functions // } // namespace mijin #endif // !defined(MIJIN_UTIL_FLAG_HPP_INCLUDED)