ALib C++ Library
Library Version: 2510 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
iterable.inl
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/// \emoji :copyright: 2013-2025 A-Worx GmbH, Germany.
6/// Published under \ref mainpage_license "Boost Software 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 with this
19/// type.
20///
21/// \note
22/// The unspecialized version of this struct is empty.
23///
24/// If specialized, the following entities become available:
25/// - \alib{enumops::iterable;operator+}
26/// - \alib{enumops::iterable;operator-}
27/// - struct \alib{enumops;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 \ref 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 \ref ALIB_ENUMS_MAKE_ITERABLE and \ref ALIB_ENUMS_MAKE_ITERABLE_BEGIN_END, which
43/// specialize this type trait for a given enumeration type.
44/// - Type \alib{enumops;EnumIterator} used to perform iterations.
45/// - For details and a source code sample see chapter \ref alib_enums_iter "3. Enum Iteration"
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{
54 #if DOXYGEN
55 /// Specializations have to implement this static method to return the first enum element
56 /// of the iteration.
57 ///
58 /// @return The first enumeration element.
59 static constexpr TEnum Begin;
60 #endif
61
62 #if DOXYGEN
63 /// Specializations have to implement this static method to return the element value after
64 /// the last enum element of the iteration.
65 ///
66 /// @return The element after the last enumeration element.
67 static constexpr TEnum End;
68 #endif
69};
70
72
73/// A concept to identify "iterable enum types".
74/// These are types for which a specialization of type trait \alib{enumops;IterableTraits}
75/// is defined.
76/// @tparam TEnum The type to be tested.
77template <typename TEnum>
78concept IsIterable = std::same_as< const TEnum, decltype(IterableTraits<TEnum>::Begin) >;
79
81
82}} // namespace [alib::enumops::]
83
84// #################################################################################################
85// Operators for iterable enums
86// #################################################################################################
87
88// For documentation, all operators and enum-related template functions are faked into namespace
89// alib::enumops.
90#if DOXYGEN
91namespace alib { namespace enumops{
92/// Operators available to elements of enumerations if \alib{enumops;IterableTraits} is
93/// specialized.
94///
95/// \note
96/// This namespace exits only in the documentation to collect the operators.
97/// When parsed by a C++ compiler, <b>the operators reside in the global namespace</b>.
98namespace iterable {
99#endif
100
101/// Add operator usable with scoped enum types and integral values.
102///
103/// Selected by the compiler only if \alib{enumops;IterableTraits} is specialized for
104/// enum type \p{TEnum}.
105///
106/// @tparam TEnum Enumeration type.
107/// @tparam TRhs The type of the summand.
108/// @param element First operand of \p{TEnum} type.
109/// @param summand The summand.
110/// @return The <em>"summand-th"</em> enum element after \p{element} .
112template<typename TEnum, typename TRhs= int>
113requires ( alib::enumops::IsIterable<TEnum> && std::integral<TRhs> )
114constexpr TEnum operator+ (TEnum element, TRhs summand) noexcept
115{
116 return TEnum( alib::UnderlyingIntegral(element)
117 + static_cast<typename std::underlying_type<TEnum>::type>(summand) );
118}
119
120/// Subtract operator usable with scoped enum types and integral values.
121///
122/// Selected by the compiler only if \alib{enumops;IterableTraits} is specialized for
123/// enum type \p{TEnum}.
124///
125/// @tparam TEnum Enumeration type.
126/// @tparam TRhs The type of the subtrahend.
127/// @param element First operand of \p{TEnum} type.
128/// @param subtrahend The subtrahend.
129/// @return The <em>"subtrahend-th"</em> enum element before \p{element} .
131template<typename TEnum, typename TRhs= int>
132requires ( alib::enumops::IsIterable<TEnum> && std::integral<TRhs> )
133constexpr TEnum operator- (TEnum element, typename std::underlying_type<TEnum>::type subtrahend) noexcept
134{
135 return TEnum( alib::UnderlyingIntegral(element)
136 - static_cast<typename std::underlying_type<TEnum>::type>(subtrahend) );
137}
138
139
140// Faking all operators and enum-related template functions to namespace alib::enumops
141#if DOXYGEN
142}
143#else
144 ALIB_EXPORT namespace alib { namespace enumops {
145#endif
146
147// #################################################################################################
148// EnumIterator
149// #################################################################################################
150/// Implements a \c std::iterator_traits class for scoped and non-scoped enum types.
151/// The documentation is found with the type trait \alib{enumops;IterableTraits}, which needs
152/// to be specialized for template type \p{TEnum}.
153/// For other types, this class is not constructible.
154/// @tparam TEnum The enum type to iterate over.
155template<typename TEnum>
158{
159 //==============================================================================================
160 /// Default constructor.
161 //==============================================================================================
162 EnumIterator()= default;
163
164 //==============================================================================================
165 /// Implementation of \c std::iterator_traits for enum type \p{TEnum}. This class exposes
166 /// #ConstIterator which uses <c>const TEnum*</c> and <c>const TEnum&</c> as
167 /// pointer and reference types.
168 ///
169 /// As the name of the class indicates, this iterator satisfies the C++ standard library concept
170 /// \https{RandomAccessIterator,en.cppreference.com/w/cpp/concept/RandomAccessIterator}.
171 //==============================================================================================
172 template<typename TPointer, typename TReference>
174 {
175 using iterator_category = std::random_access_iterator_tag; ///< Implementation of <c>std::iterator_traits</c>.
176 using value_type = TEnum ; ///< Implementation of <c>std::iterator_traits</c>.
177 using difference_type = std::ptrdiff_t ; ///< Implementation of <c>std::iterator_traits</c>.
178 using pointer = TPointer ; ///< Implementation of <c>std::iterator_traits</c>.
179 using reference = TReference ; ///< Implementation of <c>std::iterator_traits</c>.
180
181 protected:
182 /// The actual enum element.
183 TEnum p;
184
185 /// The underlying integer type.
186 using TIntegral= typename std::underlying_type<TEnum>::type;
187
188
189 public:
190 /// Constructor.
191 /// @param pp Our initial value
192 constexpr
193 explicit TRandomAccessIterator( TEnum pp = TEnum(0) ) : p(pp)
194 {
195 }
196
197 //###################### To satisfy concept of InputIterator ######################
198
199 /// Prefix increment operator.
200 /// @return A reference to ourselves.
202 {
203 if constexpr( !IsBitwise<TEnum> )
204 p= p + 1;
205 else
206 p= TEnum( UnderlyingIntegral( p ) << 1 );
207
208 return *this;
209 }
210
211 /// Postfix increment operator.
212 /// @return A reference to ourselves.
213 TRandomAccessIterator operator++(typename std::underlying_type<TEnum>::type)
214 {
215 if constexpr( !IsBitwise<TEnum> )
216 return TRandomAccessIterator(p= p + 1);
217 else
218 return TRandomAccessIterator(p= TEnum( UnderlyingIntegral( p ) << 1) );
219 }
220
221 /// Comparison operator.
222 /// @param other The iterator to compare ourselves to.
223 /// @return \c true if this and given iterator are equal, \c false otherwise.
224 constexpr
226 {
227 return p == other.p;
228 }
229
230 /// Comparison operator.
231 /// @param other The iterator to compare ourselves to.
232 /// @return \c true if this and given iterator are not equal, \c false otherwise.
233 constexpr
235 {
236 return !(*this == other);
237 }
238
239 /// Retrieves the enum element that this iterator references.
240 /// @return The enum element.
241 constexpr
242 TEnum operator*() const
243 {
244 return p;
245 }
246
247
248 //################## To satisfy concept of BidirectionalIterator ##################
249
250 /// Prefix decrement operator.
251 /// @return A reference to ourselves.
253 {
254 if constexpr( !IsBitwise<TEnum> )
255 p= p + 1;
256 else
257 p= TEnum( );
258 return *this;
259 }
260
261
262 /// Postfix decrement operator.
263 /// @return An iterator that with the old value.
264 TRandomAccessIterator operator--(typename std::underlying_type<TEnum>::type)
265 {
266 if constexpr( !IsBitwise<TEnum> )
267 return TRandomAccessIterator(p= p - 1);
268 else
269 return TRandomAccessIterator(p= TEnum( UnderlyingIntegral( p ) >> 1) );
270 }
271
272
273 //################## To satisfy concept of RandomAccessIterator ###################
274
275 /// Addition assignment.
276 /// @param n The value to subtract.
277 /// @return A reference to ourselves.
279 {
280 if constexpr( !IsBitwise<TEnum> )
281 p= p + n;
282 else
283 p= TEnum( UnderlyingIntegral( p ) << n );
284 return *this;
285 }
286
287 /// Subtraction assignment.
288 /// @param n The value to subtract.
289 /// @return A reference to ourselves.
291 {
292 if constexpr( !IsBitwise<TEnum> )
293 p= p - n;
294 else
295 p= TEnum( UnderlyingIntegral( p ) >> n );
296 }
297
298 /// Addition.
299 /// @param n The value to subtract.
300 /// @return A reference to the new iterator.
302 {
303 if constexpr( !IsBitwise<TEnum> )
304 return TRandomAccessIterator( p + n );
305 else
306 return TRandomAccessIterator( TEnum( UnderlyingIntegral( p ) << n ) );
307 }
308
309 /// Subtraction.
310 /// @param n The value to subtract.
311 /// @return A reference to the new iterator.
313 {
314 if constexpr( !IsBitwise<TEnum> )
315 return TRandomAccessIterator( p - n );
316 else
317 return TRandomAccessIterator( TEnum( UnderlyingIntegral( p ) >> n ) );
318 }
319
320 /// Difference (distance) from this iterator to the given one.
321 /// @param other The iterator to subtract
322 /// @return The iterator to subtract.
323 std::ptrdiff_t operator-(TRandomAccessIterator other) const
324 {
325 if constexpr( !IsBitwise<TEnum> )
326 return static_cast<std::ptrdiff_t>(UnderlyingIntegral(p) - UnderlyingIntegral(other.p));
327 else
328 return static_cast<std::ptrdiff_t>(lang::MSB(UnderlyingIntegral( p ) ))
329 - static_cast<std::ptrdiff_t>(lang::MSB(UnderlyingIntegral( other.p ) ));
330 }
331
332 /// Subscript operator.
333 /// @param n The iterator to subtract
334 /// @return <c>*( (*this) + n )</c>.
335 TEnum operator[]( std::ptrdiff_t n ) const
336 {
337 if constexpr( !IsBitwise<TEnum> )
338 return ( p + static_cast<TIntegral>( n ) );
339 else
340 return TEnum( UnderlyingIntegral( p ) << n );
341 }
342
343 //#### Comparison operators (also needed to satisfy concept of RandomAccessIterator) ###
344
345 /// Compares this iterator with the given one.
346 /// @param other The iterator to compare
347 /// @return \c true if this iterator is \e smaller than \p{other},
348 /// \c false otherwise.
350 {
351 return p < other.p;
352 }
353
354 /// Compares this iterator with the given one.
355 /// @param other The iterator to compare
356 /// @return \c true if this iterator is \e smaller than or equal to \p{other},
357 /// \c false otherwise.
359 {
360 return p <= other.p;
361 }
362
363
364 /// Compares this iterator with the given one.
365 /// @param other The iterator to compare
366 /// @return \c true if this iterator is \e greater than \p{other},
367 /// \c false otherwise.
369 {
370 return p > other.p;
371 }
372
373 /// Compares this iterator with the given one.
374 /// @param other The iterator to compare
375 /// @return \c true if this iterator is \e greater than or equal to \p{other},
376 /// \c false otherwise.
378 {
379 return p >= other.p;
380 }
381 };
382
383 /// The constant iterator exposed by this class. A Mutable version is not available.
385
386
387 /// Returns an iterator referring to the start of enumeration \p{TEnum}.
388 /// @return The start of the enumeration.
396
397 /// Returns an iterator referring the first illegal value of enumeration \p{TEnum}.
398 /// @return The end of the enumeration.
400 {
402 }
403}; // struct EnumIterator
404
405
406
407
408} // namespace alib[::enumops::]
409
410/// Type alias in namespace \b alib.
411template<typename TEnum>
412requires enumops::IsIterable<TEnum>
414
415} // namespace [alib]
416
417
TRandomAccessIterator operator--(typename std::underlying_type< TEnum >::type)
Definition iterable.inl:264
TRandomAccessIterator operator++(typename std::underlying_type< TEnum >::type)
Definition iterable.inl:213
TReference reference
Implementation of std::iterator_traits.
Definition iterable.inl:179
std::ptrdiff_t difference_type
Implementation of std::iterator_traits.
Definition iterable.inl:177
TRandomAccessIterator & operator-=(TIntegral n)
Definition iterable.inl:290
typename std::underlying_type< TEnum >::type TIntegral
The underlying integer type.
Definition iterable.inl:186
TRandomAccessIterator operator-(TIntegral n) const
Definition iterable.inl:312
bool operator<=(TRandomAccessIterator other) const
Definition iterable.inl:358
constexpr TRandomAccessIterator(TEnum pp=TEnum(0))
Definition iterable.inl:193
bool operator<(TRandomAccessIterator other) const
Definition iterable.inl:349
std::random_access_iterator_tag iterator_category
Implementation of std::iterator_traits.
Definition iterable.inl:175
constexpr bool operator==(TRandomAccessIterator other) const
Definition iterable.inl:225
TPointer pointer
Implementation of std::iterator_traits.
Definition iterable.inl:178
TEnum value_type
Implementation of std::iterator_traits.
Definition iterable.inl:176
bool operator>(TRandomAccessIterator other) const
Definition iterable.inl:368
TRandomAccessIterator operator+(TIntegral n) const
Definition iterable.inl:301
TRandomAccessIterator & operator+=(TIntegral n)
Definition iterable.inl:278
constexpr bool operator!=(TRandomAccessIterator other) const
Definition iterable.inl:234
bool operator>=(TRandomAccessIterator other) const
Definition iterable.inl:377
std::ptrdiff_t operator-(TRandomAccessIterator other) const
Definition iterable.inl:323
#define ALIB_WARNINGS_RESTORE
Definition alib.inl:705
#define ALIB_WARNINGS_IGNORE_DOCS
Definition alib.inl:688
#define ALIB_EXPORT
Definition alib.inl:488
std::underlying_type_t< TEnum > constexpr UnderlyingIntegral(TEnum element) noexcept
constexpr int MSB(TIntegral value)
Definition bits.inl:325
enumops::EnumIterator< TEnum > EnumIterator
Type alias in namespace alib.
Definition iterable.inl:413
ConstIterator end() const
Definition iterable.inl:399
TRandomAccessIterator< const TEnum *, const TEnum & > ConstIterator
The constant iterator exposed by this class. A Mutable version is not available.
Definition iterable.inl:384
EnumIterator()=default
Default constructor.
ConstIterator begin() const
Definition iterable.inl:389
static constexpr TEnum Begin
Definition iterable.inl:59
static constexpr TEnum End
Definition iterable.inl:67