ALib C++ Library
Library Version: 2511 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 return TEnum( alib::UnderlyingIntegral(element)
116 + static_cast<typename std::underlying_type<TEnum>::type>(summand) );
117}
118
119/// Subtract operator usable with scoped enum types and integral values.
120///
121/// Selected by the compiler only if \alib{enumops;IterableTraits} is specialized for
122/// enum type \p{TEnum}.
123///
124/// @tparam TEnum Enumeration type.
125/// @tparam TRhs The type of the subtrahend.
126/// @param element First operand of \p{TEnum} type.
127/// @param subtrahend The subtrahend.
128/// @return The <em>"subtrahend-th"</em> enum element before \p{element} .
130template<typename TEnum, typename TRhs= int>
131requires ( alib::enumops::IsIterable<TEnum> && std::integral<TRhs> )
132constexpr TEnum operator- (TEnum element,
133 typename std::underlying_type<TEnum>::type subtrahend) noexcept {
134 return TEnum( alib::UnderlyingIntegral(element)
135 - static_cast<typename std::underlying_type<TEnum>::type>(subtrahend) );
136}
137
138
139// Faking all operators and enum-related template functions to namespace alib::enumops
140#if DOXYGEN
141}
142#else
143ALIB_EXPORT namespace alib { namespace enumops {
144#endif
145
146//##################################################################################################
147// EnumIterator
148//##################################################################################################
149/// Implements a \c std::iterator_traits class for scoped and non-scoped enum types.
150/// The documentation is found with the type trait \alib{enumops;IterableTraits}, which needs
151/// to be specialized for template type \p{TEnum}.
152/// For other types, this class is not constructible.
153/// @tparam TEnum The enum type to iterate over.
154template<typename TEnum>
157{
158 /// Default constructor.
159 EnumIterator() =default;
160
161 /// Implementation of \c std::iterator_traits for enum type \p{TEnum}. This class exposes
162 /// #ConstIterator which uses <c>const TEnum*</c> and <c>const TEnum&</c> as
163 /// pointer and reference types.
164 ///
165 /// As the name of the class indicates, this iterator satisfies the C++ standard library concept
166 /// \https{RandomAccessIterator,en.cppreference.com/w/cpp/concept/RandomAccessIterator}.
167 template<typename TPointer, typename TReference>
169 {
170 using iterator_category = std::random_access_iterator_tag; ///< Implementation of <c>std::iterator_traits</c>.
171 using value_type = TEnum ; ///< Implementation of <c>std::iterator_traits</c>.
172 using difference_type = std::ptrdiff_t ; ///< Implementation of <c>std::iterator_traits</c>.
173 using pointer = TPointer ; ///< Implementation of <c>std::iterator_traits</c>.
174 using reference = TReference ; ///< Implementation of <c>std::iterator_traits</c>.
175
176 protected:
177 /// The actual enum element.
178 TEnum p;
179
180 /// The underlying integer type.
181 using TIntegral= typename std::underlying_type<TEnum>::type;
182
183 public:
184 /// Constructor.
185 /// @param pp Our initial value
186 constexpr
187 explicit TRandomAccessIterator( TEnum pp = TEnum(0) ) : p(pp) {}
188
189 //############################ To satisfy concept of InputIterator ##########################
190
191 /// Prefix increment operator.
192 /// @return A reference to ourselves.
194 if constexpr( !IsBitwise<TEnum> )
195 p= p + 1;
196 else
197 p= TEnum( UnderlyingIntegral( p ) << 1 );
198
199 return *this;
200 }
201
202 /// Postfix increment operator.
203 /// @return A reference to ourselves.
204 TRandomAccessIterator operator++(typename std::underlying_type<TEnum>::type) {
205 if constexpr( !IsBitwise<TEnum> )
206 return TRandomAccessIterator(p= p + 1);
207 else
208 return TRandomAccessIterator(p= TEnum( UnderlyingIntegral( p ) << 1) );
209 }
210
211 /// Comparison operator.
212 /// @param other The iterator to compare ourselves to.
213 /// @return \c true if this and given iterator are equal, \c false otherwise.
214 constexpr
215 bool operator==(TRandomAccessIterator other) const { return p == other.p; }
216
217 /// Comparison operator.
218 /// @param other The iterator to compare ourselves to.
219 /// @return \c true if this and given iterator are not equal, \c false otherwise.
220 constexpr
221 bool operator!=(TRandomAccessIterator other) const { return !(*this == other); }
222
223 /// Retrieves the enum element that this iterator references.
224 /// @return The enum element.
225 constexpr
226 TEnum operator*() const { return p; }
227
228
229 //######################## To satisfy concept of BidirectionalIterator ######################
230
231 /// Prefix decrement operator.
232 /// @return A reference to ourselves.
234 if constexpr( !IsBitwise<TEnum> )
235 p= p + 1;
236 else
237 p= TEnum( );
238 return *this;
239 }
240
241
242 /// Postfix decrement operator.
243 /// @return An iterator that with the old value.
244 TRandomAccessIterator operator--(typename std::underlying_type<TEnum>::type) {
245 if constexpr( !IsBitwise<TEnum> )
246 return TRandomAccessIterator(p= p - 1);
247 else
248 return TRandomAccessIterator(p= TEnum( UnderlyingIntegral( p ) >> 1) );
249 }
250
251
252 //######################## To satisfy concept of RandomAccessIterator #######################
253
254 /// Addition assignment.
255 /// @param n The value to subtract.
256 /// @return A reference to ourselves.
258 if constexpr( !IsBitwise<TEnum> )
259 p= p + n;
260 else
261 p= TEnum( UnderlyingIntegral( p ) << n );
262 return *this;
263 }
264
265 /// Subtraction assignment.
266 /// @param n The value to subtract.
267 /// @return A reference to ourselves.
269 if constexpr( !IsBitwise<TEnum> )
270 p= p - n;
271 else
272 p= TEnum( UnderlyingIntegral( p ) >> n );
273 }
274
275 /// Addition.
276 /// @param n The value to subtract.
277 /// @return A reference to the new iterator.
279 if constexpr( !IsBitwise<TEnum> )
280 return TRandomAccessIterator( p + n );
281 else
282 return TRandomAccessIterator( TEnum( UnderlyingIntegral( p ) << n ) );
283 }
284
285 /// Subtraction.
286 /// @param n The value to subtract.
287 /// @return A reference to the new iterator.
289 if constexpr( !IsBitwise<TEnum> )
290 return TRandomAccessIterator( p - n );
291 else
292 return TRandomAccessIterator( TEnum( UnderlyingIntegral( p ) >> n ) );
293 }
294
295 /// Difference (distance) from this iterator to the given one.
296 /// @param other The iterator to subtract
297 /// @return The iterator to subtract.
298 std::ptrdiff_t operator-(TRandomAccessIterator other) const {
299 if constexpr( !IsBitwise<TEnum> )
300 return static_cast<std::ptrdiff_t>(UnderlyingIntegral(p) - UnderlyingIntegral(other.p));
301 else
302 return static_cast<std::ptrdiff_t>(lang::MSB(UnderlyingIntegral( p ) ))
303 - static_cast<std::ptrdiff_t>(lang::MSB(UnderlyingIntegral( other.p ) ));
304 }
305
306 /// Subscript operator.
307 /// @param n The iterator to subtract
308 /// @return <c>*( (*this) + n )</c>.
309 TEnum operator[]( std::ptrdiff_t n ) const {
310 if constexpr( !IsBitwise<TEnum> )
311 return ( p + static_cast<TIntegral>( n ) );
312 else
313 return TEnum( UnderlyingIntegral( p ) << n );
314 }
315
316 //#### Comparison operators (also needed to satisfy concept of RandomAccessIterator) ###
317
318 /// Compares this iterator with the given one.
319 /// @param other The iterator to compare
320 /// @return \c true if this iterator is \e smaller than \p{other},
321 /// \c false otherwise.
322 bool operator<(TRandomAccessIterator other) const { return p < other.p; }
323
324 /// Compares this iterator with the given one.
325 /// @param other The iterator to compare
326 /// @return \c true if this iterator is \e smaller than or equal to \p{other},
327 /// \c false otherwise.
328 bool operator<=(TRandomAccessIterator other) const { return p <= other.p; }
329
330
331 /// Compares this iterator with the given one.
332 /// @param other The iterator to compare
333 /// @return \c true if this iterator is \e greater than \p{other},
334 /// \c false otherwise.
335 bool operator>(TRandomAccessIterator other) const { return p > other.p; }
336
337 /// Compares this iterator with the given one.
338 /// @param other The iterator to compare
339 /// @return \c true if this iterator is \e greater than or equal to \p{other},
340 /// \c false otherwise.
341 bool operator>=(TRandomAccessIterator other) const { return p >= other.p; }
342 };
343
344/// The constant iterator exposed by this class. A Mutable version is not available.
346
347
348 /// Returns an iterator referring to the start of enumeration \p{TEnum}.
349 /// @return The start of the enumeration.
356
357 /// Returns an iterator referring the first illegal value of enumeration \p{TEnum}.
358 /// @return The end of the enumeration.
361}; // struct EnumIterator
362
363
364
365
366} // namespace alib[::enumops::]
367
368/// Type alias in namespace \b alib.
369template<typename TEnum>
370requires enumops::IsIterable<TEnum>
372
373} // namespace [alib]
TRandomAccessIterator operator--(typename std::underlying_type< TEnum >::type)
Definition iterable.inl:244
TRandomAccessIterator operator++(typename std::underlying_type< TEnum >::type)
Definition iterable.inl:204
TReference reference
Implementation of std::iterator_traits.
Definition iterable.inl:174
std::ptrdiff_t difference_type
Implementation of std::iterator_traits.
Definition iterable.inl:172
TRandomAccessIterator & operator-=(TIntegral n)
Definition iterable.inl:268
typename std::underlying_type< TEnum >::type TIntegral
The underlying integer type.
Definition iterable.inl:181
TRandomAccessIterator operator-(TIntegral n) const
Definition iterable.inl:288
bool operator<=(TRandomAccessIterator other) const
Definition iterable.inl:328
constexpr TRandomAccessIterator(TEnum pp=TEnum(0))
Definition iterable.inl:187
bool operator<(TRandomAccessIterator other) const
Definition iterable.inl:322
std::random_access_iterator_tag iterator_category
Implementation of std::iterator_traits.
Definition iterable.inl:170
constexpr bool operator==(TRandomAccessIterator other) const
Definition iterable.inl:215
TPointer pointer
Implementation of std::iterator_traits.
Definition iterable.inl:173
TEnum value_type
Implementation of std::iterator_traits.
Definition iterable.inl:171
bool operator>(TRandomAccessIterator other) const
Definition iterable.inl:335
TRandomAccessIterator operator+(TIntegral n) const
Definition iterable.inl:278
TRandomAccessIterator & operator+=(TIntegral n)
Definition iterable.inl:257
constexpr bool operator!=(TRandomAccessIterator other) const
Definition iterable.inl:221
bool operator>=(TRandomAccessIterator other) const
Definition iterable.inl:341
std::ptrdiff_t operator-(TRandomAccessIterator other) const
Definition iterable.inl:298
#define ALIB_WARNINGS_RESTORE
Definition alib.inl:719
#define ALIB_WARNINGS_IGNORE_DOCS
Definition alib.inl:702
#define ALIB_EXPORT
Definition alib.inl:497
std::underlying_type_t< TEnum > constexpr UnderlyingIntegral(TEnum element) noexcept
constexpr int MSB(TIntegral value)
Definition bits.inl:314
enumops::EnumIterator< TEnum > EnumIterator
Type alias in namespace alib.
Definition iterable.inl:371
ConstIterator end() const
Definition iterable.inl:359
TRandomAccessIterator< const TEnum *, const TEnum & > ConstIterator
The constant iterator exposed by this class. A Mutable version is not available.
Definition iterable.inl:345
EnumIterator()=default
Default constructor.
ConstIterator begin() const
Definition iterable.inl:350
static constexpr TEnum Begin
Definition iterable.inl:59
static constexpr TEnum End
Definition iterable.inl:67