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