ALib C++ Framework
by
Library Version: 2605 R0
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 the module \alib_enumops of the \aliblong.
4///
5/// Copyright 2013-2026 A-Worx GmbH, Germany.
6/// Published under #"mainpage_license".
7//==================================================================================================
8ALIB_EXPORT namespace alib { namespace enumops{
9
10//##################################################################################################
11// struct IterableTraits
12//##################################################################################################
13
14
15//==================================================================================================
16/// A simple type trait that - if specialized - enables standard and range-based C++ iteration of the
17/// elements of an enumeration.
18/// Specializations have to declare <c>constexpr</c> fields #".Begin" and #".End", as documented
19/// with this type.
20///
21/// \note
22/// The unspecialized version of this struct is empty.
23///
24/// If specialized, the following entities become available:
25/// - #"iterable::operator+"
26/// - #"iterable::operator-"
27/// - struct #"EnumIterator"
28///
29/// \attention
30/// Likewise with the operators introduced with other type traits of this module,
31/// this documentation "fakes" the operators into namespace
32/// <c>alib::enumops::iterable</c>, while in fact they are defined in the global
33/// namespace!<br>
34/// See #"alib_enums_arithmetic_standard;corresponding note" in the Programmer's Manual
35/// for details.
36///
37/// <b>Restrictions</b><br>
38/// For technical reasons, this concept is not applicable to enum types that are defined as
39/// \c private or \c protected inner types of structs or classes.
40///
41/// \see
42/// - Macros #"ALIB_ENUMS_MAKE_ITERABLE" and #"ALIB_ENUMS_MAKE_ITERABLE_BEGIN_END", which
43/// specialize this type trait for a given enumeration type.
44/// - Type #"EnumIterator" used to perform iterations.
45/// - For details and a source code sample see chapter #"alib_enums_iter"
46/// of the Programmer's Manual of the module \alib_enumops.
47///
48/// @tparam TEnum The enum type to enable iteration for.
49//==================================================================================================
50template<typename TEnum>
51requires std::is_enum_v<TEnum>
52struct IterableTraits : std::false_type {
53 #if DOXYGEN
54 /// Specializations have to implement this static method to return the first enum element
55 /// of the iteration.
56 ///
57 /// @return The first enumeration element.
58 static constexpr TEnum Begin;
59 #endif
60
61 #if DOXYGEN
62 /// Specializations have to implement this static method to return the element value after
63 /// the last enum element of the iteration.
64 ///
65 /// @return The element after the last enumeration element.
66 static constexpr TEnum End;
67 #endif
68};
69
71
72/// A concept to identify "iterable enum types".
73/// These are types for which a specialization of type trait #"IterableTraits"
74/// is defined.
75/// @tparam TEnum The type to be tested.
76template <typename TEnum>
77concept IsIterable = std::same_as< const TEnum, decltype(IterableTraits<TEnum>::Begin) >;
78
80
81}} // namespace [alib::enumops::]
82
83//##################################################################################################
84// Operators for iterable enums
85//##################################################################################################
86
87// For documentation, all operators and enum-related template functions are faked into namespace
88// alib::enumops.
89#if DOXYGEN
90namespace alib { namespace enumops{
91/// Operators available to elements of enumerations if #"IterableTraits" is
92/// specialized.
93///
94/// \note
95/// This namespace exits only in the documentation to collect the operators.
96/// When parsed by a C++ compiler, <b>the operators reside in the global namespace</b>.
97namespace iterable {
98#endif
99
100/// Add operator usable with scoped enum types and integral values.
101///
102/// Selected by the compiler only if #"IterableTraits" is specialized for
103/// enum type \p{TEnum}.
104///
105/// @tparam TEnum Enumeration type.
106/// @tparam TRhs The type of the summand.
107/// @param element First operand of \p{TEnum} type.
108/// @param summand The summand.
109/// @return The <em>"summand-th"</em> enum element after \p{element} .
111template<typename TEnum, typename TRhs= int>
112requires ( alib::enumops::IsIterable<TEnum> && std::integral<TRhs> )
113constexpr TEnum operator+ (TEnum element, TRhs summand) noexcept {
114 return TEnum( alib::UnderlyingIntegral(element)
115 + static_cast<typename std::underlying_type<TEnum>::type>(summand) );
116}
117
118/// Subtract operator usable with scoped enum types and integral values.
119///
120/// Selected by the compiler only if #"IterableTraits" is specialized for
121/// enum type \p{TEnum}.
122///
123/// @tparam TEnum Enumeration type.
124/// @tparam TRhs The type of the subtrahend.
125/// @param element First operand of \p{TEnum} type.
126/// @param subtrahend The subtrahend.
127/// @return The <em>"subtrahend-th"</em> enum element before \p{element} .
129template<typename TEnum, typename TRhs= int>
130requires ( alib::enumops::IsIterable<TEnum> && std::integral<TRhs> )
131constexpr TEnum operator- (TEnum element, TRhs subtrahend) noexcept {
132 return TEnum( alib::UnderlyingIntegral(element)
133 - static_cast<typename std::underlying_type<TEnum>::type>(subtrahend) );
134}
135
136
137// Faking all operators and enum-related template functions to namespace alib::enumops
138#if DOXYGEN
139}
140#else
141ALIB_EXPORT namespace alib { namespace enumops {
142#endif
143
144//##################################################################################################
145// EnumIterator
146//##################################################################################################
147/// Implements a \c std::iterator_traits class for scoped and non-scoped enum types.
148/// The documentation is found with the type trait #"IterableTraits", which needs
149/// to be specialized for template type \p{TEnum}.
150/// For other types, this class is not constructible.
151/// @tparam TEnum The enum type to iterate over.
152template<typename TEnum>
155 /// Default constructor.
156 EnumIterator() =default;
157
158 /// Implementation of \c std::iterator_traits for enum type \p{TEnum}. This class exposes
159 /// #"EnumIterator::ConstIterator;2" which uses <c>const TEnum*</c> and <c>const TEnum&</c> as
160 /// pointer and reference types.
161 ///
162 /// As the name of the class indicates, this iterator satisfies the C++ standard library concept
163 /// \https{RandomAccessIterator,en.cppreference.com/w/cpp/concept/RandomAccessIterator}.
164 template<typename TPointer, typename TReference>
166 using iterator_category = std::random_access_iterator_tag; ///< Implementation of <c>std::iterator_traits</c>.
167 using value_type = TEnum ; ///< Implementation of <c>std::iterator_traits</c>.
168 using difference_type = std::ptrdiff_t ; ///< Implementation of <c>std::iterator_traits</c>.
169 using pointer = TPointer ; ///< Implementation of <c>std::iterator_traits</c>.
170 using reference = TReference ; ///< Implementation of <c>std::iterator_traits</c>.
171
172 protected:
173 /// The actual enum element.
174 TEnum p;
175
176 /// The underlying integer type.
177 using TIntegral= typename std::underlying_type<TEnum>::type;
178
179 public:
180 /// Constructor.
181 /// @param pp Our initial value
182 constexpr
183 explicit TRandomAccessIterator( TEnum pp = TEnum(0) ) : p(pp) {}
184
185 //############################ To satisfy concept of InputIterator ##########################
186
187 /// Prefix increment operator.
188 /// @return A reference to ourselves.
190 if constexpr( !IsBitwise<TEnum> )
191 p= p + 1;
192 else
193 p= TEnum( UnderlyingIntegral( p ) << 1 );
194
195 return *this;
196 }
197
198 /// Postfix increment operator.
199 /// @return A reference to ourselves.
200 TRandomAccessIterator operator++(typename std::underlying_type<TEnum>::type) {
201 if constexpr( !IsBitwise<TEnum> )
202 return TRandomAccessIterator(p= p + 1);
203 else
204 return TRandomAccessIterator(p= TEnum( UnderlyingIntegral( p ) << 1) );
205 }
206
207 /// Comparison operator.
208 /// @param other The iterator to compare ourselves to.
209 /// @return \c true if this and given iterator are equal, \c false otherwise.
210 constexpr
211 bool operator==(TRandomAccessIterator other) const { return p == other.p; }
212
213 /// Comparison operator.
214 /// @param other The iterator to compare ourselves to.
215 /// @return \c true if this and given iterator are not equal, \c false otherwise.
216 constexpr
217 bool operator!=(TRandomAccessIterator other) const { return !(*this == other); }
218
219 /// Retrieves the enum element that this iterator references.
220 /// @return The enum element.
221 constexpr
222 TEnum operator*() const { return p; }
223
224
225 //######################## To satisfy concept of BidirectionalIterator ######################
226
227 /// Prefix decrement operator.
228 /// @return A reference to ourselves.
230 if constexpr( !IsBitwise<TEnum> )
231 p= p + 1;
232 else
233 p= TEnum( );
234 return *this;
235 }
236
237
238 /// Postfix decrement operator.
239 /// @return An iterator that with the old value.
240 TRandomAccessIterator operator--(typename std::underlying_type<TEnum>::type) {
241 if constexpr( !IsBitwise<TEnum> )
242 return TRandomAccessIterator(p= p - 1);
243 else
244 return TRandomAccessIterator(p= TEnum( UnderlyingIntegral( p ) >> 1) );
245 }
246
247
248 //######################## To satisfy concept of RandomAccessIterator #######################
249
250 /// Addition assignment.
251 /// @param n The value to subtract.
252 /// @return A reference to ourselves.
254 if constexpr( !IsBitwise<TEnum> )
255 p= p + n;
256 else
257 p= TEnum( UnderlyingIntegral( p ) << n );
258 return *this;
259 }
260
261 /// Subtraction assignment.
262 /// @param n The value to subtract.
263 /// @return A reference to ourselves.
265 if constexpr( !IsBitwise<TEnum> )
266 p= p - n;
267 else
268 p= TEnum( UnderlyingIntegral( p ) >> n );
269 }
270
271 /// Addition.
272 /// @param n The value to subtract.
273 /// @return A reference to the new iterator.
275 if constexpr( !IsBitwise<TEnum> )
276 return TRandomAccessIterator( p + n );
277 else
278 return TRandomAccessIterator( TEnum( UnderlyingIntegral( p ) << n ) );
279 }
280
281 /// Subtraction.
282 /// @param n The value to subtract.
283 /// @return A reference to the new iterator.
285 if constexpr( !IsBitwise<TEnum> )
286 return TRandomAccessIterator( p - n );
287 else
288 return TRandomAccessIterator( TEnum( UnderlyingIntegral( p ) >> n ) );
289 }
290
291 /// Difference (distance) from this iterator to the given one.
292 /// @param other The iterator to subtract
293 /// @return The iterator to subtract.
294 std::ptrdiff_t operator-(TRandomAccessIterator other) const {
295 if constexpr( !IsBitwise<TEnum> )
296 return static_cast<std::ptrdiff_t>(UnderlyingIntegral(p) - UnderlyingIntegral(other.p));
297 else
298 return static_cast<std::ptrdiff_t>(lang::MSB(UnderlyingIntegral( p ) ))
299 - static_cast<std::ptrdiff_t>(lang::MSB(UnderlyingIntegral( other.p ) ));
300 }
301
302 /// Subscript operator.
303 /// @param n The iterator to subtract
304 /// @return <c>*( (*this) + n )</c>.
305 TEnum operator[]( std::ptrdiff_t n ) const {
306 if constexpr( !IsBitwise<TEnum> )
307 return ( p + static_cast<TIntegral>( n ) );
308 else
309 return TEnum( UnderlyingIntegral( p ) << n );
310 }
311
312 //#### Comparison operators (also needed to satisfy concept of RandomAccessIterator) ###
313
314 /// Compares this iterator with the given one.
315 /// @param other The iterator to compare
316 /// @return \c true if this iterator is \e smaller than \p{other},
317 /// \c false otherwise.
318 bool operator<(TRandomAccessIterator other) const { return p < other.p; }
319
320 /// Compares this iterator with the given one.
321 /// @param other The iterator to compare
322 /// @return \c true if this iterator is \e smaller than or equal to \p{other},
323 /// \c false otherwise.
324 bool operator<=(TRandomAccessIterator other) const { return p <= other.p; }
325
326
327 /// Compares this iterator with the given one.
328 /// @param other The iterator to compare
329 /// @return \c true if this iterator is \e greater than \p{other},
330 /// \c false otherwise.
331 bool operator>(TRandomAccessIterator other) const { return p > other.p; }
332
333 /// Compares this iterator with the given one.
334 /// @param other The iterator to compare
335 /// @return \c true if this iterator is \e greater than or equal to \p{other},
336 /// \c false otherwise.
337 bool operator>=(TRandomAccessIterator other) const { return p >= other.p; }
338 };
339
340 /// The constant iterator exposed by this class. A Mutable version is not available.
342
343
344 /// Returns an iterator referring to the start of enumeration \p{TEnum}.
345 /// @return The start of the enumeration.
352
353 /// Returns an iterator referring the first illegal value of enumeration \p{TEnum}.
354 /// @return The end of the enumeration.
357}; // struct EnumIterator
358
359
360
361
362} // namespace alib[::enumops::]
363
364/// Type alias in namespace #"%alib".
365template<typename TEnum>
366requires enumops::IsIterable<TEnum>
368
369} // namespace [alib]
#define ALIB_ALLOW_DOCS
#define ALIB_POP_ALLOWANCE
#define ALIB_EXPORT
TRandomAccessIterator operator--(typename std::underlying_type< TEnum >::type)
Definition iterable.hpp:240
TRandomAccessIterator operator++(typename std::underlying_type< TEnum >::type)
Definition iterable.hpp:200
TReference reference
Implementation of std::iterator_traits.
Definition iterable.hpp:170
std::ptrdiff_t difference_type
Implementation of std::iterator_traits.
Definition iterable.hpp:168
TRandomAccessIterator & operator-=(TIntegral n)
Definition iterable.hpp:264
typename std::underlying_type< TEnum >::type TIntegral
The underlying integer type.
Definition iterable.hpp:177
TRandomAccessIterator operator-(TIntegral n) const
Definition iterable.hpp:284
bool operator<=(TRandomAccessIterator other) const
Definition iterable.hpp:324
constexpr TRandomAccessIterator(TEnum pp=TEnum(0))
Definition iterable.hpp:183
bool operator<(TRandomAccessIterator other) const
Definition iterable.hpp:318
std::random_access_iterator_tag iterator_category
Implementation of std::iterator_traits.
Definition iterable.hpp:166
constexpr bool operator==(TRandomAccessIterator other) const
Definition iterable.hpp:211
TPointer pointer
Implementation of std::iterator_traits.
Definition iterable.hpp:169
TEnum value_type
Implementation of std::iterator_traits.
Definition iterable.hpp:167
bool operator>(TRandomAccessIterator other) const
Definition iterable.hpp:331
TRandomAccessIterator operator+(TIntegral n) const
Definition iterable.hpp:274
TRandomAccessIterator & operator+=(TIntegral n)
Definition iterable.hpp:253
constexpr bool operator!=(TRandomAccessIterator other) const
Definition iterable.hpp:217
bool operator>=(TRandomAccessIterator other) const
Definition iterable.hpp:337
std::ptrdiff_t operator-(TRandomAccessIterator other) const
Definition iterable.hpp:294
std::underlying_type_t< TEnum > constexpr UnderlyingIntegral(TEnum element) noexcept
constexpr int MSB(TIntegral value)
Definition bits.hpp:309
Definition alox.cpp:14
enumops::EnumIterator< TEnum > EnumIterator
Type alias in namespace #"%alib".
Definition iterable.hpp:367
ConstIterator end() const
Definition iterable.hpp:355
TRandomAccessIterator< const TEnum *, const TEnum & > ConstIterator
The constant iterator exposed by this class. A Mutable version is not available.
Definition iterable.hpp:341
EnumIterator()=default
Default constructor.
ConstIterator begin() const
Definition iterable.hpp:346
static constexpr TEnum Begin
Definition iterable.hpp:58
static constexpr TEnum End
Definition iterable.hpp:66