13 template<enumeration_c enum_t>
16 m_nEnumFlags = ~m_nEnumFlags;
19 template<enumeration_c enum_t>
22 using bits_type = std::make_unsigned_t<underlying_type>;
23 using shift_type = std::make_unsigned_t<decltype(+m_nEnumFlags)>;
25 if (std::cmp_greater_equal(nShift, std::numeric_limits<bits_type>::digits))
32 static_cast<underlying_type
>(
static_cast<shift_type
>(
static_cast<bits_type
>(m_nEnumFlags)) << nShift);
35 template<enumeration_c enum_t>
38 using bits_type = std::make_unsigned_t<underlying_type>;
39 using shift_type = std::make_unsigned_t<decltype(+m_nEnumFlags)>;
41 if (std::cmp_greater_equal(nShift, std::numeric_limits<bits_type>::digits))
48 static_cast<underlying_type
>(
static_cast<shift_type
>(
static_cast<bits_type
>(m_nEnumFlags)) >> nShift);
51 template<enumeration_c enum_t>
59 template<enumeration_c enum_t>
60 constexpr flags<enum_t>& flags<enum_t>::operator<<=(
size_t nShift) noexcept
66 template<enumeration_c enum_t>
67 constexpr flags<enum_t>& flags<enum_t>::operator>>=(
size_t nShift) noexcept
73 template<enumeration_c enum_t>
74 constexpr flags<enum_t> flags<enum_t>::operator<<(
size_t nShift)
const noexcept
81 template<enumeration_c enum_t>
89 template<enumeration_c enum_t>
94 template<enumeration_c enum_t>
95 template<
class... args_t>
96 requires(
sizeof...(args_t) >= 2 && specific_variadic_args_v<enum_t, args_t...>)
102 template<enumeration_c enum_t>
103 template<
class... args_t>
104 requires(
sizeof...(args_t) >= 1 && specific_variadic_args_v<enum_t, args_t...>)
107 ((m_nEnumFlags |= underlying_type(flags)), ...);
110 template<enumeration_c enum_t>
111 template<
class... args_t>
112 requires(
sizeof...(args_t) >= 1 && specific_variadic_args_v<enum_t, args_t...>)
115 ((m_nEnumFlags &= ~underlying_type(
flags)), ...);
118 template<enumeration_c enum_t>
119 template<
class... args_t>
120 requires(
sizeof...(args_t) >= 1 && specific_variadic_args_v<enum_t, args_t...>)
123 ((m_nEnumFlags ^= underlying_type(flags)), ...);
126 template<enumeration_c enum_t>
127 constexpr
auto flags<enum_t>::operator<=>(enum_t eFlag)
const noexcept
129 return underlying_type(m_nEnumFlags) <=> underlying_type(eFlag);
132 template<enumeration_c enum_t>
133 constexpr flags<enum_t>& flags<enum_t>::operator=(enum_t eFlag) noexcept
135 m_nEnumFlags = underlying_type(eFlag);
139 template<enumeration_c enum_t>
140 constexpr flags<enum_t>& flags<enum_t>::operator|=(enum_t eFlag) noexcept
146 template<enumeration_c enum_t>
147 constexpr flags<enum_t>& flags<enum_t>::operator&=(enum_t eFlag) noexcept
153 template<enumeration_c enum_t>
154 constexpr flags<enum_t>& flags<enum_t>::operator^=(enum_t eFlag) noexcept
160 template<enumeration_c enum_t>
161 constexpr flags<enum_t> flags<enum_t>::operator|(enum_t eFlag)
const noexcept
163 flags result = *
this;
168 template<enumeration_c enum_t>
169 constexpr flags<enum_t> flags<enum_t>::operator&(enum_t eFlag)
const noexcept
171 flags result = *
this;
176 template<enumeration_c enum_t>
177 constexpr flags<enum_t> flags<enum_t>::operator^(enum_t eFlag)
const noexcept
179 flags result = *
this;
184 template<enumeration_c enum_t>
187 m_nEnumFlags |= flags_.m_nEnumFlags;
190 template<enumeration_c enum_t>
193 m_nEnumFlags &= ~flags_.m_nEnumFlags;
196 template<enumeration_c enum_t>
199 m_nEnumFlags ^= flags_.m_nEnumFlags;
202 template<enumeration_c enum_t>
203 constexpr flags<enum_t>& flags<enum_t>::operator|=(flags flags_) noexcept
209 template<enumeration_c enum_t>
210 constexpr flags<enum_t>& flags<enum_t>::operator&=(flags flags_) noexcept
216 template<enumeration_c enum_t>
217 constexpr flags<enum_t>& flags<enum_t>::operator^=(flags flags_) noexcept
223 template<enumeration_c enum_t>
224 constexpr flags<enum_t> flags<enum_t>::operator|(flags flags_)
const noexcept
226 flags result = *
this;
231 template<enumeration_c enum_t>
232 constexpr flags<enum_t> flags<enum_t>::operator&(flags flags_)
const noexcept
234 flags result = *
this;
239 template<enumeration_c enum_t>
240 constexpr flags<enum_t> flags<enum_t>::operator^(flags flags_)
const noexcept
242 flags result = *
this;
247 template<enumeration_c enum_t>
250 return m_nEnumFlags & underlying_type(eFlag);
253 template<enumeration_c enum_t>
254 template<
class... args_t>
255 requires(
sizeof...(args_t) >= 2 && specific_variadic_args_v<enum_t, args_t...>)
261 template<enumeration_c enum_t>
264 return (m_nEnumFlags & other.m_nEnumFlags) == other.m_nEnumFlags;
267 template<enumeration_c enum_t>
268 template<
class... args_t>
269 requires(
sizeof...(args_t) >= 2 && specific_variadic_args_v<enum_t, args_t...>)
275 template<enumeration_c enum_t>
278 return (m_nEnumFlags & other.m_nEnumFlags) != 0;
281 template<enumeration_c enum_t>
287 template<enumeration_c enum_t>
291 flags.m_nEnumFlags = std::numeric_limits<underlying_type>::max();
Wrapper for enumerations to be used as a list of flags.
constexpr bool contains_all(flags other) const noexcept
Check if all the specified flags are present.
constexpr void remove(flags flags_) noexcept
Remove all the flags specified.
constexpr void shift_left(size_t nShift) noexcept
Shift bits to the left.
constexpr bool contains(enum_t eFlag) const noexcept
Check if flag is present.
constexpr void xor_(flags flags_) noexcept
Apply a bitwise XOR to a flags value.
constexpr bool contains_any(flags other) const noexcept
Check if any of the specified flags is present.
constexpr void add(flags flags_) noexcept
Add all the flags specified.
static constexpr flags all_flags() noexcept
Get a flags with all bits equal 1.
constexpr void reverse() noexcept
Reverse (or logically negotiate) all bits.
constexpr void shift_right(size_t nShift) noexcept
Shift bits to the right.
constexpr underlying_type to_integer() const noexcept
Convert to the corresponding integer value.
requires(same_variadic_args_v< args_t... >) const expr auto coalesce(args_t &&... args)
Coalesce function, C# a ?? b analogue.
Check that tuple type contains T.