17 template <
integral_or_enum ENUM, detail::val
id_
integral VALUE_TYPE =
unsigned long long>
18 struct enum_flag_changes;
20 constexpr inline struct all_flags_t {} all_flags;
21 constexpr inline struct no_flags_t {} no_flags;
49 template <
integral_or_enum ENUM, detail::val
id_
integral VALUE_TYPE =
unsigned long long>
71 template <
typename...
ARGS>
117 while (
n--) { b ^= (VALUE_TYPE{ 1 } << std::countr_zero(b)); }
118 return static_cast<ENUM>(std::countr_zero(b));
126 template <
typename T,
typename...
ARGS>
147 template <
typename...
ARGS>
165 template <std::convertible_to<ENUM>... ARGS>
173 template <std::convertible_to<ENUM>... ARGS>
181 template <std::convertible_to<ENUM>... ARGS>
187 template <std::convertible_to<ENUM>... ARGS>
223 template <std::convertible_to<ENUM>... ARGS>
225 template <std::convertible_to<ENUM>... ARGS>
231 constexpr self_type& operator+=(self_type
flags)
noexcept { bits |=
flags.bits;
return *
this; }
232 constexpr self_type& operator-=(self_type
flags)
noexcept { bits &=
~flags.bits;
return *
this; }
234 constexpr auto operator<=>(enum_flags
const&
other)
const noexcept =
default;
239 using bitset_type = std::make_unsigned_t<self_type::value_type>;
241 using difference_type =
int;
243 using pointer_type =
void;
244 using reference =
void;
245 using iterator_category = std::forward_iterator_tag;
250 const auto bitset =
static_cast<bitset_type
>(bits);
251#pragma warning(suppress: 4146)
257 const auto bitset =
static_cast<bitset_type
>(bits);
258#pragma warning(suppress: 4146)
264 iterator operator++(
int)
noexcept {
const auto result = *
this; operator++();
return result; }
266 auto operator<=>(iterator
const&
other)
const noexcept =
default;
271 iterator cbegin()
const noexcept {
return iterator{ bits }; }
275 constexpr void clear()
noexcept { bits = 0; }
283 template <
typename FUNC>
286 using return_type = std::invoke_result_t<FUNC, enum_type>;
287 using bitset_type = std::make_unsigned_t<value_type>;
288 auto bitset =
static_cast<bitset_type
>(bits);
291#pragma warning(suppress: 4146)
293 const auto r = std::countr_zero(
t);
294 if constexpr (std::is_convertible_v<return_type, bool>)
302 if constexpr (std::is_convertible_v<return_type, bool>)
303 return return_type{};
308 constexpr void apply(flag_changes
changes)
noexcept
322 constexpr self_type operator+(flag_changes
changes)
const noexcept
330 template <
typename TYPE>
331 struct is_enum_flags : std::false_type {};
333 template <
typename ENUM,
typename VALUE_TYPE>
334 struct is_enum_flags<enum_flags<
ENUM, VALUE_TYPE>> : std::true_type {};
336 template <
typename TYPE>
337 constexpr bool is_enum_flags_v = is_enum_flags<TYPE>::value;
339 enum class enum_flag_change :
uint8_t
347 template <
integral_or_enum ENUM, detail::val
id_
integral VALUE_TYPE>
348 struct enum_flag_changes
351 using value_type = VALUE_TYPE;
354 using enum_type =
ENUM;
355 using self_type = enum_flag_changes;
357 using flags_type = enum_flags<ENUM, VALUE_TYPE>;
367 template <std::convertible_to<ENUM>... ARGS>
369 static constexpr self_type to_set(flags_type
other)
noexcept {
return self_type{
other, 0 }; }
370 template <std::convertible_to<ENUM>... ARGS>
372 static constexpr self_type to_unset(flags_type
other)
noexcept {
return self_type{ 0,
other }; }
373 template <std::convertible_to<ENUM>... ARGS>
375 static constexpr self_type to_toggle(flags_type
other)
noexcept {
return self_type{
other,
other }; }
377 template <std::convertible_to<ENUM>... ARGS>
378 constexpr self_type& set_change_of(enum_flag_change
change,
ARGS...
args)
noexcept
382 case enum_flag_change::no_change:
return dont_change(
args...);
383 case enum_flag_change::set:
return set(
args...);
384 case enum_flag_change::unset:
return unset(
args...);
385 case enum_flag_change::toggle:
return toggle(
args...);
387#if defined(__cpp_lib_unreachable) && __cpp_lib_unreachable >= 202202L
392 constexpr enum_flag_change change_of(enum_type flag)
const noexcept
394 return static_cast<enum_flag_change
>(bits[0].is_set(flag) * 1 + bits[1].is_set(flag) * 2);
397 template <std::convertible_to<ENUM>... ARGS>
398 constexpr self_type& set(
ARGS...
args)
noexcept { bits[0].set(
args...); bits[1].unset(
args...);
return *
this; }
399 constexpr self_type& set(flags_type
other)
noexcept { bits[0].set(
other); bits[1].unset(
other);
return *
this; }
401 template <std::convertible_to<ENUM>... ARGS>
402 constexpr self_type& unset(
ARGS...
args)
noexcept { bits[0].unset(
args...); bits[1].set(
args...);
return *
this; }
403 constexpr self_type& unset(flags_type
other)
noexcept { bits[0].unset(
other); bits[1].set(
other);
return *
this; }
405 template <std::convertible_to<ENUM>... ARGS>
406 constexpr self_type& toggle(
ARGS...
args)
noexcept { bits[0].set(
args...); bits[1].set(
args...);
return *
this; }
407 constexpr self_type& toggle(flags_type
other)
noexcept { bits[0].set(
other); bits[1].set(
other);
return *
this; }
409 template <std::convertible_to<ENUM>... ARGS>
410 constexpr self_type& dont_change(
ARGS...
args)
noexcept { bits[0].unset(
args...); bits[1].unset(
args...);
return *
this; }
411 constexpr self_type& dont_change(flags_type
other)
noexcept { bits[0].unset(
other); bits[1].unset(
other);
return *
this; }
413 constexpr self_type& dont_change_any()
noexcept { bits[0].clear(); bits[1].clear();
return *
this; }
415 constexpr auto operator<=>(self_type
const&
other)
const noexcept =
default;
417 flags_type bits[2]{ {}, {} };
421 constexpr enum_flag_changes(flags_type
b0, flags_type
b1)
noexcept
constexpr auto bit_count
Equal to the number of bits in the type.
constexpr RESULT_TYPE flag_bits(ARGS... args) noexcept
Takes a list of enum values that represent bit numbers (not actual bit values) and returns a value wi...
Primary namespace for everything in this library.
A (constexpr) value struct that represents a set of bits mapped to an enum (implemented as a bitset)
constexpr self_type but_only(self_type flags) const noexcept
Returns a value with our bits from only the flags that are also set in flags (an intersection)
constexpr self_type & unset(self_type other) noexcept
Unsets the flags in the other set.
static constexpr self_type none() noexcept
Returns a value with none of the bits set.
EF_NODISCARD static EF_CONSTEXPR self_type from_bits(value_type val) EF_NOEXCEPT
Creates the enum_flags set from the given underlying bits.
constexpr self_type & set_to(bool val, self_type other) noexcept
Sets the flags in the other set to val
constexpr bool is_set(enum_type flag) const noexcept
Returns whether or not flag is set.
static constexpr self_type from_bits(value_type val) noexcept
Creates the enum_flags set from the given underlying bits.
constexpr self_type & toggle(self_type other) noexcept
Toggles the flags in the other set.
constexpr self_type & unset(ARGS... args) noexcept
TODO: insert() as an alias for set()
constexpr bool contains(enum_type flag) const noexcept
Same as is_set.
constexpr bool contains_all_of(self_type other) const noexcept
Returns whether or not all of the flags in the other set are set.
constexpr bool full() const noexcept
Returns whether *this == all()
constexpr ENUM first_set() const noexcept
Returns the lowest numerical value in the set. Returns an unspecified value if no values are in the s...
constexpr bool contains_any_of(T arg, ARGS... args) const noexcept
Returns whether or not any of the given flags are set.
constexpr self_type & set(ARGS... args) noexcept
Sets the given flags.
constexpr bool contains_all_of(ARGS... args) const noexcept
Returns whether or not all of the given flags are set.
constexpr ENUM nth_set(size_t n) const noexcept
Returns the value of the nth set bit in the set.
constexpr enum_flags(enum_type base_value, ARGS... args) noexcept
Constructs the value with all the given flags set.
constexpr self_type intersected_with(self_type flags) const noexcept
Returns a value with our bits from only the flags that are also set in flags (an intersection)
constexpr self_type & toggle(ARGS... args) noexcept
TODO: erase() as an alias for unset()
constexpr auto for_each(FUNC &&callback) const
Calls callback for each enum flag in the set.
constexpr self_type & set(self_type other) noexcept
Sets the flags in the other
static constexpr self_type all(enum_type last) noexcept
Returns a value with all bits set, up to and including the last
constexpr bool contains_any_of(self_type other) const noexcept
Returns whether or not any of the flags in the other set are set.
constexpr bool contain(enum_type flag) const noexcept
Same as is_set.
constexpr int count() const noexcept
Returns the number of flags set.
static constexpr self_type all() noexcept
Returns a value with all bits set (including the ones not in the enum, if any)
ENUM_TYPE enum_type
Type of the enum that is the source of the flags.
EF_NODISCARD EF_CONSTEXPR bool is_set(enum_type flag) const EF_NOEXCEPT
Returns whether or not flag is set.
constexpr bool are_any_set() const noexcept
Returns whether or not any of the given flags are set.
constexpr self_type & set_to(bool val, ARGS... args) noexcept
Sets the given flags to val
VALUE_TYPE value_type
The underlying integral value type that holds the bits representing the flags.
constexpr enum_type to_enum_type() const noexcept
Returns the underlying value representing this set cast to the enum_type.