Stroika Library 3.0d24
 
Loading...
Searching...
No Matches
RandomAccessIterator.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Traversal_RandomAccessIterator_h_
5#define _Stroika_Foundation_Traversal_RandomAccessIterator_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include "Stroika/Foundation/Common/Common.h"
11
12/**
13 * \file
14 *
15 * \note Code-Status: <a href="Code-Status.md#Alpha">Alpha</a>
16 */
17
18namespace Stroika::Foundation::Traversal {
19
20 /**
21 * \note Satisfies Concepts:
22 * o regular<RandomAccessIterator<T>> // implies bidirectional_iterator/totally_ordered, and several APIs available, including point at elements
23 * o random_access_iterator<RandomAccessIterator<T>>
24 * o sentinel_for<default_sentinel_t, RandomAccessIterator<T>>
25 * o constructible_from<Iterator<T>, RandomAccessIterator<T>>);
26 * o constructible_from<BidirectionalIterator<T>, RandomAccessIterator<T>>);
27 */
28 template <typename T, typename ITERATOR_TRAITS = Support::DefaultIteratorTraits<T>>
29 class RandomAccessIterator : public BidirectionalIterator<T, ITERATOR_TRAITS> {
30 private:
32
33 public:
34 /*
35 * forward type declarations so can be used more easily in this definition
36 */
37 using difference_type = typename inherited::difference_type;
38 using value_type = typename inherited::value_type;
39 using pointer = typename inherited::pointer;
40 using reference = typename inherited::reference;
41
42 public:
43 /**
44 * \brief iterator_category = random_access_iterator_tag;
45 *
46 * \note this is used by the concept random_access_iterator, and is used to distinguish from bidirectional_iterator.
47 */
48 using iterator_category = random_access_iterator_tag;
49
50 public:
51 class IRep;
52
53 public:
54 /**
55 * \brief This overload is usually not called directly. Instead, iterators are
56 * usually created from a container (eg. Sequence<T>{}.begin()).
57 *
58 * Iterators are safely copyable, preserving their current position.
59 *
60 * CTOR overload taking nullptr - is the same as GetEmptyIterator ()
61 *
62 * \note default construction of RandomAccessIterator means empty (both at start and end).
63 *
64 * \pre RequireNotNull (rep.get ()) for rep-taking CTOR
65 *
66 * \note constructor with argument default_sentinel_t - creates an end iterator
67 */
68 RandomAccessIterator (const unique_ptr<IRep>& rep) noexcept;
69 RandomAccessIterator (unique_ptr<IRep>&& rep) noexcept;
70 RandomAccessIterator (RandomAccessIterator&& src) noexcept = default;
71 RandomAccessIterator (const RandomAccessIterator& src) = default;
72 constexpr RandomAccessIterator (const default_sentinel_t&) noexcept;
73 constexpr RandomAccessIterator (nullptr_t) noexcept;
74 constexpr RandomAccessIterator () noexcept;
75
76 public:
77 /**
78 * \brief Iterators are safely copyable, preserving their current position.
79 */
80 nonvirtual RandomAccessIterator& operator= (RandomAccessIterator&& rhs) noexcept = default;
81 nonvirtual RandomAccessIterator& operator= (const RandomAccessIterator& rhs) = default;
82
83 public:
84 /**
85 * \brief
86 * Advance the iterator by the specified number of positions (which may be negative).
87 * \req i is a valid offset for the iterator. This means that if its positive, it never triggers
88 * an advance PAST the end, and if negative, it never triggers an advance before the start.
89 */
90 nonvirtual void Advance (difference_type i);
91
92 public:
93 /**
94 * \brief
95 * Calculate the difference between this iterator and another.
96 *
97 * \req both iterators of the same type, and one copied FROM the other at some
98 * point (so implies from the same container), or ONE or both of them can be the special
99 * end iterator (default_sentinel or nullptr).
100 */
101 nonvirtual difference_type Difference (const RandomAccessIterator& rhs) const;
102
103 public:
104 /**
105 * \brief same as Iterator::operator++ () - advances iterator - but returns the subclass iterator type.
106 *
107 * The subclass impl is functionaly identical, but hiding the base class implementation needed to satisfy the concepts for random access iterators.
108 */
109 nonvirtual RandomAccessIterator& operator++ ();
110 nonvirtual RandomAccessIterator operator++ (int);
111
112 public:
113 /**
114 * The subclass impl is functionaly identical, but hiding the base class implementation needed to satisfy the concepts for random access iterators.
115 */
116 nonvirtual RandomAccessIterator& operator-- ();
117 nonvirtual RandomAccessIterator operator-- (int);
118
119 public:
120 /**
121 * \brief Produce a new iterator adjusted forward by the specified number of positions (note unlike base class i maybe negative).
122 *
123 * Note this hides the inherited operator+ from BiderectionIterator, just to be a bit faster.
124 */
125 nonvirtual RandomAccessIterator operator+ (difference_type i) const;
126
127 public:
128 /**
129 * \brief Produce a new iterator adjusted backward by the specified number of positions (note unlike base class i maybe negative).
130 *
131 * \note this hides the inherited operator- from BiderectionIterator, and is probably a bit faster.
132 *
133 * \pre current offset - i is a valid position in the referenced container.
134 */
135 nonvirtual RandomAccessIterator operator- (difference_type i) const;
136
137 public:
138 /**
139 * @brief Advance () this iterator by the specified number of positions (which may be negative, but MUST be in range)
140 *
141 * \pre i + current offset is a valid position in the referenced container.
142 */
143 nonvirtual RandomAccessIterator& operator+= (difference_type i);
144
145 public:
146 /**
147 * @brief Advance (backward) this iterator by the specified number of positions (result MUST be in range)
148 *
149 * \pre current offset - i is a valid position in the referenced container.
150 */
151 nonvirtual RandomAccessIterator& operator-= (difference_type i);
152
153 public:
154 /**
155 * @brief Access the element at the specified index (relative to the current position).
156 *
157 * \req this MUST specify a valid position, or its an assertion error.
158 *
159 * API required by random_access_iterator concept
160 *
161 * @param i
162 * @return const T&
163 */
164 nonvirtual const T& operator[] (difference_type i) const;
165
166 public:
167 /**
168 * @brief compare two iterators by their position in underlying container.
169 */
170 nonvirtual strong_ordering operator<=> (const RandomAccessIterator& rhs) const;
171
172 public:
173 /**
174 * @brief addition of iterator and int is commutative.
175 *
176 * \note this friend declares (befriends) the *whole* function template defined in the .inl, via its
177 * own template parameter list (T2, ITERATOR_TRAITS2) - it does NOT reuse this class's own T /
178 * ITERATOR_TRAITS. That's deliberate: this class also has a member `operator+ (difference_type)
179 * const` of the same name, and trying to bind to one specific instantiation via explicit
180 * `operator+<T, ITERATOR_TRAITS>` here gets confused by that member during name lookup (GCC/clang
181 * resolve the unqualified `operator+` to the member, which isn't a template, and reject the
182 * template-id). Befriending the whole template sidesteps that collision entirely.
183 */
184 template <typename T2, typename ITERATOR_TRAITS2>
185 friend RandomAccessIterator<T2, ITERATOR_TRAITS2> operator+ (typename RandomAccessIterator<T2, ITERATOR_TRAITS2>::difference_type i,
186 const RandomAccessIterator<T2, ITERATOR_TRAITS2>& it);
187
188 public:
189 /**
190 * @brief Difference of two iterators is difference_type (number of elements between them)
191 *
192 * \note see note on operator+ above for why this befriends the whole template rather than using
193 * explicit <T, ITERATOR_TRAITS>.
194 */
195 template <typename T2, typename ITERATOR_TRAITS2>
196 friend typename RandomAccessIterator<T2, ITERATOR_TRAITS2>::difference_type
197 operator- (const RandomAccessIterator<T2, ITERATOR_TRAITS2>& lhs, const RandomAccessIterator<T2, ITERATOR_TRAITS2>& rhs);
198
199 public:
200 /**
201 * \brief
202 * Get a reference to the IRep owned by the iterator. This is an implementation detail,
203 * mainly intended for implementors.
204 *
205 * Get a reference to the IRep owned by the iterator.
206 * This is an implementation detail, mainly intended for implementors.
207 */
208 nonvirtual IRep& GetRep ();
209
210 public:
211 /**
212 * \brief
213 * Get a reference to the IRep owned by the iterator. This is an implementation detail,
214 * mainly intended for implementors.
215 *
216 * Get a reference to the IRep owned by the iterator.
217 * This is an implementation detail, mainly intended for implementors.
218 */
219 nonvirtual const IRep& ConstGetRep () const;
220 };
221
222 /**
223 * \brief
224 * The interface for the internal representation of a RandomAccessIterator.
225 *
226 * \note In some sense this adds no new functionality to BidirectionIterator, but the presence
227 * of these virtual Advance and Distance methods adds to code size and is an indicator of
228 * additional functionality.
229 */
230 template <typename T, typename ITERATOR_TRAITS>
231 class RandomAccessIterator<T, ITERATOR_TRAITS>::IRep : public BidirectionalIterator<T, ITERATOR_TRAITS>::IRep {
232 protected:
233 IRep () = default;
234
235 public:
236 /**
237 * \brief
238 * Advance the iterator by the specified number of positions (which CAN be negative).
239 */
240 virtual void Advance (ptrdiff_t i) = 0;
241
242 public:
243 /**
244 * \brief
245 * Calculate the difference between this iterator and another.
246 * \param rhs The other iterator to compare with.
247 * \return The difference between the two iterators.
248 * \note rhs maybe nullptr, and if so, implies the end of the container.
249 */
250 virtual ptrdiff_t Difference (const IRep* rhs) const = 0;
251
252 public:
253 /**
254 * \brief
255 * Peek at the element at the specified position.
256 * \param i The position to peek at.
257 * \return A reference to the element at the specified position.
258 * \req i produces a valid position in the underlying container.
259 *
260 * \note this API is required to support the random access iterator concept (require ... { __j[__n] } -> same_as<iter_reference_t<_It>>;)...
261 */
262 virtual const T* PeekAtElement (ptrdiff_t i) const = 0;
263 };
264
265 // see Satisfies Concepts
266 static_assert (random_access_iterator<RandomAccessIterator<int>>);
267 static_assert (regular<RandomAccessIterator<int>>);
268 static_assert (sentinel_for<default_sentinel_t, RandomAccessIterator<int>>);
269 static_assert (constructible_from<Iterator<int>, RandomAccessIterator<int>>);
270 static_assert (constructible_from<BidirectionalIterator<int>, RandomAccessIterator<int>>);
271
272}
273
274/*
275 ********************************************************************************
276 ******************************* Implementation Details *************************
277 ********************************************************************************
278 */
279
280#include "RandomAccessIterator.inl"
281
282#endif /*_Stroika_Foundation_Traversal_RandomAccessIterator_h_ */
A BidirectionalIterator is an Iterator that can be moved both forward and backward.
The interface for the internal representation of a RandomAccessIterator.
virtual ptrdiff_t Difference(const IRep *rhs) const =0
Calculate the difference between this iterator and another.
virtual void Advance(ptrdiff_t i)=0
Advance the iterator by the specified number of positions (which CAN be negative).
virtual const T * PeekAtElement(ptrdiff_t i) const =0
Peek at the element at the specified position.
nonvirtual IRep & GetRep()
Get a reference to the IRep owned by the iterator. This is an implementation detail,...
nonvirtual const IRep & ConstGetRep() const
Get a reference to the IRep owned by the iterator. This is an implementation detail,...
random_access_iterator_tag iterator_category
iterator_category = random_access_iterator_tag;
nonvirtual difference_type Difference(const RandomAccessIterator &rhs) const
Calculate the difference between this iterator and another.
nonvirtual void Advance(difference_type i)
Advance the iterator by the specified number of positions (which may be negative)....