Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Collection.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4
5/*
6 ********************************************************************************
7 ***************************** Implementation Details ***************************
8 ********************************************************************************
9 */
10
13
15
16 /*
17 ********************************************************************************
18 ******************************** Collection<T> *********************************
19 ********************************************************************************
20 */
21 template <typename T>
23 : inherited{Factory::Collection_Factory<value_type>::Default () ()}
24 {
25 _AssertRepValidType ();
26 }
27 template <typename T>
28 template <IInputIterator<T> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2>
29 inline Collection<T>::Collection (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
30 : Collection{}
31 {
32 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE2> (end));
33 _AssertRepValidType ();
34 }
35 template <typename T>
36 inline Collection<T>::Collection (const shared_ptr<_IRep>& src) noexcept
37 : inherited{src}
38 {
39 RequireNotNull (src);
40 _AssertRepValidType ();
41 }
42 template <typename T>
43 inline Collection<T>::Collection (shared_ptr<_IRep>&& src) noexcept
44 : inherited{(RequireExpression (src != nullptr), move (src))}
45 {
46 _AssertRepValidType ();
47 }
48 template <typename T>
49 inline Collection<T>::Collection (const initializer_list<value_type>& src)
50 : Collection{}
51 {
52 AddAll (src);
53 _AssertRepValidType ();
54 }
55#if !qCompilerAndStdLib_RequiresNotMatchInlineOutOfLineForTemplateClassBeingDefined_Buggy
56 template <typename T>
57 template <IIterableOfTo<T> ITERABLE_OF_ADDABLE>
58 requires (not derived_from<remove_cvref_t<ITERABLE_OF_ADDABLE>, Collection<T>>)
59 inline Collection<T>::Collection (ITERABLE_OF_ADDABLE&& src)
60 : Collection{}
61 {
62 AddAll (forward<ITERABLE_OF_ADDABLE> (src));
63 _AssertRepValidType ();
64 }
65#endif
66 template <typename T>
67 template <Common::IEqualsComparer<T> EQUALS_COMPARER>
68 inline bool Collection<T>::Contains (ArgByValueType<value_type> item, EQUALS_COMPARER&& equalsComparer) const
69 {
70 return this->Find (item, forward<EQUALS_COMPARER> (equalsComparer)) != this->end ();
71 }
72 template <typename T>
73 template <IInputIterator<T> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2>
74 void Collection<T>::AddAll (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
75 {
76 _SafeReadWriteRepAccessor<_IRep> tmp{this};
77 for (auto i = forward<ITERATOR_OF_ADDABLE> (start); i != forward<ITERATOR_OF_ADDABLE2> (end); ++i) {
78 tmp._GetWriteableRep ().Add (*i, nullptr);
79 }
80 }
81 template <typename T>
82 template <IIterableOfTo<T> ITERABLE_OF_ADDABLE>
83 inline void Collection<T>::AddAll (ITERABLE_OF_ADDABLE&& items)
84 {
85 if constexpr (std::is_convertible_v<remove_cvref_t<ITERABLE_OF_ADDABLE>*, Collection<value_type>*>) {
86 // very rare corner case
87 if (static_cast<const Iterable<value_type>*> (this) == static_cast<const Iterable<value_type>*> (&items)) [[unlikely]] {
88 // vector iterator CTOR does't support sentinel for second iterator arg...
89 vector<value_type> copy{std::begin (items), Iterator<value_type>{std::end (items)}}; // because you can not iterate over a container while modifying it
90 AddAll (std::begin (copy), std::end (copy));
91 return;
92 }
93 }
94 AddAll (std::begin (items), std::end (items));
95 }
96 template <typename T>
97 inline void Collection<T>::Add (ArgByValueType<value_type> item)
98 {
99 _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().Add (item, nullptr);
100 Ensure (not this->empty ());
101 }
102 template <typename T>
103 inline void Collection<T>::Add (ArgByValueType<value_type> item, Iterator<T>* addedAt)
104 {
105 RequireNotNull (addedAt);
106 _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().Add (item, addedAt);
107 Ensure (not this->empty ());
108 Ensure (not addedAt->Done ());
109 }
110 template <typename T>
111 inline void Collection<T>::Update (const Iterator<value_type>& i, ArgByValueType<value_type> newValue, Iterator<value_type>* nextI)
112 {
113 Require (not i.Done ());
114 auto [writerRep, patchedIterator] = _GetWritableRepAndPatchAssociatedIterator (i);
115 writerRep->Update (patchedIterator, newValue, nextI);
116 }
117 template <typename T>
119 {
120 Require (not i.Done ());
121 auto [writerRep, patchedIterator] = _GetWritableRepAndPatchAssociatedIterator (i);
122 writerRep->Remove (patchedIterator, nextI);
123 }
124 template <typename T>
125 template <Common::IPotentiallyComparer<T> EQUALS_COMPARER>
126 inline void Collection<T>::Remove (ArgByValueType<value_type> item, EQUALS_COMPARER&& equalsComparer)
127 {
128 auto i = this->Find (item, forward<EQUALS_COMPARER> (equalsComparer));
129 Require (i != this->end ()); // use remove-if if the item might not exist
130 auto [writerRep, patchedIterator] = _GetWritableRepAndPatchAssociatedIterator (i);
131 writerRep->Remove (patchedIterator, nullptr);
132 }
133 template <typename T>
134 template <Common::IEqualsComparer<T> EQUALS_COMPARER>
135 inline bool Collection<T>::RemoveIf (ArgByValueType<value_type> item, EQUALS_COMPARER&& equalsComparer)
136 {
137 if (auto i = this->Find (item, forward<EQUALS_COMPARER> (equalsComparer))) {
138 auto [writerRep, patchedIterator] = _GetWritableRepAndPatchAssociatedIterator (i);
139 writerRep->Remove (patchedIterator, nullptr);
140 return true;
141 }
142 return false;
143 }
144 template <typename T>
145 template <predicate<T> PREDICATE>
146 bool Collection<T>::RemoveIf (PREDICATE&& p)
148 if (auto i = this->Find (forward<PREDICATE> (p))) {
149 Remove (i);
150 return true;
151 }
152 return false;
153 }
154 template <typename T>
156 {
157 _SafeReadRepAccessor<_IRep> tmp{this}; // important to use READ not WRITE accessor, because write accessor would have already cloned the data
158 if (not tmp._ConstGetRep ().empty ()) {
159 this->_fRep = tmp._ConstGetRep ().CloneEmpty ();
160 }
161 }
162 template <typename T>
163 template <Common::IEqualsComparer<T> EQUALS_COMPARER>
164 size_t Collection<T>::RemoveAll (const Iterator<value_type>& start, const Iterator<value_type>& end, EQUALS_COMPARER&& equalsComparer)
165 {
166 size_t cnt{};
167 for (auto i = start; i != end;) {
168 if (RemoveIf (*i, equalsComparer, &i)) {
169 ++cnt;
170 }
171 }
172 return cnt;
173 }
174 template <typename T>
175 template <IIterableOfTo<T> ITERABLE_OF_ADDABLE, typename EQUALS_COMPARER>
176 inline size_t Collection<T>::RemoveAll (const ITERABLE_OF_ADDABLE& c, EQUALS_COMPARER&& equalsComparer)
177 {
178 if (static_cast<const void*> (this) == static_cast<const void*> (addressof (c))) {
179 return RemoveAll (forward<EQUALS_COMPARER> (equalsComparer));
180 }
181 else {
182 return RemoveAll (std::begin (c), std::end (c), forward<EQUALS_COMPARER> (equalsComparer));
183 }
184 }
185 template <typename T>
186 template <predicate<T> PREDICATE>
187 size_t Collection<T>::RemoveAll (PREDICATE&& p)
188 {
189 size_t nRemoved{};
190 for (Iterator<T> i = this->begin (); i != this->end ();) {
191 if (p (*i)) {
192 Remove (i, &i);
193 ++nRemoved;
194 }
195 else {
196 ++i;
197 }
198 }
199 return nRemoved;
200 }
201 template <typename T>
202 inline void Collection<T>::clear ()
203 {
204 RemoveAll ();
205 }
206 template <typename T>
207 template <Common::IEqualsComparer<T> EQUALS_COMPARER>
208 inline void Collection<T>::erase (ArgByValueType<value_type> item, EQUALS_COMPARER&& equalsComparer)
209 {
210 Remove (item, forward<EQUALS_COMPARER> (equalsComparer));
211 }
212 template <typename T>
213 inline auto Collection<T>::erase (const Iterator<value_type>& i) -> Iterator<value_type>
214 {
215 Iterator<value_type> nextI{nullptr};
216 Remove (i, &nextI);
217 return nextI;
218 }
219 template <typename T>
220 template <typename RESULT_CONTAINER, invocable<T> ELEMENT_MAPPER>
221 inline RESULT_CONTAINER Collection<T>::Map (ELEMENT_MAPPER&& elementMapper) const
222 requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, typename RESULT_CONTAINER::value_type> or
223 convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, optional<typename RESULT_CONTAINER::value_type>>)
224 {
225 if constexpr (same_as<RESULT_CONTAINER, Collection>) {
226 // clone the rep so we retain any ordering function/etc, rep type
227 return inherited::template Map<RESULT_CONTAINER> (forward<ELEMENT_MAPPER> (elementMapper),
228 RESULT_CONTAINER{_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().CloneEmpty ()});
229 }
230 else {
231 return inherited::template Map<RESULT_CONTAINER> (forward<ELEMENT_MAPPER> (elementMapper)); // default Iterable<> implementation then...
232 }
233 }
234 template <typename T>
235 template <derived_from<Iterable<T>> RESULT_CONTAINER, predicate<T> INCLUDE_PREDICATE>
236 inline RESULT_CONTAINER Collection<T>::Where (INCLUDE_PREDICATE&& includeIfTrue) const
237 {
238 if constexpr (same_as<RESULT_CONTAINER, Collection>) {
239 // clone the rep so we retain any ordering function/etc, rep type
240 return inherited::template Where<RESULT_CONTAINER> (
241 forward<INCLUDE_PREDICATE> (includeIfTrue), RESULT_CONTAINER{_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().CloneEmpty ()});
242 }
243 else {
244 return inherited::template Where<RESULT_CONTAINER> (forward<INCLUDE_PREDICATE> (includeIfTrue)); // default Iterable<> implementation then...
245 }
246 }
247 template <typename T>
248 inline auto Collection<T>::operator+= (ArgByValueType<value_type> item) -> Collection&
249 {
250 Add (item);
251 return *this;
252 }
253 template <typename T>
255 {
256 AddAll (items);
257 return *this;
258 }
259 template <typename T>
260 auto Collection<T>::_GetWritableRepAndPatchAssociatedIterator (const Iterator<value_type>& i) -> tuple<_IRep*, Iterator<value_type>>
261 {
262 Require (not i.Done ());
263 using element_type = typename inherited::_SharedByValueRepType::element_type;
264 Iterator<value_type> patchedIterator = i;
265 element_type* writableRep = this->_fRep.rwget ([&] (const element_type& prevRepPtr) -> typename inherited::_SharedByValueRepType::shared_ptr_type {
266 return Debug::UncheckedDynamicCast<const _IRep&> (prevRepPtr).CloneAndPatchIterator (&patchedIterator);
267 });
268 AssertNotNull (writableRep);
269 return make_tuple (Debug::UncheckedDynamicCast<_IRep*> (writableRep), move (patchedIterator));
270 }
271 template <typename T>
272 inline void Collection<T>::_AssertRepValidType () const
273 {
275 _SafeReadRepAccessor<_IRep>{this};
276 }
277 }
278
279 /*
280 ********************************************************************************
281 ********************************* operator+ ************************************
282 ********************************************************************************
283 */
284 template <typename T>
286 {
287 Collection<T> result{lhs};
288 result += rhs;
289 return result;
290 }
291 template <typename T>
292 Collection<T> operator+ (const Collection<T>& lhs, const Iterable<T>& rhs)
293 {
294 Collection<T> result{lhs};
295 result += rhs;
296 return result;
297 }
298 template <typename T>
299 Collection<T> operator+ (const Collection<T>& lhs, const Collection<T>& rhs)
300 {
301 Collection<T> result{lhs};
302 result += rhs;
303 return result;
304 }
305}
#define AssertNotNull(p)
Definition Assertions.h:333
#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
#define RequireExpression(c)
Definition Assertions.h:267
A Collection<T> is a container to manage an un-ordered collection of items, without equality defined ...
Definition Collection.h:102
nonvirtual void AddAll(ITERATOR_OF_ADDABLE &&start, ITERATOR_OF_ADDABLE2 &&end)
typename inherited::value_type value_type
Definition Collection.h:116
nonvirtual void Update(const Iterator< value_type > &i, ArgByValueType< value_type > newValue, Iterator< value_type > *nextI=nullptr)
nonvirtual bool Contains(ArgByValueType< value_type > item, EQUALS_COMPARER &&equalsComparer={}) const
Compares items with TRAITS::EqualsCompareFunctionType::Equals, and returns true if any match.
nonvirtual void Remove(ArgByValueType< value_type > item, EQUALS_COMPARER &&equalsComparer={})
Remove () the argument value (which must exist)
nonvirtual RESULT_CONTAINER Map(ELEMENT_MAPPER &&elementMapper) const
'override' Iterable<>::Map () function so RESULT_CONTAINER defaults to Collection,...
nonvirtual void erase(ArgByValueType< value_type > item, EQUALS_COMPARER &&equalsComparer={})
nonvirtual bool RemoveIf(ArgByValueType< value_type > item, EQUALS_COMPARER &&equalsComparer={})
RemoveIf () the (the first matching) argument value, if present. Returns true if item removed.
nonvirtual RESULT_CONTAINER Where(INCLUDE_PREDICATE &&includeIfTrue) const
return a subset of the Collection for which includeIfTrue returns true.
nonvirtual void Add(ArgByValueType< value_type > item)
nonvirtual tuple< _IRep *, Iterator< value_type > > _GetWritableRepAndPatchAssociatedIterator(const Iterator< value_type > &i)
Utility to get WRITABLE underlying shared_ptr (replacement for what we normally do - _SafeReadWriteRe...
nonvirtual Collection & operator+=(ArgByValueType< value_type > item)
nonvirtual void RemoveAll()
RemoveAll removes all, or all matching (predicate, iterator range, equals comparer or whatever) items...
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237
static constexpr default_sentinel_t end() noexcept
Support for ranged for, and STL syntax in general.
An Iterator<T> is a copyable object which allows traversing the contents of some container....
Definition Iterator.h:225
nonvirtual bool Done() const
Done () means there is nothing left in this iterator (a synonym for (it == container....
Definition Iterator.inl:147
Collection< T > operator+(const Iterable< T > &lhs, const Collection< T > &rhs)