qxLib
flags.h
Go to the documentation of this file.
1 /**
2 
3  @file flags.h
4  @author Khrapov
5  @date 01.10.2023
6  @copyright (c) Nick Khrapov, 2023. All right reserved.
7 
8 **/
9 #pragma once
10 
12 #include <qx/meta/concepts.h>
13 #include <qx/meta/type_traits.h>
14 
15 #include <limits>
16 #include <type_traits>
17 #include <utility>
18 
19 /**
20  @def QX_FLAGS_ENUM_CLASS
21  @brief Define to let to use this enum class in different binary operations returning qx::flags
22  @param enumName - enum class name
23 **/
24 #define QX_FLAGS_ENUM_CLASS(enumName) \
25  inline qx::flags<enumName> operator|(enumName left, enumName right) \
26  { \
27  return qx::flags(left) | right; \
28  } \
29  inline qx::flags<enumName> operator&(enumName left, enumName right) \
30  { \
31  return qx::flags(left) & right; \
32  } \
33  inline qx::flags<enumName> operator^(enumName left, enumName right) \
34  { \
35  return qx::flags(left) ^ right; \
36  }
37 
38 namespace qx
39 {
40 
41 /**
42 
43  @class flags
44  @brief Wrapper for enumerations to be used as a list of flags
45  @tparam enum_t - enum flags type
46  @code
47 
48  enum class EFlags
49  {
50  None = 0,
51  First = 1 << 0,
52  Second = 1 << 1,
53  Third = 1 << 2,
54  Fourth = 1 << 3,
55  };
56 
57  qx::flags<EFlags> flags;
58 
59  @endcode
60 
61 **/
62 template<enumeration_c enum_t>
63 class flags
64 {
65  QX_COPYMOVABLE(flags);
66 
67 public:
68  using underlying_type = std::underlying_type_t<enum_t>;
69 
70  // ------------------------------------------------ common operators -----------------------------------------------
71 
72  constexpr flags() noexcept = default;
73 
74  /**
75  @brief Reverse (or logically negotiate) all bits
76  **/
77  constexpr void reverse() noexcept;
78 
79  /**
80  @brief Shift bits to the left
81  @details Shifts at or beyond the underlying bit width clear all flags.
82  @param nShift - num of positions to shift
83  **/
84  constexpr void shift_left(size_t nShift) noexcept;
85 
86  /**
87  @brief Shift bits to the right
88  @details Logical shift; shifts at or beyond the underlying bit width clear all flags.
89  @param nShift - num of positions to shift
90  **/
91  constexpr void shift_right(size_t nShift) noexcept;
92 
93  constexpr flags operator~() const noexcept;
94 
95  constexpr flags& operator<<=(size_t nShift) noexcept;
96  constexpr flags& operator>>=(size_t nShift) noexcept;
97 
98  constexpr flags operator<<(size_t nShift) const noexcept;
99  constexpr flags operator>>(size_t nShift) const noexcept;
100 
101  // ------------------------------------------------ enum_t operators -----------------------------------------------
102 
103  /**
104  @brief flags object constructor
105  @details Separate method for 1 arg to allow type deduction
106  @param eFlag - flag to add at construction
107  **/
108  constexpr flags(enum_t eFlag) noexcept;
109 
110  /**
111  @brief flags object constructor
112  @tparam args_t... - template parameters pack, all types should be same as enum_t
113  @param flags - flags to add at construction
114  **/
115  template<class... args_t>
116  requires(sizeof...(args_t) >= 2 && specific_variadic_args_v<enum_t, args_t...>)
117  constexpr flags(args_t... flags) noexcept;
118 
119  /**
120  @brief Add all the flags specified
121  @tparam args_t... - template parameters pack, all types should be same as enum_t
122  @param flags - flags to add
123  **/
124  template<class... args_t>
125  requires(sizeof...(args_t) >= 1 && specific_variadic_args_v<enum_t, args_t...>)
126  constexpr void add(args_t... flags) noexcept;
127 
128  /**
129  @brief Remove all the flags specified
130  @tparam args_t... - template parameters pack, all types should be same as enum_t
131  @param flags - flags to remove
132  **/
133  template<class... args_t>
134  requires(sizeof...(args_t) >= 1 && specific_variadic_args_v<enum_t, args_t...>)
135  constexpr void remove(args_t... flags) noexcept;
136 
137  /**
138  @brief Apply a bitwise XOR to a flags value
139  @tparam args_t... - template parameters pack, all types should be same as enum_t
140  @param flags - flags to apply
141  **/
142  template<class... args_t>
143  requires(sizeof...(args_t) >= 1 && specific_variadic_args_v<enum_t, args_t...>)
144  constexpr void xor_(args_t... flags) noexcept;
145 
146  constexpr auto operator<=>(enum_t eFlag) const noexcept;
147  constexpr flags& operator=(enum_t eFlag) noexcept;
148 
149  constexpr flags& operator|=(enum_t eFlag) noexcept;
150  constexpr flags& operator&=(enum_t eFlag) noexcept;
151  constexpr flags& operator^=(enum_t eFlag) noexcept;
152 
153  constexpr flags operator|(enum_t eFlag) const noexcept;
154  constexpr flags operator&(enum_t eFlag) const noexcept;
155  constexpr flags operator^(enum_t eFlag) const noexcept;
156 
157  // ------------------------------------------------ flags operators ------------------------------------------------
158 
159  /**
160  @brief Add all the flags specified
161  @param flags_ - flags to add
162  **/
163  constexpr void add(flags flags_) noexcept;
164 
165  /**
166  @brief Remove all the flags specified
167  @param flags_ - flags to remove
168  **/
169  constexpr void remove(flags flags_) noexcept;
170 
171  /**
172  @brief Apply a bitwise XOR to a flags value
173  @param flags_ - flags to apply
174  **/
175  constexpr void xor_(flags flags_) noexcept;
176 
177  constexpr auto operator<=>(const flags&) const noexcept = default;
178 
179  constexpr flags& operator|=(flags flags_) noexcept;
180  constexpr flags& operator&=(flags flags_) noexcept;
181  constexpr flags& operator^=(flags flags_) noexcept;
182 
183  constexpr flags operator|(flags flags_) const noexcept;
184  constexpr flags operator&(flags flags_) const noexcept;
185  constexpr flags operator^(flags flags_) const noexcept;
186 
187  // --------------------------------------------------- algorithms --------------------------------------------------
188 
189  /**
190  @brief Check if flag is present
191  @param eFlag - flag to check
192  @retval - true if flag is present
193  **/
194  constexpr bool contains(enum_t eFlag) const noexcept;
195 
196  /**
197  @brief Check if all the specified flags are present
198  @tparam args_t... - template parameters pack, all types should be same as enum_t
199  @param flags - flags to check
200  @retval true if all the specified flags are present
201  **/
202  template<class... args_t>
203  requires(sizeof...(args_t) >= 2 && specific_variadic_args_v<enum_t, args_t...>)
204  constexpr bool contains_all(args_t... flags) const noexcept;
205 
206  /**
207  @brief Check if all the specified flags are present
208  @param other - flags to check
209  @retval - true if all the specified flags are present
210  **/
211  constexpr bool contains_all(flags other) const noexcept;
212 
213  /**
214  @brief Check if any of the specified flags is present
215  @tparam args_t... - template parameters pack, all types should be same as enum_t
216  @param flags - flags to check
217  @retval - true if any of the specified flags is present
218  **/
219  template<class... args_t>
220  requires(sizeof...(args_t) >= 2 && specific_variadic_args_v<enum_t, args_t...>)
221  constexpr bool contains_any(args_t... flags) const noexcept;
222 
223  /**
224  @brief Check if any of the specified flags is present
225  @param other - flags to check
226  @retval - true if any of the specified flags is present
227  **/
228  constexpr bool contains_any(flags other) const noexcept;
229 
230  /**
231  @brief Convert to the corresponding integer value
232  @retval - integer value
233  **/
234  constexpr underlying_type to_integer() const noexcept;
235 
236  /**
237  @brief Get a flags with all bits equal 1
238  @retval - flags with all bits equal 1
239  **/
240  static constexpr flags all_flags() noexcept;
241 
242 private:
243  underlying_type m_nEnumFlags = 0;
244 };
245 
246 } // namespace qx
247 
248 template<qx::enumeration_c enum_t>
249 struct std::hash<qx::flags<enum_t>>
250 {
251  size_t operator()(const qx::flags<enum_t>& eFlags) const noexcept
252  {
253  return std::hash<typename qx::flags<enum_t>::underlying_type>()(eFlags.to_integer());
254  }
255 };
256 
257 #include <qx/containers/flags.inl>
Wrapper for enumerations to be used as a list of flags.
Definition: flags.h:64
requires(sizeof...(args_t) >=1 &&specific_variadic_args_v< enum_t, args_t... >) const expr void xor_(args_t... flags) noexcept
Apply a bitwise XOR to a flags value.
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.
requires(sizeof...(args_t) >=2 &&specific_variadic_args_v< enum_t, args_t... >) const expr flags(args_t... flags) noexcept
flags object constructor
constexpr void xor_(flags flags_) noexcept
Apply a bitwise XOR to a flags value.
requires(sizeof...(args_t) >=1 &&specific_variadic_args_v< enum_t, args_t... >) const expr void add(args_t... flags) noexcept
Add all the flags specified.
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
requires(sizeof...(args_t) >=2 &&specific_variadic_args_v< enum_t, args_t... >) const expr bool contains_any(args_t... flags) const noexcept
Check if any of the specified flags is present.
requires(sizeof...(args_t) >=2 &&specific_variadic_args_v< enum_t, args_t... >) const expr bool contains_all(args_t... flags) const noexcept
Check if all the specified flags are present.
requires(sizeof...(args_t) >=1 &&specific_variadic_args_v< enum_t, args_t... >) const expr void remove(args_t... flags) noexcept
Remove all the flags specified.
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.