ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
bitwise.hpp
Go to the documentation of this file.
1/** ************************************************************************************************
2 * \file
3 * This header file is part of module \alib_enums of the \aliblong.
4 *
5 * \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
6 * Published under \ref mainpage_license "Boost Software License".
7 **************************************************************************************************/
8#ifndef HPP_ALIB_ENUMS_BITWISE
9#define HPP_ALIB_ENUMS_BITWISE 1
10
11#if !defined(HPP_ALIB) && !defined(ALIB_DOX)
12# include "alib/alib.hpp"
13#endif
14
16
17#if !defined(HPP_ALIB_ENUMS_ARITHMETICAL)
19#endif
20
21#if !defined (HPP_ALIB_ENUMS_UNDERLYING_INTEGRAL)
23#endif
24
25#if !defined(HPP_ALIB_LANG_BITS)
26# include "alib/lang/bits.hpp"
27#endif
28
29namespace alib {
30
31/**
32 * This is the reference documentation of sub-namespace \c enums of the \aliblink, which
33 * holds types of library module \alib_enums_nl.
34 *
35 * Extensive documentation for this module is provided with
36 * \ref alib_mod_enums "ALib Module Enums - Programmer's Manual".
37 *
38 * \attention
39 * All operators are declared in the global namespace, other than this
40 * namespace documentation indicates!
41 */
42namespace enums {
43
44// #################################################################################################
45// struct T_EnumIsBitwise
46// #################################################################################################
47#if defined(ALIB_DOX)
48/** ************************************************************************************************
49 * Simple TMP struct that inherits <c>std::false_type</c> by default. If specialized for an
50 * enumeration type \p{TEnum} to inherit <c>std::true_type</c>, the following operators set of
51 * \alib operators become applicable to elements of \p{TEnum}:
52 *
53 * - \alib{enums::bitwise;operator&}
54 * - \alib{enums::bitwise;operator&=}
55 * - \alib{enums::bitwise;operator|}
56 * - \alib{enums::bitwise;operator|=}
57 * - \alib{enums::bitwise;operator^}
58 * - \alib{enums::bitwise;operator^=}
59 * - \alib{enums::bitwise;operator~}
60 * - \alib{enums::bitwise;operator+} (Alias for \alib{enums::bitwise;operator|})
61 * - \alib{enums::bitwise;operator-} (Alias for a combination of operators
62 * \alib{enums::bitwise;operator&} and \alib{enums::bitwise;operator~})
63 * - \alib{enums::bitwise;operator+=} (An alias for \alib{enums::bitwise;operator|=})
64 * - \alib{enums::bitwise;operator-=} (Removes given bit(s) )
65 *
66 * \attention
67 * Likewise with the operators introduced with TMP struct \alib{enums;T_EnumIsArithmetical},
68 * this documentation "fakes" the operators into namespace <c>alib::enums</c>,
69 * while in fact they are defined in the global namespace!<br>
70 * See \ref alib_enums_arithmetic_standard "corresponding note" in the Programmer's Manual
71 * for details.
72 *
73 * <b>Restrictions</b><br>
74 * For technical reasons, this concept is not applicable to enum types that are defined as
75 * \c private or \c protected inner types of structs or classes.
76 *
77 * \see
78 * - Macro \ref ALIB_ENUMS_MAKE_BITWISE, which specializes this TMP struct for a given
79 * enumeration type.
80 * - For details and a source code sample see chapter \ref alib_enums_arithmetic_bitwise
81 * of the Programmer's Manual of module \alib_enums.
82 *
83 * @tparam TEnum The enum type to enable arithmetical operators for.
84 * @tparam TEnableIf This parameter has a default expressions and <b>must not</b> be provided
85 * with specializations of this struct.
86 * It is used to ensure that template parameter \p{TEnum} is an enumeration type.
87 *
88* \I{#############################################################################################}
89 * # Restrictions #
90 * For technical reasons, this concept is not applicable to enum types that are defined as
91 * \c private or \c protected inner types of structs or classes.
92 *
93 * # Reference Documentation #
94 *
95 * @tparam TEnum The enum type to enable bitwise operators for.
96 * @tparam TEnableIf This parameter has a default expressions and <b>must not</b> be provided
97 * with specializations of this struct.
98 * It is used to ensure that template parameter \p{TEnum} is an enumeration type.
99 **************************************************************************************************/
100template<typename TEnum, typename TEnableIf>
101struct T_EnumIsBitwise : public std::false_type {};
102#else
103template<typename TEnum,
104 typename TEnableIf= typename std::enable_if<std::is_enum<TEnum>::value>::type>
105struct T_EnumIsBitwise : public std::false_type {};
106#endif
107
108} // namespace alib[::enums]
109
110/// Type alias in namespace \b alib.
111template<typename TEnum>
113
114} // namespace [alib]
115
116// #################################################################################################
117// Helper Macros
118// #################################################################################################
119
120#define ALIB_ENUMS_MAKE_BITWISE(TEnum) \
121namespace alib::enums { \
122template<> \
123struct T_EnumIsBitwise<TEnum> : public std::true_type {}; }
124
125
126
127// #################################################################################################
128// Bitwise Operators
129// #################################################################################################
130
131// For documentation, all operators and enum related template functions are faked into namespace
132// alib::enums
133#if defined(ALIB_DOX)
134namespace alib { namespace enums {
135/**
136 * Operators available to elements of enumerations if \alib{enums;T_EnumIsBitwise} is
137 * specialized.
138 *
139 * \note
140 * This namespace exits only in the documentation to collect the operators.
141 * When parsed by a C++ compiler, <b>the operators reside in the global namespace</b> and
142 * functions \alib{enums::bitwise;HasBits}, \alib{enums::bitwise;CountElements},
143 * \alib{enums::bitwise;ToBitwiseEnumeration} and \alib{enums::bitwise;ToSequentialEnumeration}
144 * reside in namespace \ref alib.
145 *
146 * As required, when parsed by a C++ compiler, the operators reside in the global namespace.
147 */
148namespace bitwise {
149
150#endif
151
152
153/**
154 * Bitwise \b and operator useable with scoped enum types.
155 *
156 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
157 * template enum type \p{TEnum} to inherit \c std::true_type.
158 *
159 * @tparam TEnum Enumeration type.
160 * @param lhs First operand.
161 * @param rhs Second operand.
162 * @return The result of a bitwise and operation of the underlying enum values.
163 */
164template<typename TEnum>
165constexpr
166#if defined(ALIB_DOX)
167TEnum
168#else
169typename std::enable_if<alib::enums::T_EnumIsBitwise<TEnum>::value, TEnum>::type
170#endif
171operator& (TEnum lhs, TEnum rhs) noexcept(true)
172{
173 using TBits= typename std::underlying_type<TEnum>::type;
174 return TEnum(TBits(lhs) & TBits(rhs));
175}
176
177/**
178 * Bitwise assignment operator useable with scoped enum types.
179 *
180 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
181 * template enum type \p{TEnum} to inherit \c std::true_type.
182 *
183 * @tparam TEnum Enumeration type.
184 * @param[in,out] lhs Reference to the first operand. Receives the result.
185 * @param rhs Second operand.
186 * @return The new value of \p{lhs} which is set to <c>lhs & rhs</c>.
187 */
188template<typename TEnum>
189constexpr
190#if defined(ALIB_DOX)
191TEnum
192#else
193typename std::enable_if<alib::enums::T_EnumIsBitwise<TEnum>::value, TEnum>::type
194#endif
195operator&= (TEnum& lhs, TEnum rhs) noexcept(true)
196{
197 using TBits= typename std::underlying_type<TEnum>::type;
198 return lhs= TEnum( TBits(lhs) & TBits(rhs) );
199}
200
201/**
202 * Bitwise \b or operator useable with scoped enum types.
203 *
204 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
205 * template enum type \p{TEnum} to inherit \c std::true_type.
206 *
207 * @tparam TEnum Enumeration type.
208 * @param lhs First operand.
209 * @param rhs Second operand.
210 * @return The result of a bitwise or operation of the underlying enum values.
211 */
212template<typename TEnum>
213constexpr
214#if defined(ALIB_DOX)
215TEnum
216#else
217typename std::enable_if<alib::enums::T_EnumIsBitwise<TEnum>::value, TEnum>::type
218#endif
219operator| (TEnum lhs, TEnum rhs) noexcept(true)
220{
221 using TBits= typename std::underlying_type<TEnum>::type;
222 return TEnum(TBits(lhs) | TBits(rhs));
223}
224
225/**
226 * Bitwise <b>or assignment</b> operator useable with scoped enum types.
227 *
228 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
229 * template enum type \p{TEnum} to inherit \c std::true_type.
230 *
231 * @tparam TEnum Enumeration type.
232 * @param[in,out] lhs Reference to the first operand. Receives the result.
233 * @param rhs Second operand.
234 * @return The new value of \p{lhs} which is set to <c>lhs | rhs</c>.
235 */
236template<typename TEnum>
237constexpr
238#if defined(ALIB_DOX)
239bool
240#else
241typename std::enable_if<alib::enums::T_EnumIsBitwise<TEnum>::value, TEnum>::type
242#endif
243operator|= (TEnum& lhs, TEnum rhs) noexcept(true)
244{
245 using TBits= typename std::underlying_type<TEnum>::type;
246 return lhs= TEnum( TBits(lhs) | TBits(rhs) );
247}
248
249/**
250 * Bitwise \b xor operator useable with scoped enum types.
251 *
252 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
253 * template enum type \p{TEnum} to inherit \c std::true_type.
254 *
255 * @tparam TEnum Enumeration type.
256 * @param lhs First operand.
257 * @param rhs Second operand.
258 * @return The result of a bitwise xor operation of the underlying enum values.
259 */
260template<typename TEnum>
261constexpr
262#if defined(ALIB_DOX)
263TEnum
264#else
265typename std::enable_if<alib::enums::T_EnumIsBitwise<TEnum>::value, TEnum>::type
266#endif
267operator^ (TEnum lhs, TEnum rhs) noexcept(true)
268{
269 using TBits= typename std::underlying_type<TEnum>::type;
270 return TEnum(TBits(lhs) ^ TBits(rhs));
271}
272
273/**
274 * Bitwise <b>xor assignment</b> operator useable with scoped enum types.
275 *
276 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
277 * template enum type \p{TEnum} to inherit \c std::true_type.
278 *
279 * @tparam TEnum Enumeration type.
280 * @param[in,out] lhs Reference to the first operand. Receives the result.
281 * @param rhs Second operand.
282 * @return The new value of \p{lhs} which is set to <c>lhs ^ rhs</c>.
283 */
284template<typename TEnum>
285constexpr
286#if defined(ALIB_DOX)
287TEnum
288#else
289typename std::enable_if<alib::enums::T_EnumIsBitwise<TEnum>::value, TEnum>::type
290#endif
291operator^= (TEnum& lhs, TEnum rhs) noexcept(true)
292{
293 using TBits= typename std::underlying_type<TEnum>::type;
294 return lhs= TEnum( TBits(lhs) ^ TBits(rhs) );
295}
296
297/**
298 * Bitwise \b not operator useable with scoped enum types.
299 *
300 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
301 * template enum type \p{TEnum} to inherit \c std::true_type.
302 *
303 * \note To remove one or more bits from a scoped enum value, operator <b>&=</b> with this operator
304 * applied to \p{op} can be used.
305 * A shortcut to this is given with \ref operator-=.
306 *
307 * @tparam TEnum Enumeration type.
308 * @param op The operand to be negated.
309 * @return The result of a bitwise negation of \p{op}.
310 */
311template<typename TEnum>
312constexpr
313#if defined(ALIB_DOX)
314TEnum
315#else
316typename std::enable_if<alib::enums::T_EnumIsBitwise<TEnum>::value, TEnum>::type
317#endif
318operator~ (TEnum op) noexcept(true)
319{
320 using TBits= typename std::underlying_type<TEnum>::type;
321 return TEnum( ~ TBits(op) );
322}
323
324
325/**
326 * Alias to bitwise \b or operator useable with scoped enum types.
327 *
328 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
329 * template enum type \p{TEnum} to inherit \c std::true_type and if \alib{enums;T_EnumIsArithmetical}
330 * is \b not specialized to inherit \c std::true_type. The latter is to avoid ambiguities in
331 * situations where an enum is both, arithmetical and bitwise.
332 *
333 * @tparam TEnum Enumeration type.
334 * @param lhs First operand.
335 * @param rhs Second operand.
336 * @return The result of a bitwise or operation of the underlying enum values.
337 */
338template<typename TEnum>
339constexpr
340#if defined(ALIB_DOX)
341TEnum
342#else
343typename std::enable_if< alib::enums::T_EnumIsBitwise <TEnum>::value
345#endif
346operator+ (TEnum lhs, TEnum rhs) noexcept(true)
347{
348 using TBits= typename std::underlying_type<TEnum>::type;
349 return TEnum(TBits(lhs) | TBits(rhs));
350}
351
352/**
353 * Alias for bitwise <b>or assignment</b> operator useable with scoped enum types.
354 *
355 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
356 * template enum type \p{TEnum} to inherit \c std::true_type and if \alib{enums;T_EnumIsArithmetical}
357 * is \b not specialized to inherit \c std::true_type. The latter is to avoid ambiguities in
358 * situations where an enum is both, arithmetical and bitwise.
359 *
360 * @tparam TEnum Enumeration type.
361 * @param[in,out] lhs Reference to the first operand. Receives the result.
362 * @param rhs Second operand.
363 * @return The new value of \p{lhs} which is set to <c>lhs | rhs</c>.
364 */
365template<typename TEnum>
366constexpr
367#if defined(ALIB_DOX)
368TEnum
369#else
370typename std::enable_if< alib::enums::T_EnumIsBitwise <TEnum>::value
372#endif
373operator+= (TEnum& lhs, TEnum rhs) noexcept(true)
374{
375 using TBits= typename std::underlying_type<TEnum>::type;
376 return lhs= TEnum( TBits(lhs) | TBits(rhs) );
377}
378
379/**
380 * Removes bit(s) found in \p{rhs} from \p{lhs} an returns result. This is a shortcut to:
381 *
382 * lhs & !rhs
383 *
384 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
385 * template enum type \p{TEnum} to inherit \c std::true_type and if \alib{enums;T_EnumIsArithmetical}
386 * is \b not specialized to inherit \c std::true_type. The latter is to avoid ambiguities in
387 * situations where an enum is both, arithmetical and bitwise.
388 *
389 * @tparam TEnum Enumeration type.
390 * @param lhs First operand.
391 * @param rhs Second operand.
392 * @return The result of <c>lhs & !rhs</c>.
393 */
394template<typename TEnum>
395constexpr
396#if defined(ALIB_DOX)
397TEnum
398#else
399typename std::enable_if< alib::enums::T_EnumIsBitwise <TEnum>::value
401#endif
402operator- (TEnum lhs, TEnum rhs) noexcept(true)
403{
404 using TBits= typename std::underlying_type<TEnum>::type;
405 return TEnum( TBits(lhs) & (~TBits(rhs)) );
406}
407
408/**
409 * Removes bit(s) found in \p{rhs} from \p{lhs}. This is a shortcut to:
410 *
411 * lhs &= !rhs
412 *
413 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
414 * template enum type \p{TEnum} to inherit \c std::true_type and if \alib{enums;T_EnumIsArithmetical}
415 * is \b not specialized to inherit \c std::true_type. The latter is to avoid ambiguities in
416 * situations where an enum is both, arithmetical and bitwise.
417 *
418 * @tparam TEnum Enumeration type.
419 * @param[in,out] lhs Reference to the first operand. Receives the result.
420 * @param rhs Second operand.
421 * @return The new value of \p{lhs} which is set to <c>lhs & ( ~rhs )</c>.
422 */
423template<typename TEnum>
424constexpr
425#if defined(ALIB_DOX)
426TEnum
427#else
428typename std::enable_if< alib::enums::T_EnumIsBitwise <TEnum>::value
430#endif
431operator-= (TEnum& lhs, TEnum rhs) noexcept(true)
432{
433 using TBits= typename std::underlying_type<TEnum>::type;
434 return lhs= TEnum( TBits(lhs) & (~TBits(rhs)) );
435}
436
437#if !defined(ALIB_DOX)
438namespace alib {
439#endif
440
441#if defined(ALIB_DOX)
442/**
443 * Tests if the integral value of the given enum \p{element} contains all bits set in
444 * \p{selection}.
445 * In other words, returns result of:
446 *
447 * ( element & selection ) == selection
448 *
449 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
450 * template enum type \p{TEnum} to inherit \c std::true_type.
451 *
452 * @tparam TEnum Enumeration type. Deduced by the compiler.
453 * @param element Bitset to be tested.
454 * @param selection Second operand.
455 * @return \c true if all bits of \p{selection} are set in \p{element}.
456 */
457template<typename TEnum>
458constexpr
459bool HasBits(TEnum element, TEnum selection) noexcept;
460#else
461template<typename TEnum>
462constexpr
464HasBits(TEnum element, TEnum selection) noexcept
465{
466 using TBits= typename std::underlying_type<TEnum>::type;
467 return ( TBits(element) & TBits(selection) ) == TBits(selection);
468}
469#endif
470
471#if defined(ALIB_DOX)
472/**
473 * Returns the number of bitwise enumeration elements set in the given value.
474 * In other words, the bits given in \p value are counted and the number is returned.
475 *
476 * Selected by the compiler only if \alib{enums;T_EnumIsBitwise} is specialized for
477 * template enum type \p{TEnum} to inherit \c std::true_type.
478 *
479 * @param value A single or composite selection of bits.
480 * @return The result of a call to #alib::lang::BitCount().
481 */
482template<typename TEnum>
483static constexpr
484int CountElements( TEnum value );
485#else
486template<typename TEnum>
487constexpr
489CountElements( TEnum value )
490{
491 return lang::BitCount(UnderlyingIntegral(value));
492}
493#endif
494
495#if defined(ALIB_DOX)
496}}} // doxygen namespace [alib::enums::bitwise]
497#else
498} // namespace [alib]
499#endif
500
501#endif // HPP_ALIB_ENUMS_BITWISE
#define ALIB_ASSERT_MODULE(modulename)
Definition alib.hpp:190
#define ATMP_T_IF(T, Cond)
Definition tmp.hpp:53
constexpr TEnum operator&(TEnum lhs, TEnum rhs) noexcept(true)
Definition bitwise.hpp:171
constexpr TEnum operator-=(TEnum &lhs, TEnum rhs) noexcept(true)
Definition bitwise.hpp:431
constexpr TEnum operator|(TEnum lhs, TEnum rhs) noexcept(true)
Definition bitwise.hpp:219
constexpr bool HasBits(TEnum element, TEnum selection) noexcept
constexpr TEnum operator&=(TEnum &lhs, TEnum rhs) noexcept(true)
Definition bitwise.hpp:195
constexpr TEnum operator^(TEnum lhs, TEnum rhs) noexcept(true)
Definition bitwise.hpp:267
constexpr TEnum operator^=(TEnum &lhs, TEnum rhs) noexcept(true)
Definition bitwise.hpp:291
constexpr TEnum operator+(TEnum lhs, TEnum rhs) noexcept(true)
Definition bitwise.hpp:346
constexpr TEnum operator-(TEnum lhs, TEnum rhs) noexcept(true)
Definition bitwise.hpp:402
static constexpr int CountElements(TEnum value)
constexpr bool operator|=(TEnum &lhs, TEnum rhs) noexcept(true)
Definition bitwise.hpp:243
constexpr TEnum operator+=(TEnum &lhs, TEnum rhs) noexcept(true)
Definition bitwise.hpp:373
constexpr TEnum operator~(TEnum op) noexcept(true)
Definition bitwise.hpp:318
constexpr std::underlying_type< TEnum >::type UnderlyingIntegral(TEnum element) noexcept(true)
constexpr int BitCount(TIntegral value)
Definition alib.cpp:57