Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
MultiSet.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4
8
10
11 /*
12 ********************************************************************************
13 ************************* MultiSet<T, TRAITS>::_IRep ***************************
14 ********************************************************************************
15 */
16 template <typename T, typename TRAITS>
17 bool MultiSet<T, TRAITS>::_IRep::_Equals_Reference_Implementation (const _IRep& rhs) const
18 {
19 if (this == &rhs) {
20 return true;
21 }
22 if (this->size () != rhs.size ()) {
23 return false;
24 }
25 for (auto i = this->MakeIterator (); not i.Done (); ++i) {
26 if (i->fCount != rhs.OccurrencesOf (i->fValue)) {
27 return false;
28 }
29 }
30 return true;
31 }
32
33 /*
34 ********************************************************************************
35 ***************************** MultiSet<T, TRAITS> ******************************
36 ********************************************************************************
37 */
38 template <typename T, typename TRAITS>
40 requires (IEqualsComparer<equal_to<T>, T>)
41 : MultiSet{equal_to<T>{}}
42 {
43 _AssertRepValidType ();
44 }
45 template <typename T, typename TRAITS>
46 template <IEqualsComparer<T> EQUALS_COMPARER>
47 inline MultiSet<T, TRAITS>::MultiSet (EQUALS_COMPARER&& equalsComparer)
48 : inherited{Factory::MultiSet_Factory<T, TRAITS, remove_cvref_t<EQUALS_COMPARER>>::Default () (forward<EQUALS_COMPARER> (equalsComparer))}
49 {
50 _AssertRepValidType ();
51 }
52#if !qCompilerAndStdLib_RequiresNotMatchInlineOutOfLineForTemplateClassBeingDefined_Buggy
53 template <typename T, typename TRAITS>
54 template <IIterableOfTo<typename TRAITS::CountedValueType> ITERABLE_OF_ADDABLE>
55 inline MultiSet<T, TRAITS>::MultiSet (ITERABLE_OF_ADDABLE&& src)
56 requires (IEqualsComparer<equal_to<T>, T> and not derived_from<remove_cvref_t<ITERABLE_OF_ADDABLE>, MultiSet<T, TRAITS>>)
57 : MultiSet{}
58 {
59 AddAll (forward<ITERABLE_OF_ADDABLE> (src));
60 _AssertRepValidType ();
61 }
62#endif
63 template <typename T, typename TRAITS>
64 template <IEqualsComparer<T> EQUALS_COMPARER, IIterableOfTo<typename TRAITS::CountedValueType> ITERABLE_OF_ADDABLE>
65 inline MultiSet<T, TRAITS>::MultiSet (EQUALS_COMPARER&& equalsComparer, ITERABLE_OF_ADDABLE&& src)
66 : MultiSet{forward<EQUALS_COMPARER> (equalsComparer)}
67 {
68 AddAll (forward<ITERABLE_OF_ADDABLE> (src));
69 _AssertRepValidType ();
70 }
71 template <typename T, typename TRAITS>
72 inline MultiSet<T, TRAITS>::MultiSet (const shared_ptr<_IRep>& rep) noexcept
73 : inherited{(RequireExpression (rep != nullptr), rep)}
74 {
75 _AssertRepValidType ();
76 }
77 template <typename T, typename TRAITS>
78 inline MultiSet<T, TRAITS>::MultiSet (shared_ptr<_IRep>&& rep) noexcept
79 : inherited{(RequireExpression (rep != nullptr), move (rep))}
80 {
81 _AssertRepValidType ();
82 }
83 template <typename T, typename TRAITS>
84 MultiSet<T, TRAITS>::MultiSet (const initializer_list<T>& src)
85 requires (IEqualsComparer<equal_to<T>, T>)
86 : MultiSet{}
87 {
88 AddAll (src);
89 _AssertRepValidType ();
90 }
91 template <typename T, typename TRAITS>
92 template <IEqualsComparer<T> EQUALS_COMPARER>
93 MultiSet<T, TRAITS>::MultiSet (EQUALS_COMPARER&& equalsComparer, const initializer_list<T>& src)
94 : MultiSet{forward<EQUALS_COMPARER> (equalsComparer)}
95 {
96 AddAll (src);
97 _AssertRepValidType ();
98 }
99 template <typename T, typename TRAITS>
100 MultiSet<T, TRAITS>::MultiSet (const initializer_list<value_type>& src)
101 : MultiSet{}
102 {
103 AddAll (src);
104 _AssertRepValidType ();
105 }
106 template <typename T, typename TRAITS>
107 template <IEqualsComparer<T> EQUALS_COMPARER>
108 MultiSet<T, TRAITS>::MultiSet (EQUALS_COMPARER&& equalsComparer, const initializer_list<value_type>& src)
109 : MultiSet{forward<EQUALS_COMPARER> (equalsComparer)}
110 {
111 AddAll (src);
112 _AssertRepValidType ();
113 }
114 template <typename T, typename TRAITS>
115 template <IInputIterator<typename TRAITS::CountedValueType> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2>
116 MultiSet<T, TRAITS>::MultiSet (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
117 requires (IEqualsComparer<equal_to<T>, T>)
118 : MultiSet{}
119 {
120 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE2> (end));
121 _AssertRepValidType ();
122 }
123 template <typename T, typename TRAITS>
124 template <IEqualsComparer<T> EQUALS_COMPARER, IInputIterator<typename TRAITS::CountedValueType> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2>
125 MultiSet<T, TRAITS>::MultiSet (EQUALS_COMPARER&& equalsComparer, ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
126 : MultiSet{forward<EQUALS_COMPARER> (equalsComparer)}
127 {
128 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE2> (end));
129 _AssertRepValidType ();
130 }
131 template <typename T, typename TRAITS>
132 auto MultiSet<T, TRAITS>::TotalOccurrences () const -> CounterType
133 {
134 CounterType sum = 0;
135 for (value_type i : *this) {
136 sum += i.fCount;
137 }
138 return sum;
139 }
140 template <typename T, typename TRAITS>
142 {
143 Iterator<value_type> result{nullptr};
144 this->Remove (i, &result);
145 return result;
146 }
147 template <typename T, typename TRAITS>
149 {
150 RemoveAll ();
151 }
152 template <typename T, typename TRAITS>
154 {
155 // Need explicit struct because we need to re-create the iterator on copies
156 // Not just simple map cuz must pause and 'create' new extra elements
157 struct Context_ {
158 MultiSet<T, TRAITS> fOriginalMultiset;
159 Iterator<typename TRAITS::CountedValueType> fCurrentIteratorOverOrig;
160 size_t fIthAdvanceOfIterator{0}; // because not a random-accessor iterator so hard to compute without tracking
161 size_t fIthOfCurrentIterator{0};
162 Context_ (const Context_& rhs)
163 : fOriginalMultiset{rhs.fOriginalMultiset}
164 , fCurrentIteratorOverOrig{fOriginalMultiset.MakeIterator ()}
165 , fIthAdvanceOfIterator{rhs.fIthAdvanceOfIterator}
166 , fIthOfCurrentIterator{rhs.fIthOfCurrentIterator}
167 {
168 std::advance (fCurrentIteratorOverOrig, fIthAdvanceOfIterator);
169 }
170 Context_ (const MultiSet<T, TRAITS>& ms)
171 : fOriginalMultiset{ms}
172 , fCurrentIteratorOverOrig{fOriginalMultiset.MakeIterator ()}
173 {
174 }
175 Context_& operator= (Context_&) = delete; // could implement but I think no need
176 };
177 function<optional<T> ()> getNext = [context = Context_{*this}] () mutable -> optional<T> {
178 again:
179 if (context.fCurrentIteratorOverOrig) {
180 if (context.fIthOfCurrentIterator < context.fCurrentIteratorOverOrig->fCount) {
181 ++context.fIthOfCurrentIterator;
182 return context.fCurrentIteratorOverOrig->fValue;
183 }
184 else {
185 ++context.fCurrentIteratorOverOrig;
186 ++context.fIthAdvanceOfIterator;
187 context.fIthOfCurrentIterator = 0;
188 goto again;
189 }
190 }
191 return nullopt;
192 };
193 return Traversal::CreateGenerator (getNext);
194 }
195 template <typename T, typename TRAITS>
197 {
198 return this->template Map<Iterable<T>> ([] (const typename TRAITS::CountedValueType& cv) { return cv.fValue; });
199 }
200 template <typename T, typename TRAITS>
202 {
203 return this->inherited::Top ([] (const typename TRAITS::CountedValueType& lhs, const typename TRAITS::CountedValueType& rhs) {
204 return lhs.fCount > rhs.fCount;
205 });
206 }
207 template <typename T, typename TRAITS>
209 {
210 return this->inherited::Top (n, [] (const typename TRAITS::CountedValueType& lhs, const typename TRAITS::CountedValueType& rhs) {
211 return lhs.fCount > rhs.fCount;
212 });
213 }
214 template <typename T, typename TRAITS>
216 {
217 return Top ().template Map<Iterable<T>> ([] (const typename TRAITS::CountedValueType& cv) { return cv.fValue; });
218 }
219 template <typename T, typename TRAITS>
221 {
222 return Top (n).template Map<Iterable<T>> ([] (const typename TRAITS::CountedValueType& cv) { return cv.fValue; });
223 }
224 template <typename T, typename TRAITS>
226 {
227 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().GetElementEqualsComparer ();
228 }
229 template <typename T, typename TRAITS>
230 inline bool MultiSet<T, TRAITS>::Contains (ArgByValueType<T> item) const
231 {
232 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Contains (item);
233 }
234 template <typename T, typename TRAITS>
236 {
237 _SafeReadRepAccessor<_IRep> tmp{this}; // important to use READ not WRITE accessor, because write accessor would have already cloned the data
238 if (not tmp._ConstGetRep ().empty ()) {
239 this->_fRep = tmp._ConstGetRep ().CloneEmpty ();
240 }
241 }
242 template <typename T, typename TRAITS>
243 inline size_t MultiSet<T, TRAITS>::RemoveAll (ArgByValueType<T> item)
244 {
245 return RemoveIf (item, OccurrencesOf (item));
246 }
247 template <typename T, typename TRAITS>
248 inline void MultiSet<T, TRAITS>::Add (ArgByValueType<T> item)
249 {
250 _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().Add (item, 1);
251 }
252 template <typename T, typename TRAITS>
253 inline void MultiSet<T, TRAITS>::Add (ArgByValueType<T> item, CounterType count)
254 {
255 _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().Add (item, count);
256 }
257 template <typename T, typename TRAITS>
258 inline void MultiSet<T, TRAITS>::Add (const value_type& item)
259 {
260 _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().Add (item.fValue, item.fCount);
261 }
262 template <typename T, typename TRAITS>
263 template <IInputIterator<typename TRAITS::CountedValueType> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2>
264 void MultiSet<T, TRAITS>::AddAll (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
265 {
266 for (ITERATOR_OF_ADDABLE i = forward<ITERATOR_OF_ADDABLE> (start); i != forward<ITERATOR_OF_ADDABLE2> (end); ++i) {
267 Add (*i);
268 }
269 }
270 template <typename T, typename TRAITS>
271 template <IIterableOfTo<typename TRAITS::CountedValueType> ITERABLE_OF_ADDABLE>
272 void MultiSet<T, TRAITS>::AddAll (ITERABLE_OF_ADDABLE&& items)
273 {
274 // see http://stroika-bugs.sophists.com/browse/STK-645
275 if constexpr (std::is_convertible_v<remove_cvref_t<ITERABLE_OF_ADDABLE>*, const MultiSet<T, TRAITS>*>) {
276 if (static_cast<const Iterable<value_type>*> (this) == static_cast<const Iterable<value_type>*> (&items)) [[unlikely]] {
277 // very rare corner case
278 using VEC_ELT_T = typename remove_cvref_t<ITERABLE_OF_ADDABLE>::value_type;
279 using ELTS_IT_T = decltype (items.begin ());
280 vector<VEC_ELT_T> copy{std::begin (items), ELTS_IT_T{std::end (items)}}; // because you can not iterate over a container while modifying it
281 for (const auto& i : copy) {
282 Add (i);
283 }
284 return;
285 }
286 }
287 for (const auto& i : items) {
288 Add (i);
289 }
291 template <typename T, typename TRAITS>
292 inline void MultiSet<T, TRAITS>::Remove (ArgByValueType<T> item, CounterType count)
293 {
294 Verify (_SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().RemoveIf (item, count) == count);
295 }
296 template <typename T, typename TRAITS>
298 {
299 Require (not i.Done ());
300 auto [writerRep, patchedIterator] = _GetWritableRepAndPatchAssociatedIterator (i);
301 writerRep->Remove (patchedIterator, nextI);
303 template <typename T, typename TRAITS>
304 inline size_t MultiSet<T, TRAITS>::RemoveIf (ArgByValueType<T> item, CounterType count)
305 {
306 return _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().RemoveIf (item, count);
307 }
308 template <typename T, typename TRAITS>
309 inline void MultiSet<T, TRAITS>::UpdateCount (const Iterator<value_type>& i, CounterType newCount, Iterator<value_type>* nextI)
310 {
311 Require (not i.Done ());
312 auto [writerRep, patchedIterator] = _GetWritableRepAndPatchAssociatedIterator (i);
313 writerRep->UpdateCount (patchedIterator, newCount, nextI);
314 }
315 template <typename T, typename TRAITS>
316 inline void MultiSet<T, TRAITS>::SetCount (ArgByValueType<T> i, CounterType newCount)
317 {
318 CounterType cnt = OccurrencesOf (i);
319 if (newCount > cnt) {
320 Add (i, newCount - cnt);
322 else if (newCount < cnt) {
323 Remove (i, cnt - newCount);
324 }
325 }
326 template <typename T, typename TRAITS>
327 inline auto MultiSet<T, TRAITS>::OccurrencesOf (ArgByValueType<T> item) const -> CounterType
328 {
329 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().OccurrencesOf (item);
330 }
331 template <typename T, typename TRAITS>
332 template <typename RESULT_CONTAINER, invocable<T> ELEMENT_MAPPER>
333 inline RESULT_CONTAINER MultiSet<T, TRAITS>::Map (ELEMENT_MAPPER&& elementMapper) const
334 requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, typename TRAITS::CountedValueType>, typename RESULT_CONTAINER::value_type> or
335 convertible_to<invoke_result_t<ELEMENT_MAPPER, typename TRAITS::CountedValueType>, optional<typename RESULT_CONTAINER::value_type>>)
337 if constexpr (same_as<RESULT_CONTAINER, MultiSet>) {
338 // clone the rep so we retain the ordering function
339 return inherited::template Map<RESULT_CONTAINER> (forward<ELEMENT_MAPPER> (elementMapper),
340 RESULT_CONTAINER{_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().CloneEmpty ()});
341 }
342 else {
343 return inherited::template Map<RESULT_CONTAINER> (forward<ELEMENT_MAPPER> (elementMapper)); // default Iterable<> interpretation
344 }
345 }
346 template <typename T, typename TRAITS>
347 template <derived_from<Iterable<typename TRAITS::CountedValueType>> RESULT_CONTAINER, predicate<typename TRAITS::CountedValueType> INCLUDE_PREDICATE>
348 inline RESULT_CONTAINER MultiSet<T, TRAITS>::Where (INCLUDE_PREDICATE&& includeIfTrue) const
349 {
350 if constexpr (same_as<RESULT_CONTAINER, MultiSet>) {
351 // clone the rep so we retain the ordering function
352 return inherited::template Where<RESULT_CONTAINER> (
353 forward<INCLUDE_PREDICATE> (includeIfTrue), RESULT_CONTAINER{_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().CloneEmpty ()});
354 }
355 else {
356 return inherited::template Where<RESULT_CONTAINER> (forward<INCLUDE_PREDICATE> (includeIfTrue)); // default Iterable<> interpretation
357 }
358 }
359 template <typename T, typename TRAITS>
361 {
362 _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().Add (item, 1);
363 return *this;
364 }
365 template <typename T, typename TRAITS>
367 {
368 AddAll (items);
369 return *this;
371 template <typename T, typename TRAITS>
373 {
374 Require (not i.Done ());
375 using element_type = typename inherited::_SharedByValueRepType::element_type;
376 Iterator<value_type> patchedIterator = i;
377 element_type* writableRep = this->_fRep.rwget ([&] (const element_type& prevRepPtr) -> typename inherited::_SharedByValueRepType::shared_ptr_type {
378 return Debug::UncheckedDynamicCast<const _IRep&> (prevRepPtr).CloneAndPatchIterator (&patchedIterator);
379 });
380 AssertNotNull (writableRep);
381 return make_tuple (Debug::UncheckedDynamicCast<_IRep*> (writableRep), move (patchedIterator));
382 }
383 template <typename T, typename TRAITS>
385 {
387 _SafeReadRepAccessor<_IRep>{this};
388 }
389 }
390 template <typename T, typename TRAITS>
391 inline bool MultiSet<T, TRAITS>::operator== (const MultiSet& rhs) const
392 {
393 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Equals (_SafeReadRepAccessor<_IRep>{&rhs}._ConstGetRep ());
394 }
395
396}
#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 RequireExpression(c)
Definition Assertions.h:267
#define Verify(c)
Definition Assertions.h:419
nonvirtual MultiSet & operator+=(ArgByValueType< T > item)
Definition MultiSet.inl:360
nonvirtual void AddAll(ITERATOR_OF_ADDABLE &&start, ITERATOR_OF_ADDABLE2 &&end)
nonvirtual CounterType TotalOccurrences() const
Definition MultiSet.inl:132
nonvirtual Iterator< value_type > erase(const Iterator< value_type > &i)
Definition MultiSet.inl:141
nonvirtual void Remove(ArgByValueType< T > item, CounterType count=1)
remove the argument data from the multiset. The data specified MUST exist (require) - else use Remove...
Definition MultiSet.inl:292
nonvirtual Iterable< T > Elements() const
Definition MultiSet.inl:153
nonvirtual void UpdateCount(const Iterator< value_type > &i, CounterType newCount, Iterator< value_type > *nextI=nullptr)
Definition MultiSet.inl:309
nonvirtual void Add(ArgByValueType< T > item)
Definition MultiSet.inl:248
nonvirtual Iterable< T > TopElements() const
Find the most commonly occurring elements of the multiset (list of elements - without count - ordered...
Definition MultiSet.inl:215
nonvirtual ElementEqualityComparerType GetElementEqualsComparer() const
Definition MultiSet.inl:225
typename inherited::value_type value_type
Definition MultiSet.h:149
nonvirtual bool operator==(const MultiSet &rhs) const
Definition MultiSet.inl:391
nonvirtual RESULT_CONTAINER Map(ELEMENT_MAPPER &&elementMapper) const
'override' Iterable<>::Map () function so RESULT_CONTAINER defaults to MultiSet, and improve that cas...
nonvirtual Iterable< typename TRAITS::CountedValueType > Top() const
Find the most commonly occurring elements of the multiset (list with count ordered most to last)
Definition MultiSet.inl:201
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...
Definition MultiSet.inl:372
nonvirtual RESULT_CONTAINER Where(INCLUDE_PREDICATE &&includeIfTrue) const
nonvirtual bool Contains(ArgByValueType< T > item) const
Definition MultiSet.inl:230
nonvirtual void RemoveAll()
RemoveAll removes all, or all matching (predicate, iterator range, equals comparer or whatever) items...
Definition MultiSet.inl:235
nonvirtual CounterType OccurrencesOf(ArgByValueType< T > item) const
Definition MultiSet.inl:327
nonvirtual size_t RemoveIf(ArgByValueType< T > item, CounterType count=1)
remove the argument data from the multiset (can specify remove of more than are present) - returns nu...
Definition MultiSet.inl:304
nonvirtual void SetCount(ArgByValueType< T > i, CounterType newCount)
Definition MultiSet.inl:316
nonvirtual Iterable< T > UniqueElements() const
Definition MultiSet.inl:196
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.
nonvirtual Iterator< T > MakeIterator() const
Create an iterator object which can be used to traverse the 'Iterable'.
Definition Iterable.inl:294
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