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  using underlying_type = std::underlying_type_t<enum_t>;
64 
65 public:
66  // ------------------------------------------------ common operators -----------------------------------------------
67 
68  constexpr flags() noexcept = default;
69 
70  /**
71  @brief Reverse (or logically negotiate) all bits
72  **/
73  constexpr void reverse() noexcept;
74 
75  /**
76  @brief Shift bits to the left
77  @param nShift - num of positions to shift
78  **/
79  constexpr void shift_left(size_t nShift) noexcept;
80 
81  /**
82  @brief Shift bits to the right
83  @param nShift - num of positions to shift
84  **/
85  constexpr void shift_right(size_t nShift) noexcept;
86 
87  constexpr flags operator~() const noexcept;
88 
89  constexpr flags& operator<<=(size_t nShift) noexcept;
90  constexpr flags& operator>>=(size_t nShift) noexcept;
91 
92  constexpr flags operator<<(size_t nShift) const noexcept;
93  constexpr flags operator>>(size_t nShift) const noexcept;
94 
95  // ------------------------------------------------ enum_t operators -----------------------------------------------
96 
97  /**
98  @brief flags object constructor
99  @details Separate method for 1 arg to allow type deduction
100  @param eFlag - flag to add at construction
101  **/
102  constexpr flags(enum_t eFlag) noexcept;
103 
104  /**
105  @brief flags object constructor
106  @tparam args_t... - template parameters pack, all types should be same as enum_t
107  @param flags - flags to add at construction
108  **/
109  template<class... args_t>
110  requires(sizeof...(args_t) >= 2 && are_specific_v<enum_t, args_t...>)
111  constexpr flags(args_t... flags) noexcept;
112 
113  /**
114  @brief Add all the flags specified
115  @tparam args_t... - template parameters pack, all types should be same as enum_t
116  @param flags - flags to add
117  **/
118  template<class... args_t>
119  requires(sizeof...(args_t) >= 1 && are_specific_v<enum_t, args_t...>)
120  constexpr void add(args_t... flags) noexcept;
121 
122  /**
123  @brief Remove all the flags specified
124  @tparam args_t... - template parameters pack, all types should be same as enum_t
125  @param flags - flags to remove
126  **/
127  template<class... args_t>
128  requires(sizeof...(args_t) >= 1 && are_specific_v<enum_t, args_t...>)
129  constexpr void remove(args_t... flags) noexcept;
130 
131  /**
132  @brief Apply a bitwise XOR to a flags value
133  @tparam args_t... - template parameters pack, all types should be same as enum_t
134  @param flags - flags to apply
135  **/
136  template<class... args_t>
137  requires(sizeof...(args_t) >= 1 && are_specific_v<enum_t, args_t...>)
138  constexpr void xor_(args_t... flags) noexcept;
139 
140  constexpr auto operator<=>(enum_t eFlag) const noexcept;
141  constexpr flags& operator=(enum_t eFlag) noexcept;
142 
143  constexpr flags& operator|=(enum_t eFlag) noexcept;
144  constexpr flags& operator&=(enum_t eFlag) noexcept;
145  constexpr flags& operator^=(enum_t eFlag) noexcept;
146 
147  constexpr flags operator|(enum_t eFlag) const noexcept;
148  constexpr flags operator&(enum_t eFlag) const noexcept;
149  constexpr flags operator^(enum_t eFlag) const noexcept;
150 
151  // ------------------------------------------------ flags operators ------------------------------------------------
152 
153  QX_COPYMOVABLE(flags);
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 #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.