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