qxLib
flags.inl
Go to the documentation of this file.
1 /**
2 
3  @file flags.inl
4  @author Khrapov
5  @date 29.09.2023
6  @copyright (c) Nick Khrapov, 2023. All right reserved.
7 
8 **/
9 
10 namespace qx
11 {
12 
13 template<enumeration_c enum_t>
14 constexpr void flags<enum_t>::reverse() noexcept
15 {
16  m_nEnumFlags = ~m_nEnumFlags;
17 }
18 
19 template<enumeration_c enum_t>
20 constexpr void flags<enum_t>::shift_left(size_t nShift) noexcept
21 {
22  using bits_type = std::make_unsigned_t<underlying_type>;
23  using shift_type = std::make_unsigned_t<decltype(+m_nEnumFlags)>;
24 
25  if (std::cmp_greater_equal(nShift, std::numeric_limits<bits_type>::digits))
26  {
27  m_nEnumFlags = 0;
28  return;
29  }
30 
31  m_nEnumFlags =
32  static_cast<underlying_type>(static_cast<shift_type>(static_cast<bits_type>(m_nEnumFlags)) << nShift);
33 }
34 
35 template<enumeration_c enum_t>
36 constexpr void flags<enum_t>::shift_right(size_t nShift) noexcept
37 {
38  using bits_type = std::make_unsigned_t<underlying_type>;
39  using shift_type = std::make_unsigned_t<decltype(+m_nEnumFlags)>;
40 
41  if (std::cmp_greater_equal(nShift, std::numeric_limits<bits_type>::digits))
42  {
43  m_nEnumFlags = 0;
44  return;
45  }
46 
47  m_nEnumFlags =
48  static_cast<underlying_type>(static_cast<shift_type>(static_cast<bits_type>(m_nEnumFlags)) >> nShift);
49 }
50 
51 template<enumeration_c enum_t>
52 constexpr flags<enum_t> flags<enum_t>::operator~() const noexcept
53 {
54  flags result = *this;
55  result.reverse();
56  return result;
57 }
58 
59 template<enumeration_c enum_t>
60 constexpr flags<enum_t>& flags<enum_t>::operator<<=(size_t nShift) noexcept
61 {
62  shift_left(nShift);
63  return *this;
64 }
65 
66 template<enumeration_c enum_t>
67 constexpr flags<enum_t>& flags<enum_t>::operator>>=(size_t nShift) noexcept
68 {
69  shift_right(nShift);
70  return *this;
71 }
72 
73 template<enumeration_c enum_t>
74 constexpr flags<enum_t> flags<enum_t>::operator<<(size_t nShift) const noexcept
75 {
76  flags result = *this;
77  result <<= nShift;
78  return result;
79 }
80 
81 template<enumeration_c enum_t>
82 constexpr flags<enum_t> flags<enum_t>::operator>>(size_t nShift) const noexcept
83 {
84  flags result = *this;
85  result >>= nShift;
86  return result;
87 }
88 
89 template<enumeration_c enum_t>
90 constexpr flags<enum_t>::flags(enum_t eFlag) noexcept : m_nEnumFlags(underlying_type(eFlag))
91 {
92 }
93 
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...>)
97 constexpr flags<enum_t>::flags(args_t... flags) noexcept
98 {
99  add(flags...);
100 }
101 
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...>)
105 constexpr void flags<enum_t>::add(args_t... flags) noexcept
106 {
107  ((m_nEnumFlags |= underlying_type(flags)), ...);
108 }
109 
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...>)
113 constexpr void flags<enum_t>::remove(args_t... flags) noexcept
114 {
115  ((m_nEnumFlags &= ~underlying_type(flags)), ...);
116 }
117 
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...>)
121 constexpr void flags<enum_t>::xor_(args_t... flags) noexcept
122 {
123  ((m_nEnumFlags ^= underlying_type(flags)), ...);
124 }
125 
126 template<enumeration_c enum_t>
127 constexpr auto flags<enum_t>::operator<=>(enum_t eFlag) const noexcept
128 {
129  return underlying_type(m_nEnumFlags) <=> underlying_type(eFlag);
130 }
131 
132 template<enumeration_c enum_t>
133 constexpr flags<enum_t>& flags<enum_t>::operator=(enum_t eFlag) noexcept
134 {
135  m_nEnumFlags = underlying_type(eFlag);
136  return *this;
137 }
138 
139 template<enumeration_c enum_t>
140 constexpr flags<enum_t>& flags<enum_t>::operator|=(enum_t eFlag) noexcept
141 {
142  add(eFlag);
143  return *this;
144 }
145 
146 template<enumeration_c enum_t>
147 constexpr flags<enum_t>& flags<enum_t>::operator&=(enum_t eFlag) noexcept
148 {
149  remove(eFlag);
150  return *this;
151 }
152 
153 template<enumeration_c enum_t>
154 constexpr flags<enum_t>& flags<enum_t>::operator^=(enum_t eFlag) noexcept
155 {
156  xor_(eFlag);
157  return *this;
158 }
159 
160 template<enumeration_c enum_t>
161 constexpr flags<enum_t> flags<enum_t>::operator|(enum_t eFlag) const noexcept
162 {
163  flags result = *this;
164  result |= eFlag;
165  return result;
166 }
167 
168 template<enumeration_c enum_t>
169 constexpr flags<enum_t> flags<enum_t>::operator&(enum_t eFlag) const noexcept
170 {
171  flags result = *this;
172  result &= eFlag;
173  return result;
174 }
175 
176 template<enumeration_c enum_t>
177 constexpr flags<enum_t> flags<enum_t>::operator^(enum_t eFlag) const noexcept
178 {
179  flags result = *this;
180  result ^= eFlag;
181  return result;
182 }
183 
184 template<enumeration_c enum_t>
185 constexpr void flags<enum_t>::add(flags flags_) noexcept
186 {
187  m_nEnumFlags |= flags_.m_nEnumFlags;
188 }
189 
190 template<enumeration_c enum_t>
191 constexpr void flags<enum_t>::remove(flags flags_) noexcept
192 {
193  m_nEnumFlags &= ~flags_.m_nEnumFlags;
194 }
195 
196 template<enumeration_c enum_t>
197 constexpr void flags<enum_t>::xor_(flags flags_) noexcept
198 {
199  m_nEnumFlags ^= flags_.m_nEnumFlags;
200 }
201 
202 template<enumeration_c enum_t>
203 constexpr flags<enum_t>& flags<enum_t>::operator|=(flags flags_) noexcept
204 {
205  add(flags_);
206  return *this;
207 }
208 
209 template<enumeration_c enum_t>
210 constexpr flags<enum_t>& flags<enum_t>::operator&=(flags flags_) noexcept
211 {
212  remove(flags_);
213  return *this;
214 }
215 
216 template<enumeration_c enum_t>
217 constexpr flags<enum_t>& flags<enum_t>::operator^=(flags flags_) noexcept
218 {
219  xor_(flags_);
220  return *this;
221 }
222 
223 template<enumeration_c enum_t>
224 constexpr flags<enum_t> flags<enum_t>::operator|(flags flags_) const noexcept
225 {
226  flags result = *this;
227  result |= flags_;
228  return result;
229 }
230 
231 template<enumeration_c enum_t>
232 constexpr flags<enum_t> flags<enum_t>::operator&(flags flags_) const noexcept
233 {
234  flags result = *this;
235  result &= flags_;
236  return result;
237 }
238 
239 template<enumeration_c enum_t>
240 constexpr flags<enum_t> flags<enum_t>::operator^(flags flags_) const noexcept
241 {
242  flags result = *this;
243  result ^= flags_;
244  return result;
245 }
246 
247 template<enumeration_c enum_t>
248 constexpr bool flags<enum_t>::contains(enum_t eFlag) const noexcept
249 {
250  return m_nEnumFlags & underlying_type(eFlag);
251 }
252 
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...>)
256 constexpr bool flags<enum_t>::contains_all(args_t... flags) const noexcept
257 {
258  return (contains(flags) && ...);
259 }
260 
261 template<enumeration_c enum_t>
262 constexpr bool flags<enum_t>::contains_all(flags other) const noexcept
263 {
264  return (m_nEnumFlags & other.m_nEnumFlags) == other.m_nEnumFlags;
265 }
266 
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...>)
270 constexpr bool flags<enum_t>::contains_any(args_t... flags) const noexcept
271 {
272  return (contains(flags) || ...);
273 }
274 
275 template<enumeration_c enum_t>
276 constexpr bool flags<enum_t>::contains_any(flags other) const noexcept
277 {
278  return (m_nEnumFlags & other.m_nEnumFlags) != 0;
279 }
280 
281 template<enumeration_c enum_t>
282 constexpr typename flags<enum_t>::underlying_type flags<enum_t>::to_integer() const noexcept
283 {
284  return m_nEnumFlags;
285 }
286 
287 template<enumeration_c enum_t>
288 constexpr flags<enum_t> flags<enum_t>::all_flags() noexcept
289 {
290  flags flags;
291  flags.m_nEnumFlags = std::numeric_limits<underlying_type>::max();
292  return flags;
293 }
294 
295 } // namespace qx
Wrapper for enumerations to be used as a list of flags.
Definition: flags.h:64
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.
Definition: flags.inl:20
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.
Definition: flags.inl:14
constexpr void shift_right(size_t nShift) noexcept
Shift bits to the right.
Definition: flags.inl:36
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.
Definition: coalesce.inl:57
Check that tuple type contains T.