Stroika Library 3.0d18
 
Loading...
Searching...
No Matches
IteratorImplHelper.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include <random>
5
8
10
11 /*
12 ********************************************************************************
13 *************************** ContainerDebugChangeCounts_ ************************
14 ********************************************************************************
15 */
16#if qStroika_Foundation_Debug_AssertionsChecked
17 inline ContainerDebugChangeCounts_::ChangeCountType ContainerDebugChangeCounts_::mkInitial_ ()
18 {
19 // use random number so when we assign new object we are more likely to detect bad iterators (dangling)
20 random_device rd;
21 mt19937 gen{rd ()};
22 uniform_int_distribution<ChangeCountType> distrib{1, 1000};
23 return distrib (gen);
24 }
25#endif
26 inline ContainerDebugChangeCounts_::ContainerDebugChangeCounts_ ()
27#if qStroika_Foundation_Debug_AssertionsChecked
28 : fChangeCount{mkInitial_ ()}
29#endif
30 {
31 }
32 inline ContainerDebugChangeCounts_::ContainerDebugChangeCounts_ ([[maybe_unused]] const ContainerDebugChangeCounts_& src)
33#if qStroika_Foundation_Debug_AssertionsChecked
34 : fDeleted{src.fDeleted}
35 , fChangeCount{src.fChangeCount.load ()}
36#endif
37 {
38 }
39 inline ContainerDebugChangeCounts_::~ContainerDebugChangeCounts_ ()
40 {
41#if qStroika_Foundation_Debug_AssertionsChecked
42 fDeleted = true;
43#endif
44 }
45 inline void ContainerDebugChangeCounts_::PerformedChange ()
46 {
47#if qStroika_Foundation_Debug_AssertionsChecked
48 ++fChangeCount;
49#endif
50 }
51
52 /*
53 ********************************************************************************
54 ************ IteratorImplHelper_<T, DATASTRUCTURE_CONTAINER, TRAITS> ***********
55 ********************************************************************************
56 */
57 template <typename T, typename DATASTRUCTURE_CONTAINER, typename TRAITS>
58 template <typename... ADDITIONAL_BACKEND_ITERATOR_CTOR_ARGUMENTS>
59 inline IteratorImplHelper_<T, DATASTRUCTURE_CONTAINER, TRAITS>::IteratorImplHelper_ (const DATASTRUCTURE_CONTAINER* data,
60 [[maybe_unused]] const ContainerDebugChangeCounts_* changeCounter,
61 ADDITIONAL_BACKEND_ITERATOR_CTOR_ARGUMENTS&&... args)
62 requires (constructible_from<DATASTRUCTURE_CONTAINER_ITERATOR, const DATASTRUCTURE_CONTAINER*, ADDITIONAL_BACKEND_ITERATOR_CTOR_ARGUMENTS...>)
63 : fIterator{data, forward<ADDITIONAL_BACKEND_ITERATOR_CTOR_ARGUMENTS> (args)...}
65 , fChangeCounter{changeCounter}
66 , fLastCapturedChangeCount{(changeCounter == nullptr) ? 0 : changeCounter->fChangeCount.load ()}
67#endif
68 {
69 RequireNotNull (data);
70 }
71 template <typename T, typename DATASTRUCTURE_CONTAINER, typename TRAITS>
72 template <typename... ADDITIONAL_BACKEND_ITERATOR_CTOR_ARGUMENTS>
73 inline IteratorImplHelper_<T, DATASTRUCTURE_CONTAINER, TRAITS>::IteratorImplHelper_ ([[maybe_unused]] const ContainerDebugChangeCounts_* changeCounter,
74 ADDITIONAL_BACKEND_ITERATOR_CTOR_ARGUMENTS&&... args)
75 requires (constructible_from<DATASTRUCTURE_CONTAINER_ITERATOR, ADDITIONAL_BACKEND_ITERATOR_CTOR_ARGUMENTS...>)
76 : fIterator{forward<ADDITIONAL_BACKEND_ITERATOR_CTOR_ARGUMENTS> (args)...}
78 , fChangeCounter{changeCounter}
79 , fLastCapturedChangeCount{(changeCounter == nullptr) ? 0 : changeCounter->fChangeCount.load ()}
80#endif
81 {
82 }
83 template <typename T, typename DATASTRUCTURE_CONTAINER, typename TRAITS>
84 auto IteratorImplHelper_<T, DATASTRUCTURE_CONTAINER, TRAITS>::Clone () const -> unique_ptr<typename Iterator<T>::IRep>
85 {
86 ValidateChangeCount ();
87 return make_unique<IteratorImplHelper_> (*this);
88 }
89 template <typename T, typename DATASTRUCTURE_CONTAINER, typename TRAITS>
91 {
92 RequireNotNull (result); // API says result ptr required
93 ValidateChangeCount ();
94 // Typically calls have advance = true
95 if (advance) [[likely]] {
96 Require (not fIterator.Done ());
97 ++fIterator;
98 }
99 if (fIterator.Done ()) [[unlikely]] {
100 *result = nullopt;
101 }
102 else {
103 *result = TRAITS::ConvertDataStructureIterationResult2ContainerIteratorResult (*fIterator);
104 }
105 }
106 template <typename T, typename DATASTRUCTURE_CONTAINER, typename TRAITS>
108 {
109 RequireNotNull (rhs);
110 using ActualIterImplType_ = IteratorImplHelper_;
111 const ActualIterImplType_* rrhs = Debug::UncheckedDynamicCast<const ActualIterImplType_*> (rhs);
112 return fIterator == rrhs->fIterator;
113 }
114#if qStroika_Foundation_Debug_AssertionsChecked
115 template <typename T, typename DATASTRUCTURE_CONTAINER, typename TRAITS>
116 void IteratorImplHelper_<T, DATASTRUCTURE_CONTAINER, TRAITS>::Invariant () const noexcept
117 {
118 ValidateChangeCount ();
119 }
120#endif
121 template <typename T, typename DATASTRUCTURE_CONTAINER, typename TRAITS>
123 {
124#if qStroika_Foundation_Debug_AssertionsChecked
125 if (fChangeCounter != nullptr) {
126 fLastCapturedChangeCount = fChangeCounter->fChangeCount;
127 }
128#endif
129 }
130 template <typename T, typename DATASTRUCTURE_CONTAINER, typename TRAITS>
132 {
133#if qStroika_Foundation_Debug_AssertionsChecked
134 if (fChangeCounter != nullptr) {
135 Require (not fChangeCounter->fDeleted); // if this is triggered, it means the container changed so drastically that its rep was deleted
136 Require (fChangeCounter->fChangeCount == fLastCapturedChangeCount); // if this fails, it almost certainly means you are using a stale iterator
137 }
138#endif
139 }
140
141}
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
Definition Assertions.h:48
#define RequireNotNull(p)
Definition Assertions.h:347
helper to wrap a low level 'DataStructure Container Iterator' into a 'Stroika' Iterator::IRep iterato...
virtual void More(optional< T > *result, bool advance) override
virtual unique_ptr< typename Iterator< T >::IRep > Clone() const override
Implementation detail for iterator implementors.
Definition Iterator.h:599
An Iterator<T> is a copyable object which allows traversing the contents of some container....
Definition Iterator.h:225