Stroika Library 3.0d16
 
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 nonvirtual void MoveIteratorHereAfterClone (ForwardIterator* pi, const STLContainerWrapper* movedFrom) const;
88
89 public:
90 nonvirtual bool contains (Common::ArgByValueType<value_type> item) const;
91
92 public:
93 /**
94 * \note Runtime performance/complexity:
95 * Always: O(N)
96 */
97 template <invocable<typename STL_CONTAINER_OF_T::value_type> FUNCTION>
98 nonvirtual void Apply (FUNCTION&& doToElement) const;
99
100 public:
101 /**
102 * \note Runtime performance/complexity:
103 * Worst Case: O(N)
104 * Typical: O(N), but can be less if systematically finding entries near start of container
105 */
106 template <predicate<typename STL_CONTAINER_OF_T::value_type> FUNCTION>
107 nonvirtual iterator Find (FUNCTION&& firstThat);
108 template <predicate<typename STL_CONTAINER_OF_T::value_type> FUNCTION>
109 nonvirtual const_iterator Find (FUNCTION&& firstThat) const;
110
111 public:
112 template <predicate<typename STL_CONTAINER_OF_T::value_type> PREDICATE>
113 nonvirtual bool FindIf (PREDICATE&& pred) const;
114
115 public:
116 nonvirtual void Invariant () const noexcept;
117
118 public:
119 nonvirtual iterator remove_constness (const_iterator it);
120 };
121
122 /**
123 * STLContainerWrapper::ForwardIterator is a private utility class designed
124 * to promote source code sharing among the patched iterator implementations.
125 *
126 * \note ForwardIterator takes a const-pointer the the container as argument since this
127 * iterator never MODIFIES the container.
128 *
129 * However, it does a const-cast to maintain a non-const pointer since that is needed to
130 * option a non-const iterator pointer, which is needed by some classes that use this, and
131 * there is no zero (or even low for forward_list) cost way to map from const to non const
132 * iterators (needed to perform the update).
133 *
134 * @see http://stroika-bugs.sophists.com/browse/STK-538
135 */
136 template <typename STL_CONTAINER_OF_T>
137 class STLContainerWrapper<STL_CONTAINER_OF_T>::ForwardIterator {
138 public:
139 // stuff STL requires you to set to look like an iterator
140 using iterator_category = forward_iterator_tag;
141 using value_type = STLContainerWrapper::value_type;
142 using difference_type = ptrdiff_t;
143 using pointer = const value_type*;
144 using reference = const value_type&;
145
146 public:
147 /**
148 * /0 overload: sets iterator to 'end' - sentinel
149 * /1 (data) overload: sets iterator to begin
150 * /2 (data,startAt) overload: sets iterator to startAt
151 */
152 constexpr ForwardIterator () noexcept = default;
153 explicit constexpr ForwardIterator (const STLContainerWrapper* data) noexcept;
154 explicit constexpr ForwardIterator (const STLContainerWrapper* data, UnderlyingIteratorRep startAt) noexcept;
155 constexpr ForwardIterator (const ForwardIterator&) noexcept = default;
156 constexpr ForwardIterator (ForwardIterator&&) noexcept = default;
157
158 public:
159 nonvirtual ForwardIterator& operator= (const ForwardIterator&) = default;
160 nonvirtual ForwardIterator& operator= (ForwardIterator&&) noexcept = default;
161
162 public:
163 /**
164 * return true if iterator not Done
165 */
166 explicit operator bool () const;
167
168 public:
169 nonvirtual bool Done () const noexcept;
170
171 public:
172 nonvirtual ForwardIterator& operator++ () noexcept;
173
174 public:
175 nonvirtual const value_type& operator* () const;
176
177 public:
178 nonvirtual const value_type* operator->() const;
179
180 public:
181 /**
182 */
183 nonvirtual size_t CurrentIndex () const;
184
185 public:
186 nonvirtual UnderlyingIteratorRep GetUnderlyingIteratorRep () const;
187
188 public:
189 nonvirtual void SetUnderlyingIteratorRep (UnderlyingIteratorRep l);
190
191 public:
192 nonvirtual bool operator== (const ForwardIterator& rhs) const;
193
194 public:
195 /**
196 * For debugging, assert the iterator data matches argument data
197 */
198 constexpr void AssertDataMatches (const STLContainerWrapper* data) const;
199
200 private:
201 const STLContainerWrapper* fData_{nullptr};
202 const_iterator fStdIterator_{};
203
204 private:
205 friend class STLContainerWrapper;
206 };
207
208 static_assert (ranges::input_range<STLContainerWrapper<vector<int>>>); // smoke test - make sure basic iteration etc should work (allows formattable to work)
209
210}
211
212/*
213 ********************************************************************************
214 ***************************** Implementation Details ***************************
215 ********************************************************************************
216 */
217#include "STLContainerWrapper.inl"
218
219#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