CommonLibSSE (powerof3)
EnumSet.h
Go to the documentation of this file.
1 #pragma once
2 
3 namespace REX
4 {
5  template <
6  class E,
7  class U = std::underlying_type_t<E>>
8  class EnumSet
9  {
10  public:
11  using enum_type = E;
12  using underlying_type = U;
13 
14  static_assert(std::is_enum_v<E>, "EnumSet<E, ...> must be an enum");
15  static_assert(std::is_integral_v<U>, "EnumSet<..., U> must be an integral");
16 
17  constexpr EnumSet() noexcept = default;
18  constexpr EnumSet(const EnumSet&) noexcept = default;
19  constexpr EnumSet(EnumSet&&) noexcept = default;
20 
21  template <class U2> // NOLINTNEXTLINE(google-explicit-constructor)
22  constexpr EnumSet(EnumSet<E, U2> a_rhs) noexcept :
23  _impl(static_cast<U>(a_rhs.get()))
24  {}
25 
26  template <class... Args>
27  constexpr EnumSet(Args... a_values) noexcept
28  requires(std::same_as<Args, E>&&...) :
29  _impl((static_cast<U>(a_values) | ...))
30  {}
31 
32  ~EnumSet() noexcept = default;
33 
34  constexpr EnumSet& operator=(const EnumSet&) noexcept = default;
35  constexpr EnumSet& operator=(EnumSet&&) noexcept = default;
36 
37  template <class U2>
38  constexpr EnumSet& operator=(EnumSet<E, U2> a_rhs) noexcept
39  {
40  _impl = static_cast<U>(a_rhs.get());
41  }
42 
43  constexpr EnumSet& operator=(E a_value) noexcept
44  {
45  _impl = static_cast<U>(a_value);
46  return *this;
47  }
48 
49  public:
50  [[nodiscard]] explicit constexpr operator bool() const noexcept { return _impl != static_cast<U>(0); }
51 
52  [[nodiscard]] constexpr E operator*() const noexcept { return get(); }
53  [[nodiscard]] constexpr E get() const noexcept { return static_cast<E>(_impl); }
54  [[nodiscard]] constexpr U underlying() const noexcept { return _impl; }
55 
56  public:
57  template <class... Args>
58  constexpr EnumSet& set(Args... a_args) noexcept
59  requires(std::same_as<Args, E>&&...)
60  {
61  _impl |= (static_cast<U>(a_args) | ...);
62  return *this;
63  }
64 
65  template <class... Args>
66  constexpr EnumSet& set(bool a_set, Args... a_args) noexcept
67  requires(std::same_as<Args, E>&&...)
68  {
69  if (a_set)
70  _impl |= (static_cast<U>(a_args) | ...);
71  else
72  _impl &= ~(static_cast<U>(a_args) | ...);
73 
74  return *this;
75  }
76 
77  template <class... Args>
78  constexpr EnumSet& reset(Args... a_args) noexcept
79  requires(std::same_as<Args, E>&&...)
80  {
81  _impl &= ~(static_cast<U>(a_args) | ...);
82  return *this;
83  }
84 
85  constexpr EnumSet& reset() noexcept
86  {
87  _impl = 0;
88  return *this;
89  }
90 
91  template <class... Args>
92  [[nodiscard]] constexpr bool any(Args... a_args) const noexcept
93  requires(std::same_as<Args, E>&&...)
94  {
95  return (_impl & (static_cast<U>(a_args) | ...)) != static_cast<U>(0);
96  }
97 
98  template <class... Args>
99  [[nodiscard]] constexpr bool all(Args... a_args) const noexcept
100  requires(std::same_as<Args, E>&&...)
101  {
102  return (_impl & (static_cast<U>(a_args) | ...)) == (static_cast<U>(a_args) | ...);
103  }
104 
105  template <class... Args>
106  [[nodiscard]] constexpr bool none(Args... a_args) const noexcept
107  requires(std::same_as<Args, E>&&...)
108  {
109  return (_impl & (static_cast<U>(a_args) | ...)) == static_cast<U>(0);
110  }
111 
112  public:
113  friend constexpr bool operator==(EnumSet a_lhs, EnumSet a_rhs) noexcept { return a_lhs.underlying() == a_rhs.underlying(); }
114  friend constexpr bool operator==(EnumSet a_lhs, E a_rhs) noexcept { return a_lhs.underlying() == static_cast<U>(a_rhs); }
115  friend constexpr bool operator==(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<U>(a_lhs) == a_rhs.underlying(); }
116 
117  friend constexpr std::strong_ordering operator<=>(EnumSet a_lhs, EnumSet a_rhs) noexcept { return a_lhs.underlying() <=> a_rhs.underlying(); }
118  friend constexpr std::strong_ordering operator<=>(EnumSet a_lhs, E a_rhs) noexcept { return a_lhs.underlying() <=> static_cast<U>(a_rhs); }
119  friend constexpr std::strong_ordering operator<=>(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<U>(a_lhs) <=> a_rhs.underlying(); }
120 
121  friend constexpr EnumSet operator&(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() & a_rhs.underlying()); }
122  friend constexpr EnumSet operator&(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() & static_cast<U>(a_rhs)); }
123  friend constexpr EnumSet operator&(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) & a_rhs.underlying()); }
124 
125  friend constexpr EnumSet& operator&=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs & a_rhs; }
126  friend constexpr EnumSet& operator&=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs & a_rhs; }
127 
128  friend constexpr EnumSet operator|(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() | a_rhs.underlying()); }
129  friend constexpr EnumSet operator|(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() | static_cast<U>(a_rhs)); }
130  friend constexpr EnumSet operator|(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) | a_rhs.underlying()); }
131 
132  friend constexpr EnumSet& operator|=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs | a_rhs; }
133  friend constexpr EnumSet& operator|=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs | a_rhs; }
134 
135  friend constexpr EnumSet operator^(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() ^ a_rhs.underlying()); }
136  friend constexpr EnumSet operator^(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() ^ static_cast<U>(a_rhs)); }
137  friend constexpr EnumSet operator^(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) ^ a_rhs.underlying()); }
138 
139  friend constexpr EnumSet& operator^=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs ^ a_rhs; }
140  friend constexpr EnumSet& operator^=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs ^ a_rhs; }
141 
142  friend constexpr EnumSet operator+(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() + a_rhs.underlying()); }
143  friend constexpr EnumSet operator+(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() + static_cast<U>(a_rhs)); }
144  friend constexpr EnumSet operator+(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) + a_rhs.underlying()); }
145 
146  friend constexpr EnumSet& operator+=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs + a_rhs; }
147  friend constexpr EnumSet& operator+=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs + a_rhs; }
148 
149  friend constexpr EnumSet operator-(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() - a_rhs.underlying()); }
150  friend constexpr EnumSet operator-(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() - static_cast<U>(a_rhs)); }
151  friend constexpr EnumSet operator-(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) - a_rhs.underlying()); }
152 
153  friend constexpr EnumSet& operator-=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs - a_rhs; }
154  friend constexpr EnumSet& operator-=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs - a_rhs; }
155 
156  friend constexpr EnumSet operator<<(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() << a_rhs.underlying()); }
157  friend constexpr EnumSet operator<<(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() << static_cast<U>(a_rhs)); }
158  friend constexpr EnumSet operator<<(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) << a_rhs.underlying()); }
159 
160  friend constexpr EnumSet& operator<<=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs << a_rhs; }
161  friend constexpr EnumSet& operator<<=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs << a_rhs; }
162 
163  friend constexpr EnumSet operator>>(EnumSet a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() >> a_rhs.underlying()); }
164  friend constexpr EnumSet operator>>(EnumSet a_lhs, E a_rhs) noexcept { return static_cast<E>(a_lhs.underlying() >> static_cast<U>(a_rhs)); }
165  friend constexpr EnumSet operator>>(E a_lhs, EnumSet a_rhs) noexcept { return static_cast<E>(static_cast<U>(a_lhs) >> a_rhs.underlying()); }
166 
167  friend constexpr EnumSet& operator>>=(EnumSet& a_lhs, EnumSet a_rhs) noexcept { return a_lhs = a_lhs >> a_rhs; }
168  friend constexpr EnumSet& operator>>=(EnumSet& a_lhs, E a_rhs) noexcept { return a_lhs = a_lhs >> a_rhs; }
169 
170  friend constexpr EnumSet& operator~(EnumSet& a_lhs) noexcept { return a_lhs = ~a_lhs.underlying(); }
171 
172  private:
173  U _impl{ 0 };
174  };
175 
176  template <class... Args>
177  EnumSet(Args...) -> EnumSet<
178  std::common_type_t<Args...>,
179  std::underlying_type_t<
180  std::common_type_t<Args...>>>;
181 }
Definition: EnumSet.h:9
constexpr EnumSet() noexcept=default
constexpr friend std::strong_ordering operator<=>(EnumSet a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:117
constexpr EnumSet & set(bool a_set, Args... a_args) noexcept requires(std
Definition: EnumSet.h:66
constexpr friend EnumSet operator>>(EnumSet a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:163
constexpr friend EnumSet & operator+=(EnumSet &a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:147
constexpr U underlying() const noexcept
Definition: EnumSet.h:54
constexpr friend std::strong_ordering operator<=>(E a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:119
constexpr friend EnumSet operator|(EnumSet a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:129
constexpr friend EnumSet operator|(EnumSet a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:128
constexpr E get() const noexcept
Definition: EnumSet.h:53
constexpr friend EnumSet operator<<(EnumSet a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:156
constexpr friend EnumSet & operator~(EnumSet &a_lhs) noexcept
Definition: EnumSet.h:170
constexpr EnumSet(Args... a_values) noexcept requires(std
Definition: EnumSet.h:27
constexpr EnumSet & operator=(E a_value) noexcept
Definition: EnumSet.h:43
constexpr friend bool operator==(E a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:115
constexpr friend EnumSet operator-(EnumSet a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:149
constexpr EnumSet & reset() noexcept
Definition: EnumSet.h:85
constexpr friend EnumSet operator-(EnumSet a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:150
constexpr friend EnumSet & operator|=(EnumSet &a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:133
constexpr friend EnumSet operator<<(E a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:158
constexpr friend EnumSet operator^(EnumSet a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:135
constexpr friend bool operator==(EnumSet a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:114
constexpr friend EnumSet operator+(E a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:144
constexpr friend EnumSet operator<<(EnumSet a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:157
constexpr friend EnumSet operator>>(E a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:165
constexpr friend EnumSet & operator|=(EnumSet &a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:132
constexpr friend EnumSet & operator<<=(EnumSet &a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:160
constexpr friend EnumSet operator&(EnumSet a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:122
constexpr friend EnumSet operator^(EnumSet a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:136
constexpr friend std::strong_ordering operator<=>(EnumSet a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:118
constexpr friend EnumSet & operator&=(EnumSet &a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:125
constexpr friend EnumSet operator^(E a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:137
constexpr friend EnumSet & operator^=(EnumSet &a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:140
constexpr friend EnumSet operator|(E a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:130
constexpr friend EnumSet operator&(E a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:123
constexpr friend EnumSet & operator^=(EnumSet &a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:139
constexpr EnumSet & reset(Args... a_args) noexcept requires(std
Definition: EnumSet.h:78
U underlying_type
Definition: EnumSet.h:12
constexpr friend EnumSet & operator<<=(EnumSet &a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:161
~EnumSet() noexcept=default
constexpr friend EnumSet & operator+=(EnumSet &a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:146
constexpr friend EnumSet operator&(EnumSet a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:121
constexpr bool none(Args... a_args) const noexcept requires(std
Definition: EnumSet.h:106
constexpr bool all(Args... a_args) const noexcept requires(std
Definition: EnumSet.h:99
constexpr friend EnumSet & operator>>=(EnumSet &a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:167
constexpr friend EnumSet operator+(EnumSet a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:142
constexpr friend EnumSet & operator-=(EnumSet &a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:153
constexpr friend EnumSet operator>>(EnumSet a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:164
constexpr friend EnumSet & operator-=(EnumSet &a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:154
constexpr bool any(Args... a_args) const noexcept requires(std
Definition: EnumSet.h:92
constexpr friend bool operator==(EnumSet a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:113
constexpr EnumSet & set(Args... a_args) noexcept requires(std
Definition: EnumSet.h:58
constexpr friend EnumSet & operator>>=(EnumSet &a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:168
constexpr E operator*() const noexcept
Definition: EnumSet.h:52
constexpr friend EnumSet operator+(EnumSet a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:143
E enum_type
Definition: EnumSet.h:11
constexpr friend EnumSet & operator&=(EnumSet &a_lhs, E a_rhs) noexcept
Definition: EnumSet.h:126
constexpr friend EnumSet operator-(E a_lhs, EnumSet a_rhs) noexcept
Definition: EnumSet.h:151
Definition: BSDirectInputManager.h:8
EnumSet(Args...) -> EnumSet< std::common_type_t< Args... >, std::underlying_type_t< std::common_type_t< Args... >>>
requires(std::invocable< std::remove_reference_t< EF >>) class scope_exit
Definition: PCH.h:153