ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
iterable.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_ITERABLE
9#define HPP_ALIB_ENUMS_ITERABLE 1
10
11#if !defined (HPP_ALIB_ENUMS_BITWISE)
12# include "alib/enums/bitwise.hpp"
13#endif
14
16
17#if !defined (HPP_ALIB_ENUMS_UNDERLYING_INTEGRAL)
19#endif
20
21#if !defined (_GLIBCXX_CSTDINT) && !defined (_CSTDINT_)
22# include <cstdint>
23#endif
24
25#if !defined (_GLIBCXX_ITERATOR) && !defined (_ITERATOR_)
26# include <iterator>
27#endif
28
29namespace alib { namespace enums {
30
31// #################################################################################################
32// struct T_EnumIsIterable
33// #################################################################################################
34
35
36/** ************************************************************************************************
37 * Simple TMP struct that - if specialized - enables standard and range-based C++ iteration of the
38 * elements of an enumeration.
39 * Specializations have to declare <c>constexpr</c> fields #Begin and #End, as documented with this
40 * type.
41 *
42 * \note
43 * The unspecialized version of this struct is empty.
44 *
45 * If specialized, the following entities become available:
46 * - \alib{enums::iterable;operator+}
47 * - \alib{enums::iterable;operator-}
48 * - struct \alib{enums;EnumIterator}
49 *
50 * \attention
51 * Likewise with the operators introduced with other TMP structs of this module,
52 * this documentation "fakes" the operators into namespace
53 * <c>alib::enums::iterable</c>, while in fact they are defined in the global
54 * namespace!<br>
55 * See \ref alib_enums_arithmetic_standard "corresponding note" in the Programmer's Manual
56 * for details.
57 *
58 * <b>Restrictions</b><br>
59 * For technical reasons, this concept is not applicable to enum types that are defined as
60 * \c private or \c protected inner types of structs or classes.
61 *
62 * \see
63 * - Macros \ref ALIB_ENUMS_MAKE_ITERABLE and \ref ALIB_ENUMS_MAKE_ITERABLE_BEGIN_END, which
64 * specialize this TMP struct for a given enumeration type.
65 * - Type \alib{enums;EnumIterator} used to perform iterations.
66 * - For details and a source code sample see chapter \ref alib_enums_iter "3. Enum Iteration"
67 * of the Programmer's Manual of module \alib_enums.
68 *
69 * @tparam TEnum The enum type to enable iteration for.
70 * @tparam TEnableIf This parameter has a default expressions and <b>must not</b> be provided
71 * with specializations of this struct.
72 * It is used to ensure that template parameter \p{TEnum} is an enumeration type.
73 **************************************************************************************************/
74template<typename TEnum,
75 typename TEnableIf= typename std::enable_if<std::is_enum<TEnum>::value>::type>
76struct T_EnumIsIterable : public std::false_type
77{
78 #if defined(ALIB_DOX)
79 /**
80 * Specializations have to implement this static method to return the first enum element
81 * of the iteration.
82 *
83 * @return The first enumeration element.
84 */
85 static constexpr TEnum Begin;
86 #endif
87
88 #if defined(ALIB_DOX)
89 /**
90 * Specializations have to implement this static method to return the element value after
91 * the last enum element of the iteration.
92 *
93 * @return The element after the last enumeration element.
94 */
95 static constexpr TEnum End;
96 #endif
97
98};
99
100}} // namespace [alib::enums]
101
102// #################################################################################################
103// Helper Macros
104// #################################################################################################
105
106#define ALIB_ENUMS_MAKE_ITERABLE_BEGIN_END(TEnum, StartElement, StopElement ) \
107namespace alib::enums { \
108template<> struct T_EnumIsIterable<TEnum> : std::true_type \
109{ \
110 static constexpr TEnum Begin = StartElement; \
111 static constexpr TEnum End = StopElement; \
112};}
113
114#define ALIB_ENUMS_MAKE_ITERABLE(TEnum, StopElement ) \
115ALIB_ENUMS_MAKE_ITERABLE_BEGIN_END( TEnum, TEnum(0), StopElement )
116
117
118// #################################################################################################
119// Operators for iterable enums
120// #################################################################################################
121
122// For documentation, all operators and enum related template functions are faked into namespace
123// alib::enums
124#if defined(ALIB_DOX)
125namespace alib { namespace enums {
126/**
127 * Operators available to elements of enumerations if \alib{enums;T_EnumIsIterable} is
128 * specialized.
129 *
130 * \note
131 * This namespace exits only in the documentation to collect the operators.
132 * When parsed by a C++ compiler, <b>the operators reside in the global namespace</b>.
133 */
134namespace iterable {
135#endif
136
137#if defined(ALIB_DOX)
138/**
139 * Add operator useable with scoped enum types and integral values.
140 *
141 * Selected by the compiler only if \alib{enums;T_EnumIsIterable} is specialized for
142 * enum type \p{TEnum}.
143 *
144 * @tparam TEnum Enumeration type.
145 * @param element First operand of \p{TEnum} type.
146 * @param addend The addend as of \c int type.
147 * @return The <em>"addend-th"</em> enum element after \p{element} .
148 */
149template<typename TEnum>
150constexpr
151TEnum operator+ (TEnum element, int addend) noexcept(true);
152#else
153template<typename TEnum>
154constexpr
156operator+ (TEnum element, int addend) noexcept(true)
157{
158 return TEnum( alib::UnderlyingIntegral(element) + addend );
159}
160#endif
161
162#if defined(ALIB_DOX)
163/**
164 * Subtract operator useable with scoped enum types and integral values.
165 *
166 * Selected by the compiler only if \alib{enums;T_EnumIsIterable} is specialized for
167 * enum type \p{TEnum}.
168 *
169 * @tparam TEnum Enumeration type.
170 * @param element First operand of \p{TEnum} type.
171 * @param subtrahend The subtrahend as of \c int type.
172 * @return The <em>"subtrahend-th"</em> enum element before \p{element} .
173 */
174template<typename TEnum>
175constexpr
176TEnum operator- (TEnum element, int subtrahend) noexcept(true);
177#else
178
179template<typename TEnum>
180constexpr
182operator- (TEnum element, int subtrahend) noexcept(true)
183{
184 return TEnum( alib::UnderlyingIntegral(element) - subtrahend );
185}
186#endif
187
188
189// Faking all operators and enum related template functions to namespace alib::enums
190#if defined(ALIB_DOX)
191}
192#else
193 namespace alib { namespace enums {
194#endif
195
196
197// #################################################################################################
198// EnumIterator
199// #################################################################################################
200#if defined(ALIB_DOX)
201/** ************************************************************************************************
202 * Implements a \c std::iterator_traits class for scoped and non-scoped enum types.
203 * The documentation is found with TMP struct \alib{enums;T_EnumIsIterable}, which needs to be
204 * specialized for template type \p{TEnum}. For other types, this class is not constructible.
205 *
206 * @tparam TEnum The enum type to iterate over.
207 * @tparam TEnableIf This parameter has a default expressions and <b>must not</b> be provided
208 * with specializations of this struct.
209 * It is used internally to ensure that only if a specialization of
210 * \alib{enums;T_EnumIsIterable;T_EnumIsIterable<TEnum>} exists, this class
211 * is available.
212 **************************************************************************************************/
213template<typename TEnum, typename TEnableIf>
215#else
216template<typename TEnum, typename TEnableIf
218struct EnumIterator
219#endif
220{
221 /** ********************************************************************************************
222 * Default constructor.
223 **********************************************************************************************/
224 EnumIterator()= default;
225
226 /** ********************************************************************************************
227 * Implementation of \c std::iterator_traits for enum type \p{TEnum}. This class exposes
228 * #ConstIterator which uses <c>const TEnum*</c> and <c>const TEnum&</c> as
229 * pointer and reference types.
230 *
231 * As the name of the class indicates, this iterator satisfies the C++ standard library concept
232 * \https{RandomAccessIterator,en.cppreference.com/w/cpp/concept/RandomAccessIterator}.
233 **********************************************************************************************/
234 template<typename TPointer, typename TReference>
236 {
237 using iterator_category = std::random_access_iterator_tag; ///< Implementation of <c>std::iterator_traits</c>.
238 using value_type = TEnum ; ///< Implementation of <c>std::iterator_traits</c>.
239 using difference_type = std::ptrdiff_t ; ///< Implementation of <c>std::iterator_traits</c>.
240 using pointer = TPointer ; ///< Implementation of <c>std::iterator_traits</c>.
241 using reference = TReference ; ///< Implementation of <c>std::iterator_traits</c>.
242
243 protected:
244 /** The actual enum element. */
245 TEnum p;
246
247 /** The underlying integer type. */
248 using TIntegral= typename std::underlying_type<TEnum>::type;
249
250
251 public:
252 /** Constructor.
253 * @param _p Our initial value */
254 constexpr
255 explicit TRandomAccessIterator( TEnum _p = TEnum(0) ) : p(_p)
256 {
257 }
258
259 //###################### To satisfy concept of InputIterator ######################
260
261 /** Prefix increment operator.
262 * @return A reference to ourselves. */
264 {
266 p= p + 1;
267 else
268 p= TEnum( UnderlyingIntegral( p ) << 1 );
269
270 return *this;
271 }
272
273 /** Postfix increment operator.
274 * @return A reference to ourselves. */
276 {
278 return TRandomAccessIterator(p= p + 1);
279 else
280 return TRandomAccessIterator(p= TEnum( UnderlyingIntegral( p ) << 1) );
281 }
282
283 /** Comparison operator.
284 * @param other The iterator to compare ourselves to.
285 * @return \c true if this and given iterator are equal, \c false otherwise. */
286 constexpr
288 {
289 return p == other.p;
290 }
291
292 /** Comparison operator.
293 * @param other The iterator to compare ourselves to.
294 * @return \c true if this and given iterator are not equal, \c false otherwise. */
295 constexpr
297 {
298 return !(*this == other);
299 }
300
301 /** Retrieves the enum element that this iterator references.
302 * @return The enum element. */
303 constexpr
304 TEnum operator*() const
305 {
306 return p;
307 }
308
309
310 //################## To satisfy concept of BidirectionalIterator ##################
311
312 /** Prefix decrement operator.
313 * @return A reference to ourselves. */
315 {
317 p= p + 1;
318 else
319 p= TEnum( );
320 return *this;
321 }
322
323
324 /** Postfix decrement operator.
325 * @return An iterator that with the old value. */
327 {
329 return TRandomAccessIterator(p= p - 1);
330 else
331 return TRandomAccessIterator(p= TEnum( UnderlyingIntegral( p ) >> 1) );
332 }
333
334
335 //################## To satisfy concept of RandomAccessIterator ###################
336
337 /** Addition assignment.
338 * @param n The value to subtract.
339 * @return A reference to ourselves. */
341 {
343 p= p + n;
344 else
345 p= TEnum( UnderlyingIntegral( p ) << n );
346 return *this;
347 }
348
349 /** Subtraction assignment.
350 * @param n The value to subtract.
351 * @return A reference to ourselves. */
353 {
355 p= p - n;
356 else
357 p= TEnum( UnderlyingIntegral( p ) >> n );
358 }
359
360 /** Addition.
361 * @param n The value to subtract.
362 * @return A reference to the new iterator. */
364 {
366 return TRandomAccessIterator( p + n );
367 else
368 return TRandomAccessIterator( TEnum( UnderlyingIntegral( p ) << n ) );
369 }
370
371 /** Subtraction.
372 * @param n The value to subtract.
373 * @return A reference to the new iterator. */
375 {
377 return TRandomAccessIterator( p - n );
378 else
379 return TRandomAccessIterator( TEnum( UnderlyingIntegral( p ) >> n ) );
380 }
381
382 /** Difference (distance) from this iterator to the given one.
383 * @param other The iterator to subtract
384 * @return The iterator to subtract. */
385 std::ptrdiff_t operator-(TRandomAccessIterator other) const
386 {
388 return static_cast<std::ptrdiff_t>(UnderlyingIntegral(p) - UnderlyingIntegral(other.p));
389 else
390 return static_cast<std::ptrdiff_t>(lang::MSB(UnderlyingIntegral( p ) ))
391 - static_cast<std::ptrdiff_t>(lang::MSB(UnderlyingIntegral( other.p ) ));
392 }
393
394 /** Subscript operator.
395 * @param n The iterator to subtract
396 * @return <c>*( (*this) + n )</c>.
397 */
398 TEnum operator[]( std::ptrdiff_t n ) const
399 {
401 return ( p + static_cast<TIntegral>( n ) );
402 else
403 return TEnum( UnderlyingIntegral( p ) << n );
404 }
405
406 //#### Comparison operators (also needed to satisfy concept of RandomAccessIterator) ###
407
408 /** Compares this iterator with the given one.
409 * @param other The iterator to compare
410 * @return \c true if this iterator is \e smaller than \p{other},
411 * \c false otherwise. */
413 {
414 return p < other.p;
415 }
416
417 /** Compares this iterator with the given one.
418 * @param other The iterator to compare
419 * @return \c true if this iterator is \e smaller than or equal to \p{other},
420 * \c false otherwise. */
422 {
423 return p <= other.p;
424 }
425
426
427 /** Compares this iterator with the given one.
428 * @param other The iterator to compare
429 * @return \c true if this iterator is \e greater than \p{other},
430 * \c false otherwise. */
432 {
433 return p > other.p;
434 }
435
436 /** Compares this iterator with the given one.
437 * @param other The iterator to compare
438 * @return \c true if this iterator is \e greater than or equal to \p{other},
439 * \c false otherwise. */
441 {
442 return p >= other.p;
443 }
444 };
445
446 /**
447 * The constant iterator exposed by this class. A Mutable version is not available.
448 */
450
451
452 /**
453 * Returns an iterator referring to the start of enumeration \p{TEnum}.
454 * @return The start of the enumeration.
455 */
463
464 /**
465 * Returns an iterator referring the first illegal value of enumeration \p{TEnum}.
466 * @return The end of the enumeration.
467 */
469 {
471 }
472}; // struct EnumIterator
473
474
475
476
477} // namespace alib[::enums]
478
479#if defined(ALIB_DOX)
480
481/// Type alias in namespace \b alib.
482template<typename TEnum, typename TEnableIf= void>
484
485#else
486
487template<typename TEnum, typename TEnableIf
490
491#endif
492
493} // namespace [alib]
494
495#endif // HPP_ALIB_ENUMS_ITERABLE
bool operator<=(TRandomAccessIterator other) const
Definition iterable.hpp:421
TEnum operator[](std::ptrdiff_t n) const
Definition iterable.hpp:398
std::ptrdiff_t operator-(TRandomAccessIterator other) const
Definition iterable.hpp:385
constexpr TRandomAccessIterator(TEnum _p=TEnum(0))
Definition iterable.hpp:255
TRandomAccessIterator operator-(TIntegral n) const
Definition iterable.hpp:374
bool operator<(TRandomAccessIterator other) const
Definition iterable.hpp:412
typename std::underlying_type< TEnum >::type TIntegral
Definition iterable.hpp:248
bool operator>=(TRandomAccessIterator other) const
Definition iterable.hpp:440
TEnum value_type
Implementation of std::iterator_traits.
Definition iterable.hpp:238
TRandomAccessIterator operator+(TIntegral n) const
Definition iterable.hpp:363
TRandomAccessIterator & operator-=(TIntegral n)
Definition iterable.hpp:352
std::random_access_iterator_tag iterator_category
Implementation of std::iterator_traits.
Definition iterable.hpp:237
constexpr bool operator==(TRandomAccessIterator other) const
Definition iterable.hpp:287
TRandomAccessIterator & operator+=(TIntegral n)
Definition iterable.hpp:340
bool operator>(TRandomAccessIterator other) const
Definition iterable.hpp:431
TPointer pointer
Implementation of std::iterator_traits.
Definition iterable.hpp:240
constexpr bool operator!=(TRandomAccessIterator other) const
Definition iterable.hpp:296
std::ptrdiff_t difference_type
Implementation of std::iterator_traits.
Definition iterable.hpp:239
TReference reference
Implementation of std::iterator_traits.
Definition iterable.hpp:241
#define ALIB_ASSERT_MODULE(modulename)
Definition alib.hpp:190
#define ATMP_VOID_IF(Cond)
Definition tmp.hpp:52
#define ATMP_EQ( T, TEqual)
Definition tmp.hpp:32
#define ATMP_T_IF(T, Cond)
Definition tmp.hpp:53
constexpr TEnum operator+(TEnum element, int addend) noexcept(true)
constexpr TEnum operator-(TEnum element, int subtrahend) noexcept(true)
constexpr std::underlying_type< TEnum >::type UnderlyingIntegral(TEnum element) noexcept(true)
constexpr int MSB(TIntegral value)
Definition alib.cpp:57
ConstIterator end() const
Definition iterable.hpp:468
TRandomAccessIterator< const TEnum *, const TEnum & > ConstIterator
Definition iterable.hpp:449
ConstIterator begin() const
Definition iterable.hpp:456
static constexpr TEnum Begin
Definition iterable.hpp:85
static constexpr TEnum End
Definition iterable.hpp:95