opynsim
Unofficial C++ Documentation
Loading...
Searching...
No Matches
flags.h
Go to the documentation of this file.
1#pragma once
2
3#include <bit>
4#include <cstddef>
5#include <functional>
6#include <initializer_list>
7#include <type_traits>
8
9namespace osc
10{
11 // a helper class that stores `OR` combinations of flag-like enum values
12 //
13 // note, the templated enum class must:
14 //
15 // - have a `None` member that is equal to zero (i.e. `std::to_underlying(None) == 0`)
16 // - store the flags densely, with no gaps
17 // - have a `NUM_FLAGS` member that contains the count of densely-stored flags (e.g. 1<<(NUM_FLAGS-1) is the highest flag)
18 template<typename TEnum>
19 requires std::is_enum_v<TEnum>
20 class Flags final {
21 public:
22 using underlying_type = std::underlying_type_t<TEnum>;
23
25 {
26 return Flags{v};
27 }
28
29 constexpr Flags() = default;
30 constexpr Flags(TEnum flag) : value_{static_cast<underlying_type>(flag)} {}
31 constexpr Flags(std::initializer_list<TEnum> flags)
32 {
33 for (TEnum flag : flags) {
34 value_ |= static_cast<underlying_type>(flag);
35 }
36 }
37
38 constexpr bool operator!() const
39 {
40 return !static_cast<bool>(*this);
41 }
42
43 explicit constexpr operator bool () const
44 {
45 return value_ != 0;
46 }
47
48 friend constexpr bool operator==(const Flags&, const Flags&) = default;
49
50 friend constexpr Flags operator&(const Flags& lhs, const Flags& rhs)
51 {
52 return Flags{static_cast<underlying_type>(lhs.value_ & rhs.value_)};
53 }
54
55 friend constexpr Flags operator|(const Flags& lhs, const Flags& rhs)
56 {
57 return Flags{static_cast<underlying_type>(lhs.value_ | rhs.value_)};
58 }
59
60 constexpr Flags& operator|=(const Flags& rhs)
61 {
62 value_ |= rhs.value_;
63 return *this;
64 }
65
66 constexpr TEnum lowest_set() const
67 {
68 if (value_ != 0) {
69 const auto unsigned_val = static_cast<std::make_unsigned_t<underlying_type>>(value_);
70 return static_cast<TEnum>(underlying_type{1} << std::countr_zero(unsigned_val));
71 }
72 return static_cast<TEnum>(underlying_type{0});
73 }
74
75 constexpr Flags with(TEnum flag) const
76 {
77 return Flags{static_cast<underlying_type>(value_ | static_cast<underlying_type>(flag))};
78 }
79
80 constexpr Flags without(TEnum flag) const
81 {
82 return Flags{static_cast<underlying_type>(value_ & ~static_cast<underlying_type>(flag))};
83 }
84
85 constexpr bool get(TEnum flag) const
86 {
87 return static_cast<bool>(*this & flag);
88 }
89
90 constexpr void set(TEnum flag, bool v)
91 {
92 *this = v ? this->with(flag) : this->without(flag);
93 }
94
96 {
97 Flags copy{*this};
98 copy = (*this & flag0) ? copy.with(flag1) : copy.without(flag1);
99 copy = (*this & flag1) ? copy.with(flag0) : copy.without(flag0);
100 return copy;
101 }
102
104 {
105 return value_;
106 }
107
108 private:
109 explicit constexpr Flags(underlying_type value) : value_{value} {}
110
111 underlying_type value_{};
112 };
113
114 template<class TEnum>
115 requires std::is_enum_v<TEnum>
116 constexpr auto to_underlying(const Flags<TEnum>& e) noexcept
117 {
118 return e.underlying_value();
119 }
120}
121
122template<typename T>
123struct std::hash<osc::Flags<T>> final {
124 size_t operator()(const osc::Flags<T>& flags) const noexcept
125 {
126 return inner_hasher_(flags.underlying_value());
127 }
128private:
129 std::hash<typename osc::Flags<T>::underlying_type> inner_hasher_{};
130};
Definition flags.h:20
constexpr Flags with(TEnum flag) const
Definition flags.h:75
constexpr bool operator!() const
Definition flags.h:38
constexpr Flags & operator|=(const Flags &rhs)
Definition flags.h:60
std::underlying_type_t< TEnum > underlying_type
Definition flags.h:22
static constexpr Flags from_underlying(underlying_type v)
Definition flags.h:24
constexpr bool get(TEnum flag) const
Definition flags.h:85
constexpr Flags(TEnum flag)
Definition flags.h:30
constexpr TEnum lowest_set() const
Definition flags.h:66
constexpr Flags(std::initializer_list< TEnum > flags)
Definition flags.h:31
constexpr underlying_type underlying_value() const
Definition flags.h:103
constexpr Flags with_flag_values_swapped(TEnum flag0, TEnum flag1) const
Definition flags.h:95
constexpr void set(TEnum flag, bool v)
Definition flags.h:90
constexpr Flags()=default
constexpr Flags without(TEnum flag) const
Definition flags.h:80
friend constexpr Flags operator&(const Flags &lhs, const Flags &rhs)
Definition flags.h:50
friend constexpr Flags operator|(const Flags &lhs, const Flags &rhs)
Definition flags.h:55
friend constexpr bool operator==(const Flags &, const Flags &)=default
Definition custom_decoration_generator.h:5
constexpr auto to_underlying(const Flags< TEnum > &e) noexcept
Definition flags.h:116
constexpr U to(T &&value)
Definition conversion.h:56
size_t operator()(const osc::Flags< T > &flags) const noexcept
Definition flags.h:124