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