GCC Code Coverage Report


Directory: ./
File: include/CXXIter/src/Traits.h
Date: 2023-01-04 16:32:12
Exec Total Coverage
Lines: 19 19 100.0%
Functions: 140 140 100.0%
Branches: 2 4 50.0%

Line Branch Exec Source
1 #pragma once
2
3 #include "IterValue.h"
4 #include "SizeHint.h"
5
6 /**
7 * @brief Trait namespace. This namespaces contains all public traits that cover all of the iterator's inner workings.
8 */
9 namespace CXXIter::trait {
10
11 // ################################################################################################
12 // ITERATOR TRAITS
13 // ################################################################################################
14
15 /**
16 * @brief Trait, that is used for the chaining and the operation of iterator pipelines.
17 * @details This allows making any class or struct iterable, to be able to interact with CXXIter's
18 * iterator pipelines. It essentially provides two functions:
19 * - One that delivers a hint about the iterator's size after the current element implementing
20 * the trait @c CXXIter::trait::Iterator
21 * - Method that allows pulling one element from the iterator pipeline.
22 */
23 template<typename T>
24 struct Iterator {
25 /**
26 * @brief Self-Type. This is the type of the struct for which the trait::Iterator is being specialized.
27 */
28 using Self = trait::Iterator<T>;
29 /**
30 * @brief Item-Type. This is the type of elements that can be pulled from this pipeline-element.
31 */
32 using Item = void;
33
34 /**
35 * @brief Pull one element from the iterator pipeline previous to this pipeline-element.
36 * @param self Reference to the instance of the class for which trait::Iterator is being specialized.
37 * @return An element (if any) wrapped in the CXXIter::IterValue.
38 */
39 static constexpr inline IterValue<Item> next(Self& self) = delete;
40
41 /**
42 * @brief Get the bounds on the remaining length of the iterator pipeline until this pipeline-element,
43 * estimated from the source and all of the chained iterations until after this pipeline-element.
44 * @return The estimated bounds on the remaining length of the iterator pipeline until after this pipeline-element.
45 */
46 static constexpr inline SizeHint sizeHint(const Self& self) = delete;
47
48 /**
49 * @brief Advance the iterator by n elements.
50 * @details If possible, this should be forwarded to the previous pipeline element, because then the
51 * pipeline source has the possibility to implement this as a O(1) operation, if supported.
52 * @param n The amount of elements to advance the iterator by.
53 * @return The amount of elements by which the iterator was actually advanced (e.g. if the iterator
54 * did have less than @p n elements remaining)
55 */
56 static constexpr inline size_t advanceBy(Self& self, size_t n) = delete;
57 };
58
59 /**
60 * @brief Trait, that extends iterators for which an exact length is known.
61 */
62 template<typename T>
63 struct ExactSizeIterator {
64 /**
65 * @brief Get the iterator's exact number of elements.
66 * @param self Reference to the instance of the class for which trait::ExactSizeIterator is being specialized.
67 * @return This iterator's exact number of elements.
68 */
69 static constexpr inline size_t size(const typename trait::Iterator<T>::Self& self) = delete;
70 };
71
72 /**
73 * @brief Trait, that iterators implement whose elements are stored in a contiguous block of memory.
74 * @details This trait allows downstream elements to assume that it is valid to access following
75 * elements by reading from the current element onward.
76 */
77 template<typename T>
78 struct ContiguousMemoryIterator {
79 /**
80 * @brief Pointer type to an item of this iterator.
81 * @details This keeps the const specifier.
82 */
83 using ItemPtr = std::add_pointer_t<std::remove_reference_t<typename Iterator<T>::Item>>;
84 /**
85 * @brief Get the pointer of the current element.
86 * @param self Reference to the instance of the class for which trait::ExactSizeIterator is being specialized.
87 * @return Pointer of the element that would be returned by the next call to next().
88 */
89 static constexpr inline ItemPtr currentPtr(typename trait::Iterator<T>::Self& self) = delete;
90 };
91
92 /**
93 * @brief Trait that extends the Iterator trait with double-ended functionality.
94 * @details Implementing this trait extends the iterator with the functionality to pull elements from the back.
95 * This can be arbitrarily mixed. Elements can e.g. be retrieved from front and back alternatingly.
96 */
97 template<typename T>
98 struct DoubleEndedIterator {
99 using Self = typename trait::Iterator<T>::Self;
100
101 /**
102 * @brief Pull the next last element from the iterator pipeline previous to this pipeline-element.
103 * @param self Reference to the instance of the class for which trait::DoubleEndedIterator is being specialized.
104 * @return An element (if any) wrapped in the CXXIter::IterValue.
105 */
106 static constexpr inline IterValue<typename Iterator<T>::Item> nextBack(Self& self) = delete;
107 };
108
109
110 // ################################################################################################
111 // SOURCE TRAITS
112 // ################################################################################################
113
114 /**
115 * @brief SourceTrait, that is used by CXXIter's standard source classes @c CXXIter::SrcMov, @c CXXIter::SrcRef and @c CXXIter::SrcCRef.
116 * @details If you want to add support for your own containers to these sources, and thus to @c CXXIter::from() calls,
117 * create a template specialization of @c CXXIter::SourceTrait, for your container class.
118 *
119 * This is the default implementation supporting all STL containers.
120 */
121 template<typename TContainer> struct Source {
122 /**
123 * @brief Type of the item @p TContainer holds and provides for the iterator.
124 */
125 using Item = typename TContainer::value_type;
126 /**
127 * @brief Type of the item @p TContainer holds and provides for the iterator, in referenced form.
128 */
129 using ItemRef = typename TContainer::reference;
130 /**
131 * @brief Type of the item @p TContainer holds and provides for the iterator, in const referenced form.
132 */
133 using ItemConstRef = typename TContainer::const_reference;
134
135 /**
136 * @brief Type of the state structure stored in CXXIter's source classes, used to keep track of the iteration progress.
137 * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef
138 */
139 struct IteratorState {
140 /** Iteration range left (start) */
141 typename TContainer::iterator left;
142 /** Iteration range right (end) */
143 typename TContainer::iterator right;
144 };
145
146 /**
147 * @brief Type of the state structure stored in CXXIter's source classes, used to keep track of the iteration progress.
148 * @details This is used for @c CXXIter::SrcCRef
149 */
150 struct ConstIteratorState {
151 /** Iteration range left (start) */
152 typename TContainer::const_iterator left;
153 /** Iteration range right (end) */
154 typename TContainer::const_iterator right;
155 };
156
157 /**
158 * @brief Report a size hint for a source on the given @p container.
159 * @details This injects information about the source's size (element count) into the iterator API.
160 * @param container Container for which to generate a size hint.
161 * @return A size hint for the given @p container.
162 */
163 532 static constexpr inline SizeHint sizeHint(const TContainer& container) { return SizeHint(container.size(), container.size()); }
164
165 /**
166 * @brief Return an initial @c IteratorState instance for iteration on the given @p container.
167 * @details This is stored within CXXIter's source classes, to hold the iteration's state.
168 * This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef
169 * @param container Container on which the source runs.
170 * @return Instance of @c IteratorState
171 */
172 872 static constexpr inline IteratorState initIterator(TContainer& container) { return {container.begin(), container.end()}; }
173 /**
174 * @brief Return an initial @c IteratorState instance for iteration on the given @p container.
175 * @details This is stored within CXXIter's source classes, to hold the iteration's state.
176 * This is used for @c CXXIter::SrcCRef
177 * @param container Container on which the source runs.
178 * @return Instance of @c ConstIteratorState
179 */
180 76 static constexpr inline ConstIteratorState initIterator(const TContainer& container) { return {container.begin(), container.end()}; }
181
182 /**
183 * @brief Checks whether there is a next item in the iteration with the given @p iter state on the given @p container.
184 * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef
185 * @param container Container on which the current iteration is running.
186 * @param iter The current iteration's state structure.
187 * @return @c true when there is another item available, @c false otherwise.
188 */
189 2978 static constexpr inline bool hasNext([[maybe_unused]] TContainer& container, IteratorState& iter) { return (iter.left != iter.right); }
190 /**
191 * @brief Checks whether there is a next item in the iteration with the given @p iter state on the given @p container.
192 * @details This is used for @c CXXIter::SrcCRef
193 * @param container Container on which the current iteration is running.
194 * @param iter The current iteration's state structure.
195 * @return @c true when there is another item available, @c false otherwise.
196 */
197 184 static constexpr inline bool hasNext([[maybe_unused]] const TContainer& container, ConstIteratorState& iter) { return (iter.left != iter.right); }
198
199 /**
200 * @brief Return the next item in the iteration with the given @p iter state on the given @p container.
201 * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef
202 * @param container Container on which the current iteration is running.
203 * @param iter The current iteration's state structure.
204 * @return The next item from the current iteration.
205 */
206 2176 static constexpr inline ItemRef next([[maybe_unused]] TContainer& container, IteratorState& iter) { return (*iter.left++); }
207 /**
208 * @brief Return the next item in the iteration with the given @p iter state on the given @p container.
209 * @details This is used for @c CXXIter::SrcCRef
210 * @param container Container on which the current iteration is running.
211 * @param iter The current iteration's state structure.
212 * @return The next item from the current iteration.
213 */
214 151 static constexpr inline ItemConstRef next([[maybe_unused]] const TContainer& container, ConstIteratorState& iter) { return (*iter.left++); }
215
216 /**
217 * @brief Return the next item in the iteration with the given @p iter state on the given @p container, without advancing.
218 * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef
219 * @param container Container on which the current iteration is running.
220 * @param iter The current iteration's state structure.
221 * @return The next item from the current iteration.
222 * @attention Calling this when @c hasNext() returns @c false is undefined behavior!
223 */
224 38 static constexpr inline ItemRef peekNext([[maybe_unused]] TContainer& container, IteratorState& iter) { return (*iter.left); }
225 /**
226 * @brief Return the next item in the iteration with the given @p iter state on the given @p container, without advancing.
227 * @details This is used for @c CXXIter::SrcCRef
228 * @param container Container on which the current iteration is running.
229 * @param iter The current iteration's state structure.
230 * @return The next item from the current iteration.
231 * @attention Calling this when @c hasNext() returns @c false is undefined behavior!
232 */
233 3 static constexpr inline ItemConstRef peekNext([[maybe_unused]] const TContainer& container, ConstIteratorState& iter) { return (*iter.left); }
234
235 /**
236 * @brief Skip the next @p n elements from the container.
237 * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef
238 * @param container Container on which the current iteration is running.
239 * @param iter The current iteration's state structure.
240 * @param n The amount of elements to skip.
241 * @return The amount of actually skipped elements (e.g. if there were less than @p n elements remaining).
242 */
243 102 static constexpr inline size_t skipN([[maybe_unused]] const TContainer& container, IteratorState& iter, size_t n) {
244
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
102 size_t skipN = std::min(n, static_cast<size_t>(std::distance(iter.left, iter.right)));
245 102 iter.left += skipN;
246 102 return skipN;
247 }
248 /**
249 * @brief Skip the next @p n elements from the container.
250 * @details This is used for @c CXXIter::SrcCRef
251 * @param container Container on which the current iteration is running.
252 * @param iter The current iteration's state structure.
253 * @param n The amount of elements to skip.
254 * @return The amount of actually skipped elements (e.g. if there were less than @p n elements remaining).
255 */
256 7 static constexpr inline size_t skipN([[maybe_unused]] const TContainer& container, ConstIteratorState& iter, size_t n) {
257
1/2
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
7 size_t skipN = std::min(n, static_cast<size_t>(std::distance(iter.left, iter.right)));
258 7 iter.left += skipN;
259 7 return skipN;
260 }
261
262 /**
263 * @name Double-Ended iterator functionality (optional)
264 */
265 //@{
266 /**
267 * @brief Return the next item from the back of the iteration with the given @p iter state on the given @p container.
268 * @note Implementing this is optional, since not all containers can support this.
269 * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef
270 * @param container Container on which the current iteration is running.
271 * @param iter The current iteration's state structure.
272 * @return The next item from the back of the current iteration.
273 */
274 180 static constexpr inline ItemRef nextBack([[maybe_unused]] TContainer& container, IteratorState& iter) { return (*--iter.right); }
275 /**
276 * @brief Return the next item from the back of the iteration with the given @p iter state on the given @p container.
277 * @note Implementing this is optional, since not all containers can support this.
278 * @details This is used for @c CXXIter::SrcCRef
279 * @param container Container on which the current iteration is running.
280 * @param iter The current iteration's state structure.
281 * @return The next item from the back of the current iteration.
282 */
283 5 static constexpr inline ItemConstRef nextBack([[maybe_unused]] const TContainer& container, ConstIteratorState& iter) { return (*--iter.right); }
284
285 /**
286 * @brief Skip the next n elements from the back of this iterator.
287 * @details This is used for @c CXXIter::SrcMov and @c CXXIter::SrcRef
288 * @param container Container on which the current iteration is running.
289 * @param iter The current iteration's state structure.
290 * @param n The amount of elements to skip.
291 * @return The amount of actually skipped elements (e.g. if there were less than @p n elements remaining).
292 */
293 static constexpr inline size_t skipNBack([[maybe_unused]] const TContainer& container, IteratorState& iter, size_t n) {
294 size_t skipN = std::min(n, static_cast<size_t>(std::distance(iter.left, iter.right)));
295 iter.right -= skipN;
296 return skipN;
297 }
298 /**
299 * @brief Skip the next n elements from the back of this iterator.
300 * @details This is used for @c CXXIter::SrcCRef
301 * @param container Container on which the current iteration is running.
302 * @param iter The current iteration's state structure.
303 * @param n The amount of elements to skip.
304 * @return The amount of actually skipped elements (e.g. if there were less than @p n elements remaining).
305 */
306 static constexpr inline size_t skipNBack([[maybe_unused]] const TContainer& container, ConstIteratorState& iter, size_t n) {
307 size_t skipN = std::min(n, static_cast<size_t>(std::distance(iter.left, iter.right)));
308 iter.right -= skipN;
309 return skipN;
310 }
311 //}@
312
313 };
314
315 }
316