Stroika Library 3.0d18
 
Loading...
Searching...
No Matches
STLContainerWrapper.h
Go to the documentation of this file.
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Containers_DataStructures_STLContainerWrapper_h_
5#define _Stroika_Foundation_Containers_DataStructures_STLContainerWrapper_h_
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#include "Stroika/Foundation/Common/Common.h"
10#include "Stroika/Foundation/Common/Concepts.h"
12#include "Stroika/Foundation/Containers/Common.h"
14
15/**
16 * \file
17 *
18 * Description:
19 * This module generically wraps STL containers (such as map, vector etc), and facilitates
20 * using them as backends for Stroika containers.
21 *
22 * TODO:
23 *
24 * @todo Replace Contains() with Lookup () - as we did for LinkedList<T>
25 *
26 * @todo Redo Contains1 versus Contains using partial template specialization of STLContainerWrapper - easy
27 * cuz such a trivial class. I can use THAT trick to handle the case of forward_list too. And size...
28 *
29 * @todo Add special subclass of ForwardIterator that tracks PREVPTR - and use to cleanup stuff
30 * that uses forward_list code...
31 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
32 */
33
35
36 namespace Private_ {
37 template <typename T>
38 using has_erase_t = decltype (declval<T&> ().erase (begin (declval<T&> ()), end (declval<T&> ())));
39 template <typename T>
40 constexpr inline bool has_erase_v = Common::is_detected_v<has_erase_t, T>;
41 }
42
43 /**
44 * Use this to wrap an underlying stl container (like std::vector or stl:list, etc) to adapt
45 * it for Stroika containers.
46 *
47 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
48 *
49 */
50 template <typename STL_CONTAINER_OF_T>
51 class STLContainerWrapper : public STL_CONTAINER_OF_T, public Debug::AssertExternallySynchronizedMutex {
52 private:
53 using inherited = STL_CONTAINER_OF_T;
54
55 public:
56 using value_type = typename STL_CONTAINER_OF_T::value_type;
57 using iterator = typename STL_CONTAINER_OF_T::iterator;
58 using const_iterator = typename STL_CONTAINER_OF_T::const_iterator;
59
60 public:
61 /**
62 * Basic (mostly internal) element used by ForwardIterator. Abstract name so can be referenced generically across 'DataStructure' objects
63 */
64 using UnderlyingIteratorRep = const_iterator;
65
66 public:
67 /**
68 * pass through CTOR args to underlying container
69 */
70 template <typename... EXTRA_ARGS>
71 STLContainerWrapper (EXTRA_ARGS&&... args);
72 constexpr STLContainerWrapper (const STLContainerWrapper&) = default;
73 constexpr STLContainerWrapper (STLContainerWrapper&&) noexcept = default;
74
75 public:
76 class ForwardIterator;
77
78 public:
79 /*
80 * Support for COW (CopyOnWrite):
81 *
82 * Take iterator 'pi' which is originally a valid iterator from 'movedFrom' - and replace *pi with a valid
83 * iterator from 'this' - which points at the same logical position. This requires that this container
84 * was just 'copied' from 'movedFrom' - and is used to produce an equivalent iterator (since iterators are tied to
85 * the container they were iterating over).
86 *
87 * // we iterate over old data structure, and new ones at the same time. return true
88 * // when the newI should be considered to 'match' the old I value. NOTE - the argument lambda MAY use other information, like
89 * // the passed in pi forward iterator
90 * bool pointToSameThingTester (oldI, newI)
91 * {
92 * return true if newI now matches oldI;
93 * }
94 *
95 * // For example, to move in an INDEX like situation, just count the number of times pointToSameThingTester called
96 * bool pointToSameThingTester (oldI, newI)
97 * {
98 * return oldI == origIterator->GetOSRep();
99 * }
100 * // For example, to move in an key equals situation
101 * bool pointToSameThingTester (oldI, newI)
102 * {
103 * return origIterator->GetOSRep()->fKey == newI->fKey;
104 * }
105 */
106 template <invocable<typename STL_CONTAINER_OF_T::const_iterator, typename STL_CONTAINER_OF_T::const_iterator> POINT_TO_SAME_THING>
107 nonvirtual void MoveIteratorHereAfterClone (ForwardIterator* pi, const STLContainerWrapper* movedFrom, POINT_TO_SAME_THING&& pointToSameThingTester) const
108 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>)
109 ;
110
111 public:
112 nonvirtual bool contains (Common::ArgByValueType<value_type> item) const;
113
114 public:
115 /**
116 * \note Runtime performance/complexity:
117 * Always: O(N)
118 */
119 template <invocable<typename STL_CONTAINER_OF_T::value_type> FUNCTION>
120 nonvirtual void Apply (FUNCTION&& doToElement) const;
121
122 public:
123 /**
124 * \note Runtime performance/complexity:
125 * Worst Case: O(N)
126 * Typical: O(N), but can be less if systematically finding entries near start of container
127 */
128 template <predicate<typename STL_CONTAINER_OF_T::value_type> FUNCTION>
129 nonvirtual iterator Find (FUNCTION&& firstThat);
130 template <predicate<typename STL_CONTAINER_OF_T::value_type> FUNCTION>
131 nonvirtual const_iterator Find (FUNCTION&& firstThat) const;
132
133 public:
134 template <predicate<typename STL_CONTAINER_OF_T::value_type> PREDICATE>
135 nonvirtual bool FindIf (PREDICATE&& pred) const;
136
137 public:
138 nonvirtual void Invariant () const noexcept;
139
140 public:
141 nonvirtual iterator remove_constness (const_iterator it);
142 };
143
144 /**
145 * STLContainerWrapper::ForwardIterator is a private utility class designed
146 * to promote source code sharing among the patched iterator implementations.
147 *
148 * \note ForwardIterator takes a const-pointer the the container as argument since this
149 * iterator never MODIFIES the container.
150 *
151 * However, it does a const-cast to maintain a non-const pointer since that is needed to
152 * option a non-const iterator pointer, which is needed by some classes that use this, and
153 * there is no zero (or even low for forward_list) cost way to map from const to non const
154 * iterators (needed to perform the update).
155 *
156 * @see http://stroika-bugs.sophists.com/browse/STK-538
157 */
158 template <typename STL_CONTAINER_OF_T>
159 class STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator {
160 public:
161 // stuff STL requires you to set to look like an iterator
162 using iterator_category = forward_iterator_tag;
163 using value_type = STLContainerWrapper::value_type;
164 using difference_type = ptrdiff_t;
165 using pointer = const value_type*;
166 using reference = const value_type&;
167
168 public:
169 /**
170 * /0 overload: sets iterator to 'end' - sentinel
171 * /1 (data) overload: sets iterator to begin
172 * /2 (data,startAt) overload: sets iterator to startAt
173 */
174 constexpr ForwardIterator () noexcept = default;
175 explicit constexpr ForwardIterator (const STLContainerWrapper* data) noexcept;
176 explicit constexpr ForwardIterator (const STLContainerWrapper* data, UnderlyingIteratorRep startAt) noexcept;
177 constexpr ForwardIterator (const ForwardIterator&) noexcept = default;
178 constexpr ForwardIterator (ForwardIterator&&) noexcept = default;
179
180 public:
181 nonvirtual ForwardIterator& operator= (const ForwardIterator&) = default;
182 nonvirtual ForwardIterator& operator= (ForwardIterator&&) noexcept = default;
183
184 public:
185 /**
186 * return true if iterator not Done
187 */
188 explicit operator bool () const;
189
190 public:
191 nonvirtual bool Done () const noexcept;
192
193 public:
194 nonvirtual ForwardIterator& operator++ () noexcept;
195
196 public:
197 nonvirtual const value_type& operator* () const;
198
199 public:
200 nonvirtual const value_type* operator->() const;
201
202 public:
203 /**
204 */
205 nonvirtual size_t CurrentIndex () const;
206
207 public:
208 nonvirtual UnderlyingIteratorRep GetUnderlyingIteratorRep () const;
209
210 public:
211 nonvirtual void SetUnderlyingIteratorRep (UnderlyingIteratorRep l);
212
213 public:
214 nonvirtual bool operator== (const ForwardIterator& rhs) const;
215
216 public:
217 /**
218 * For debugging, assert the iterator data matches argument data
219 */
220 constexpr void AssertDataMatches (const STLContainerWrapper* data) const;
221
222 private:
223 const STLContainerWrapper* fData_{nullptr};
224 const_iterator fStdIterator_{};
225
226 private:
227 friend class STLContainerWrapper;
228 };
229
230 static_assert (ranges::input_range<STLContainerWrapper<vector<int>>>); // smoke test - make sure basic iteration etc should work (allows formattable to work)
231
232}
233
234/*
235 ********************************************************************************
236 ***************************** Implementation Details ***************************
237 ********************************************************************************
238 */
239#include "STLContainerWrapper.inl"
240
241#endif /*_Stroika_Foundation_Containers_DataStructures_STLContainerWrapper_h_ */
nonvirtual void Apply(FUNCTION &&doToElement) const
NOT a real mutex - just a debugging infrastructure support tool so in debug builds can be assured thr...
constexpr void AssertDataMatches(const DoublyLinkedList *data) const
nonvirtual size_t CurrentIndex(const DoublyLinkedList *data) const