Stroika Library 3.0d24
 
Loading...
Searching...
No Matches
STLContainerWrapper.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#include <algorithm>
5
7
9
10 namespace Private_ {
11 template <typename T, typename A>
12 constexpr bool IsStdForwardList_ (forward_list<T, A>*)
13 {
14 return true;
15 }
16 constexpr bool IsStdForwardList_ (...)
17 {
18 return false;
19 }
20 template <typename T>
21 constexpr bool IsStdForwardList ()
22 {
23 return IsStdForwardList_ ((T*)nullptr);
24 }
25 }
26
27// Would like to leave on by default but we just added and cannot afford to have debug builds get that slow
28#ifndef qStroika_Foundation_Containers_DataStructures_STLContainerWrapper_IncludeSlowDebugChecks_
29#define qStroika_Foundation_Containers_DataStructures_STLContainerWrapper_IncludeSlowDebugChecks_ 0
30#endif
31
32 /*
33 ********************************************************************************
34 ******************* STLContainerWrapper<STL_CONTAINER_OF_T> ********************
35 ********************************************************************************
36 */
37 template <typename STL_CONTAINER_OF_T>
38 template <typename... EXTRA_ARGS>
40 : inherited{forward<EXTRA_ARGS> (args)...}
41 {
42 }
43 template <typename STL_CONTAINER_OF_T>
45 {
46 AssertExternallySynchronizedChecker::ReadContext declareContext{*this};
47 return this->find (item) != this->end ();
48 }
49 template <typename STL_CONTAINER_OF_T>
50 template <invocable<typename STL_CONTAINER_OF_T::const_iterator, typename STL_CONTAINER_OF_T::const_iterator> POINT_TO_SAME_THING>
51 void STLContainerWrapper<STL_CONTAINER_OF_T>::MoveIteratorHereAfterClone (ForwardIterator* pi, const STLContainerWrapper* movedFrom,
52 [[maybe_unused]] POINT_TO_SAME_THING&& pointToSameThingTester) const
53 requires (convertible_to<invoke_result_t<POINT_TO_SAME_THING, typename STL_CONTAINER_OF_T::const_iterator, typename STL_CONTAINER_OF_T::const_iterator>, bool>)
54 {
55 AssertExternallySynchronizedChecker::ReadContext declareContext{*this};
56 // TRICKY TODO - BUT MUST DO - MUST MOVE FROM OLD ITER TO NEW
57 // only way
58 //
59 // For STL containers, not sure how to find an equiv new iterator for an old one, but my best guess is to iterate through
60 // old for old, and when I match, stop on new
61 pi->AssertDataMatches (movedFrom);
62 auto newI = this->begin ();
63 [[maybe_unused]] auto newE = this->end ();
64 auto oldI = movedFrom->begin ();
65 [[maybe_unused]] auto oldE = movedFrom->end ();
66 while (not forward<POINT_TO_SAME_THING> (pointToSameThingTester) (oldI, newI)) {
67 Assert (newI != newE);
68 Assert (oldI != oldE);
69 ++newI;
70 ++oldI;
71 Assert (newI != newE);
72 Assert (oldI != oldE);
73 }
74 Assert (oldI == pi->_fStdIterator);
75 pi->_fStdIterator = newI;
76 pi->_fData = this;
77 }
78 template <typename STL_CONTAINER_OF_T>
79 template <invocable<typename STL_CONTAINER_OF_T::value_type> FUNCTION>
80 void STLContainerWrapper<STL_CONTAINER_OF_T>::Apply (FUNCTION&& doToElement) const
81 {
82 AssertExternallySynchronizedChecker::ReadContext declareContext{*this};
83 for (auto i = this->begin (); i != this->end (); ++i) {
84 (doToElement) (*i);
85 }
86 }
87 template <typename STL_CONTAINER_OF_T>
88 template <predicate<typename STL_CONTAINER_OF_T ::value_type> FUNCTION>
89 auto STLContainerWrapper<STL_CONTAINER_OF_T>::Find (FUNCTION&& firstThat) const -> const_iterator
90 {
91 AssertExternallySynchronizedChecker::ReadContext declareContext{*this};
92 for (auto i = this->begin (); i != this->end (); ++i) {
93 if (firstThat (*i)) {
94 return i;
95 }
96 }
97 return this->end ();
98 }
99 template <typename STL_CONTAINER_OF_T>
100 template <predicate<typename STL_CONTAINER_OF_T ::value_type> FUNCTION>
101 auto STLContainerWrapper<STL_CONTAINER_OF_T>::Find (FUNCTION&& firstThat) -> iterator
102 {
104 for (auto i = this->begin (); i != this->end (); ++i) {
105 if (firstThat (*i)) {
106 return i;
107 }
108 }
109 return this->end ();
110 }
111 template <typename STL_CONTAINER_OF_T>
112 template <predicate<typename STL_CONTAINER_OF_T::value_type> PREDICATE>
113 inline bool STLContainerWrapper<STL_CONTAINER_OF_T>::FindIf (PREDICATE&& pred) const
114 {
115 AssertExternallySynchronizedChecker::ReadContext declareContext{*this};
116 return find_if (this->begin (), this->end (), forward<PREDICATE> (pred)) != this->end ();
117 }
118 template <typename STL_CONTAINER_OF_T>
119 inline void STLContainerWrapper<STL_CONTAINER_OF_T>::Invariant () const noexcept
120 {
121 }
122 template <typename STL_CONTAINER_OF_T>
123 inline auto STLContainerWrapper<STL_CONTAINER_OF_T>::remove_constness (const_iterator it) -> iterator
124 {
125 // http://stackoverflow.com/questions/765148/how-to-remove-constness-of-const-iterator
126 if constexpr (Private_::IsStdForwardList<STL_CONTAINER_OF_T> ()) {
127 return this->erase_after (it, it);
128 }
129 else {
130 return this->erase (it, it);
131 }
132 }
133
134 /*
135 ********************************************************************************
136 *********** STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator ***********
137 ********************************************************************************
138 */
139 template <typename STL_CONTAINER_OF_T>
140 constexpr STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::ForwardIterator (const STLContainerWrapper* data, UnderlyingIteratorRep startAt) noexcept
141 : _fData{data}
142 , _fStdIterator{startAt}
143 {
144 RequireNotNull (data);
145 }
146 template <typename STL_CONTAINER_OF_T>
147 constexpr STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::ForwardIterator (const STLContainerWrapper* data) noexcept
148 : ForwardIterator{data, (RequireExpression (data != nullptr), data->cbegin ())}
149 {
150 }
151 template <typename STL_CONTAINER_OF_T>
153 {
154 return not AtEnd ();
155 }
156 template <typename STL_CONTAINER_OF_T>
158 {
159#if qStroika_Foundation_Containers_DataStructures_STLContainerWrapper_IncludeSlowDebugChecks_
160 AssertExternallySynchronizedChecker::ReadContext declareContext{*_fData};
161#endif
162 AssertNotNull (_fData);
163 return _fStdIterator == _fData->end ();
164 }
165 template <typename STL_CONTAINER_OF_T>
166 inline auto STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::operator++ () noexcept -> ForwardIterator&
167 {
168 Require (not AtEnd ());
169 ++_fStdIterator;
170 return *this;
171 }
172 template <typename STL_CONTAINER_OF_T>
173 inline auto STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::operator++ (int) noexcept -> ForwardIterator
174 {
175 ForwardIterator result{*this};
176 this->operator++ ();
177 return result;
178 }
179 template <typename STL_CONTAINER_OF_T>
180 inline auto STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::operator* () const -> const value_type&
181 {
182 AssertExternallySynchronizedChecker::ReadContext declareContext{*_fData};
183 AssertNotNull (_fData);
184 Require (not AtEnd ());
185 return *_fStdIterator;
186 }
187 template <typename STL_CONTAINER_OF_T>
188 inline auto STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::operator->() const -> const value_type*
189 {
190 AssertExternallySynchronizedChecker::ReadContext declareContext{*_fData};
191 AssertNotNull (_fData);
192 Require (not AtEnd ());
193 return &*_fStdIterator;
194 }
195 template <typename STL_CONTAINER_OF_T>
196 inline size_t STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::CurrentIndex () const
197 {
198 AssertExternallySynchronizedChecker::ReadContext declareContext{*_fData};
199 AssertNotNull (_fData);
200 return static_cast<size_t> (std::distance (_fData->begin (), _fStdIterator));
201 }
202 template <typename STL_CONTAINER_OF_T>
203 inline auto STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::GetUnderlyingIteratorRep () const -> UnderlyingIteratorRep
204 {
205 AssertExternallySynchronizedChecker::ReadContext declareContext{*_fData};
206 return _fStdIterator;
207 }
208 template <typename STL_CONTAINER_OF_T>
209 inline void STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator::SetUnderlyingIteratorRep (UnderlyingIteratorRep l)
210 {
211 AssertExternallySynchronizedChecker::ReadContext declareContext{*_fData}; // read lock on data, though writing to this iterator
212 _fStdIterator = l;
213 }
214 template <typename STL_CONTAINER_OF_T>
216 {
217#if qStroika_Foundation_Debug_AssertionsChecked
218 Require (data == _fData);
219#endif
220 }
221 template <typename STL_CONTAINER_OF_T>
223 {
224 AssertExternallySynchronizedChecker::ReadContext declareContext{*_fData};
225 return _fStdIterator == rhs._fStdIterator;
226 }
227
228 /*
229 ********************************************************************************
230 ******** STLContainerWrapper<STL_CONTAINER_OF_T>::BidirectionalIterator ********
231 ********************************************************************************
232 */
233 template <typename STL_CONTAINER_OF_T>
235 {
236 inherited::operator++ ();
237 return *this;
238 }
239 template <typename STL_CONTAINER_OF_T>
241 {
242 BidirectionalIterator result{*this};
243 this->operator++ ();
244 return result;
245 }
246 template <typename STL_CONTAINER_OF_T>
247 inline bool STLContainerWrapper<STL_CONTAINER_OF_T>::BidirectionalIterator::AtStart () const noexcept
248 {
249 AssertNotNull (this->_fData);
250 return this->_fStdIterator == this->_fData->begin ();
251 }
252 template <typename STL_CONTAINER_OF_T>
254 {
255 Require (not this->AtStart ());
256 --this->_fStdIterator;
257 return *this;
258 }
259 template <typename STL_CONTAINER_OF_T>
262 BidirectionalIterator result{*this};
263 this->operator-- ();
264 return result;
265 }
266
267 /*
268 ********************************************************************************
269 ********* STLContainerWrapper<STL_CONTAINER_OF_T>::RandomAccessIterator ********
270 ********************************************************************************
271 */
272 template <typename STL_CONTAINER_OF_T>
274 {
275 inherited::operator++ ();
276 return *this;
277 }
278 template <typename STL_CONTAINER_OF_T>
280 {
281 RandomAccessIterator result{*this};
282 this->operator++ ();
283 return result;
284 }
285 template <typename STL_CONTAINER_OF_T>
286 inline auto STLContainerWrapper<STL_CONTAINER_OF_T>::RandomAccessIterator::operator-- () noexcept -> RandomAccessIterator&
287 {
288 inherited::operator-- ();
289 return *this;
290 }
291 template <typename STL_CONTAINER_OF_T>
292 inline auto STLContainerWrapper<STL_CONTAINER_OF_T>::RandomAccessIterator::operator-- (int) noexcept -> RandomAccessIterator
293 {
294 RandomAccessIterator result{*this};
295 this->operator-- ();
296 return result;
297 }
298 template <typename STL_CONTAINER_OF_T>
299 inline auto STLContainerWrapper<STL_CONTAINER_OF_T>::RandomAccessIterator::operator+ (difference_type i) const -> RandomAccessIterator
300 {
301 RandomAccessIterator result{*this};
302 result += i;
303 return result;
304 }
305 template <typename STL_CONTAINER_OF_T>
306 inline auto STLContainerWrapper<STL_CONTAINER_OF_T>::RandomAccessIterator::operator- (difference_type i) const -> RandomAccessIterator
307 {
308 RandomAccessIterator result{*this};
309 result -= i;
310 return result;
311 }
312 template <typename STL_CONTAINER_OF_T>
314 {
315 AssertNotNull (this->_fData);
316 [[maybe_unused]] difference_type newIdx = static_cast<difference_type> (this->CurrentIndex ()) + i;
317 Require (newIdx >= 0 and static_cast<size_t> (newIdx) <= this->_fData->size ());
318 this->_fStdIterator += i;
319 return *this;
320 }
321 template <typename STL_CONTAINER_OF_T>
322 inline auto STLContainerWrapper<STL_CONTAINER_OF_T>::RandomAccessIterator::operator-= (difference_type i) -> RandomAccessIterator&
324 return this->operator+= (-i);
325 }
326 template <typename STL_CONTAINER_OF_T>
327 inline auto STLContainerWrapper<STL_CONTAINER_OF_T>::RandomAccessIterator::operator[] (difference_type i) const -> const value_type&
328 {
329 AssertNotNull (this->_fData);
330 return *(this->_fStdIterator + i);
331 }
332 template <typename STL_CONTAINER_OF_T>
334 {
335 return (*this - rhs) <=> 0;
336 }
337
338}
#define AssertNotNull(p)
Definition Assertions.h:334
#define RequireNotNull(p)
Definition Assertions.h:348
#define RequireExpression(c)
Definition Assertions.h:268
nonvirtual BidirectionalIterator & operator++() noexcept
same as inherited operator++ () - advances iterator - but returning the subclass iterator type.
like BidirectionalIterator, but adding random access (operator+=, operator[], etc).
nonvirtual const value_type & operator[](difference_type i) const
access the element at the specified index, relative to the current position.
friend difference_type operator-(const RandomAccessIterator &lhs, const RandomAccessIterator &rhs)
difference between two iterators - handling the 'sentinel' (default-constructed, _fData == nullptr,...
nonvirtual RandomAccessIterator & operator++() noexcept
same as inherited operator++ ()/operator-- () - but returning the subclass iterator type.
nonvirtual void Apply(FUNCTION &&doToElement) const
unique_lock< AssertExternallySynchronizedChecker > WriteContext
Instantiate AssertExternallySynchronizedChecker::WriteContext to designate an area of code where prot...
A BidirectionalIterator is an Iterator that can be moved both forward and backward.
conditional_t<(sizeof(CHECK_T)<=2 *sizeof(void *)) and is_trivially_copyable_v< CHECK_T >, CHECK_T, const CHECK_T & > ArgByValueType
This is an alias for 'T' - but how we want to pass it on stack as formal parameter.
Definition TypeHints.h:36
nonvirtual ForwardIterator & operator++() noexcept
nonvirtual size_t CurrentIndex(const DoublyLinkedList *data) const