Stroika Library 3.0d24
 
Loading...
Searching...
No Matches
KeyedCollection.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4
5/*
6 ********************************************************************************
7 ***************************** Implementation Details ***************************
8 ********************************************************************************
9 */
13
15
16 /*
17 ********************************************************************************
18 ******************** KeyedCollection<T, KEY_TYPE, TRAITS> **********************
19 ********************************************************************************
20 */
21 template <typename T, typename KEY_TYPE, typename TRAITS>
22 template <IEqualsComparer<KEY_TYPE> KEY_EQUALS_COMPARER>
23 inline KeyedCollection<T, KEY_TYPE, TRAITS>::KeyedCollection (KEY_EQUALS_COMPARER&& keyComparer)
25 : KeyedCollection{KeyExtractorType{}, forward<KEY_EQUALS_COMPARER> (keyComparer)}
26 {
27 _AssertRepValidType ();
28 }
29 template <typename T, typename KEY_TYPE, typename TRAITS>
30 template <IEqualsComparer<KEY_TYPE> KEY_EQUALS_COMPARER>
31 inline KeyedCollection<T, KEY_TYPE, TRAITS>::KeyedCollection (const KeyExtractorType& keyExtractor, KEY_EQUALS_COMPARER&& keyComparer)
32 : inherited{Factory::KeyedCollection_Factory<T, KEY_TYPE, TRAITS, remove_cvref_t<KEY_EQUALS_COMPARER>>::Default () (
33 keyExtractor, forward<KEY_EQUALS_COMPARER> (keyComparer))}
34 {
35 _AssertRepValidType ();
36 }
37 template <typename T, typename KEY_TYPE, typename TRAITS>
38 inline KeyedCollection<T, KEY_TYPE, TRAITS>::KeyedCollection (const initializer_list<value_type>& src)
39 : KeyedCollection{}
40 {
41 AddAll (src);
42 }
43#if !qCompilerAndStdLib_template_Requires_templateDeclarationMatchesOutOfLine2_Buggy
44 template <typename T, typename KEY_TYPE, typename TRAITS>
45 template <IIterableOfTo<T> ITERABLE_OF_ADDABLE, IEqualsComparer<KEY_TYPE> KEY_EQUALS_COMPARER>
46 inline KeyedCollection<T, KEY_TYPE, TRAITS>::KeyedCollection (ITERABLE_OF_ADDABLE&& src)
47 requires (IKeyedCollection_ExtractorCanBeDefaulted<T, KEY_TYPE, TRAITS> and
48 not derived_from<remove_cvref_t<ITERABLE_OF_ADDABLE>, KeyedCollection<T, KEY_TYPE, TRAITS>>)
49 : KeyedCollection{}
50 {
51 AddAll (forward<ITERABLE_OF_ADDABLE> (src));
52 _AssertRepValidType ();
53 }
54#endif
55#if !qCompilerAndStdLib_template_Requires_templateDeclarationMatchesOutOfLine2_Buggy
56 template <typename T, typename KEY_TYPE, typename TRAITS>
57 template <IIterableOfTo<T> ITERABLE_OF_ADDABLE, IEqualsComparer<KEY_TYPE> KEY_EQUALS_COMPARER>
58 inline KeyedCollection<T, KEY_TYPE, TRAITS>::KeyedCollection (KEY_EQUALS_COMPARER&& keyComparer, ITERABLE_OF_ADDABLE&& src)
59 requires (IKeyedCollection_ExtractorCanBeDefaulted<T, KEY_TYPE, TRAITS> and
60 not derived_from<remove_cvref_t<ITERABLE_OF_ADDABLE>, KeyedCollection<T, KEY_TYPE, TRAITS>>)
61 : KeyedCollection{KeyExtractorType{}, forward<KEY_EQUALS_COMPARER> (keyComparer)}
62 {
63 AddAll (src);
64 _AssertRepValidType ();
65 }
66#endif
67 template <typename T, typename KEY_TYPE, typename TRAITS>
68 template <IEqualsComparer<KEY_TYPE> KEY_EQUALS_COMPARER, IIterableOfTo<T> ITERABLE_OF_ADDABLE>
69 inline KeyedCollection<T, KEY_TYPE, TRAITS>::KeyedCollection (const KeyExtractorType& keyExtractor, KEY_EQUALS_COMPARER&& keyComparer,
70 ITERABLE_OF_ADDABLE&& src)
71 : KeyedCollection{keyExtractor, forward<KEY_EQUALS_COMPARER> (keyComparer)}
72 {
73 AddAll (src);
74 _AssertRepValidType ();
75 }
76 template <typename T, typename KEY_TYPE, typename TRAITS>
77 template <IIterableOfTo<T> ITERABLE_OF_ADDABLE>
78 inline KeyedCollection<T, KEY_TYPE, TRAITS>::KeyedCollection (const KeyExtractorType& keyExtractor, ITERABLE_OF_ADDABLE&& src)
79 requires (IEqualsComparer<KEY_TYPE, equal_to<KEY_TYPE>>)
80 : KeyedCollection{keyExtractor, equal_to<KEY_TYPE>{}}
81 {
82 AddAll (src);
83 _AssertRepValidType ();
84 }
85 template <typename T, typename KEY_TYPE, typename TRAITS>
86 template <IInputIterator<T> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2, IEqualsComparer<KEY_TYPE> KEY_EQUALS_COMPARER>
87 KeyedCollection<T, KEY_TYPE, TRAITS>::KeyedCollection (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
88 requires (IKeyedCollection_ExtractorCanBeDefaulted<T, KEY_TYPE, TRAITS>)
89 : KeyedCollection{KeyExtractorType{}, KEY_EQUALS_COMPARER{}}
90 {
91 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE2> (end));
92 _AssertRepValidType ();
93 }
94 template <typename T, typename KEY_TYPE, typename TRAITS>
95 template <IInputIterator<T> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2, IEqualsComparer<KEY_TYPE> KEY_EQUALS_COMPARER>
96 KeyedCollection<T, KEY_TYPE, TRAITS>::KeyedCollection (KEY_EQUALS_COMPARER&& keyComparer, ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
97 requires (IKeyedCollection_ExtractorCanBeDefaulted<T, KEY_TYPE, TRAITS>)
98 : KeyedCollection{KeyExtractorType{}, forward<KEY_EQUALS_COMPARER> (keyComparer)}
99 {
100 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE2> (end));
101 _AssertRepValidType ();
102 }
103 template <typename T, typename KEY_TYPE, typename TRAITS>
104 template <IEqualsComparer<KEY_TYPE> KEY_EQUALS_COMPARER, IInputIterator<T> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2>
105 KeyedCollection<T, KEY_TYPE, TRAITS>::KeyedCollection (const KeyExtractorType& keyExtractor, KEY_EQUALS_COMPARER&& keyComparer,
106 ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
107 : KeyedCollection{keyExtractor, forward<KEY_EQUALS_COMPARER> (keyComparer)}
108 {
110 _AssertRepValidType ();
111 }
112 template <typename T, typename KEY_TYPE, typename TRAITS>
113 inline KeyedCollection<T, KEY_TYPE, TRAITS>::KeyedCollection (const shared_ptr<_IRep>& rep) noexcept
114 : inherited{(RequireExpression (rep != nullptr), rep)}
115 {
116 _AssertRepValidType ();
117 }
118 template <typename T, typename KEY_TYPE, typename TRAITS>
119 inline KeyedCollection<T, KEY_TYPE, TRAITS>::KeyedCollection (shared_ptr<_IRep>&& rep) noexcept
120 : inherited{(RequireExpression (rep != nullptr), move (rep))}
121 {
122 _AssertRepValidType ();
123 }
124 template <typename T, typename KEY_TYPE, typename TRAITS>
126 {
127 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().GetKeyExtractor ();
128 }
129 template <typename T, typename KEY_TYPE, typename TRAITS>
131 {
132 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().GetKeyEqualityComparer ();
133 }
134 template <typename T, typename KEY_TYPE, typename TRAITS>
136 {
137 return this->template Map<Iterable<KEY_TYPE>> ([keyExtractor = this->GetKeyExtractor ()] (const T& t) { return keyExtractor (t); });
138 }
139 template <typename T, typename KEY_TYPE, typename TRAITS>
140 inline bool KeyedCollection<T, KEY_TYPE, TRAITS>::Contains (ArgByValueType<KEY_TYPE> key) const
141 {
142 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, nullptr);
143 }
144 template <typename T, typename KEY_TYPE, typename TRAITS>
145 inline bool KeyedCollection<T, KEY_TYPE, TRAITS>::Contains (ArgByValueType<value_type> elt) const
146 {
147 _SafeReadRepAccessor<_IRep> r{this};
148 return r._ConstGetRep ().Lookup (r._ConstGetRep ().GetKeyExtractor () (elt), nullptr);
149 }
150 template <typename T, typename KEY_TYPE, typename TRAITS>
151 inline auto KeyedCollection<T, KEY_TYPE, TRAITS>::Lookup (ArgByValueType<KeyType> key) const -> optional<value_type>
152 {
153 optional<T> r;
154 [[maybe_unused]] bool result = _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, &r);
155 Ensure (result == r.has_value ());
156 return r;
157 }
158 template <typename T, typename KEY_TYPE, typename TRAITS>
159 inline bool KeyedCollection<T, KEY_TYPE, TRAITS>::Lookup (ArgByValueType<KeyType> key, optional<value_type>* item) const
160 {
161 if (item == nullptr) {
162 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, nullptr);
163 }
164 else {
165 optional<value_type> tmp;
166 if (_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, &tmp)) {
167 *item = *tmp;
168 return true;
169 }
170 return false;
171 }
172 }
173 template <typename T, typename KEY_TYPE, typename TRAITS>
174 inline bool KeyedCollection<T, KEY_TYPE, TRAITS>::Lookup (ArgByValueType<KeyType> key, value_type* item) const
175 {
176 if (item == nullptr) {
177 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, nullptr);
178 }
179 else {
180 optional<value_type> tmp;
181 if (_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, &tmp)) {
182 *item = *tmp;
183 return true;
184 }
185 return false;
186 }
187 }
188 template <typename T, typename KEY_TYPE, typename TRAITS>
189 inline bool KeyedCollection<T, KEY_TYPE, TRAITS>::Lookup (ArgByValueType<KeyType> key, nullptr_t) const
190 {
191 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, nullptr);
192 }
193 template <typename T, typename KEY_TYPE, typename TRAITS>
194 template <typename THROW_IF_MISSING>
195 inline auto KeyedCollection<T, KEY_TYPE, TRAITS>::LookupChecked (ArgByValueType<KeyType> key, THROW_IF_MISSING&& throwIfMissing) const -> value_type
196 {
197 if (optional<value_type> r{Lookup (key)}) [[likely]] {
198 return *r;
199 }
200 Execution::Throw (forward<THROW_IF_MISSING> (throwIfMissing));
201 }
202 template <typename T, typename KEY_TYPE, typename TRAITS>
203 inline auto KeyedCollection<T, KEY_TYPE, TRAITS>::LookupValue (ArgByValueType<KeyType> key, ArgByValueType<value_type> defaultValue) const -> value_type
204 {
205 optional<value_type> r{Lookup (key)};
206 return r.has_value () ? *r : defaultValue;
207 }
208 template <typename T, typename KEY_TYPE, typename TRAITS>
209 inline bool KeyedCollection<T, KEY_TYPE, TRAITS>::Add (ArgByValueType<value_type> t)
210 {
211 return _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().Add (t);
212 }
213 template <typename T, typename KEY_TYPE, typename TRAITS>
214 template <IInputIterator<T> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2>
215 unsigned int KeyedCollection<T, KEY_TYPE, TRAITS>::AddAll (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
216 {
217 unsigned int cntAdded{};
218 _SafeReadWriteRepAccessor<_IRep> r{this};
219 for (auto i = forward<ITERATOR_OF_ADDABLE> (start); i != forward<ITERATOR_OF_ADDABLE2> (end); ++i) {
220 if (r._GetWriteableRep ().Add (*i)) {
221 ++cntAdded;
222 }
223 }
224 return cntAdded;
225 }
226 template <typename T, typename KEY_TYPE, typename TRAITS>
227 template <IIterableOfTo<T> ITERABLE_OF_ADDABLE>
228 inline unsigned int KeyedCollection<T, KEY_TYPE, TRAITS>::AddAll (ITERABLE_OF_ADDABLE&& items)
229 {
230 /*
231 * SOURCE-SIDE fast path - see Set<T>::AddAll (ITERABLE_OF_ADDABLE) for the mechanism and why
232 * borrowing the source's buffer is safe. _IRep::Add () takes one item and returns whether it
233 * actually added, so this cannot batch the destination and the span walk has to accumulate the
234 * count this method returns. Measured ~1.11x penalty for a Stroika source (Tests/52
235 * "KeyedCollection<int,int>::AddAll ()"), which is what this recovers - modest next to Set's
236 * 1.42x, because a key extraction (often through a std::function) per element makes the
237 * destination work a bigger share of the total.
238 */
239 if constexpr (derived_from<remove_cvref_t<ITERABLE_OF_ADDABLE>, Iterable<T>>) {
240 if (static_cast<const Iterable<T>*> (this) != static_cast<const Iterable<T>*> (&items)) [[likely]] {
241 optional<unsigned int> cntAdded;
242 {
243 _SafeReadWriteRepAccessor<_IRep> destAccessor{this};
244 _IRep& destRep = destAccessor._GetWriteableRep ();
245 _SafeReadRepAccessor<typename Iterable<T>::_IRep> srcAccessor{&items};
246 if (auto srcSpan = srcAccessor._ConstGetRep ().PeekContiguousStorage ()) {
247 unsigned int n{};
248 for (const T& v : *srcSpan) {
249 if (destRep.Add (v)) {
250 ++n;
251 }
252 }
253 cntAdded = n;
254 }
255 }
256 if (cntAdded) {
257 return *cntAdded;
258 }
259 }
260 }
261 if constexpr (same_as<remove_cvref_t<ITERABLE_OF_ADDABLE>, KeyedCollection>) {
262 // avoid trouble with a.AddAll(a);
263 if (this != &items) {
264 return AddAll (std::begin (items), std::end (items));
265 }
266 return 0;
267 }
268 else {
269 return AddAll (std::begin (items), std::end (items));
270 }
271 }
272 template <typename T, typename KEY_TYPE, typename TRAITS>
273 inline void KeyedCollection<T, KEY_TYPE, TRAITS>::Remove (ArgByValueType<KeyType> key)
274 {
275 Verify (_SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().RemoveIf (key));
276 }
277 template <typename T, typename KEY_TYPE, typename TRAITS>
278 inline void KeyedCollection<T, KEY_TYPE, TRAITS>::Remove (ArgByValueType<value_type> elt)
279 {
280 _SafeReadWriteRepAccessor<_IRep> writeAccessor{this};
281 Verify (writeAccessor._GetWriteableRep ().RemoveIf (writeAccessor._ConstGetRep ().GetKeyExtractor () (elt)));
282 }
283 template <typename T, typename KEY_TYPE, typename TRAITS>
285 {
286 Require (not i.AtEnd ());
287 auto [writerRep, patchedIterator] = _GetWritableRepAndPatchAssociatedIterator (i);
288 writerRep->Remove (patchedIterator, nextI);
289 }
290 template <typename T, typename KEY_TYPE, typename TRAITS>
291 inline bool KeyedCollection<T, KEY_TYPE, TRAITS>::RemoveIf (ArgByValueType<KeyType> key)
292 {
293 return _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().RemoveIf (key);
294 }
295 template <typename T, typename KEY_TYPE, typename TRAITS>
296 inline bool KeyedCollection<T, KEY_TYPE, TRAITS>::RemoveIf (ArgByValueType<value_type> elt)
297 {
298 _SafeReadWriteRepAccessor<_IRep> r{this};
299 return r._GetWriteableRep ().Remove (r._ConstGetRep ().GetKeyExtractor () (elt));
300 }
301 template <typename T, typename KEY_TYPE, typename TRAITS>
302 inline void KeyedCollection<T, KEY_TYPE, TRAITS>::RemoveAll ()
304 _SafeReadRepAccessor<_IRep> tmp{this}; // important to use READ not WRITE accessor, because write accessor would have already cloned the data
305 if (not tmp._ConstGetRep ().empty ()) {
306 this->_fRep = tmp._ConstGetRep ().CloneEmpty ();
307 }
308 }
309 template <typename T, typename KEY_TYPE, typename TRAITS>
310 template <predicate<T> PREDICATE>
312 {
313 size_t nRemoved{};
314 for (Iterator<T> i = this->begin (); i != this->end ();) {
315 if (p (*i)) {
316 Remove (i, &i);
317 ++nRemoved;
318 }
319 else {
320 ++i;
321 }
322 }
323 return nRemoved;
324 }
325 template <typename T, typename KEY_TYPE, typename TRAITS>
326 template <IIterableOfTo<T> ITERABLE_OF_ADDABLE>
327 inline size_t KeyedCollection<T, KEY_TYPE, TRAITS>::RemoveAll (const ITERABLE_OF_ADDABLE& items)
328 {
329 size_t cnt{};
330 for (const auto& i : items) {
331 Remove (i.first);
332 ++cnt;
333 }
334 return cnt;
335 }
336 template <typename T, typename KEY_TYPE, typename TRAITS>
337 template <IInputIterator<T> ITERATOR_OF_ADDABLE>
338 inline size_t KeyedCollection<T, KEY_TYPE, TRAITS>::RemoveAll (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE&& end)
339 {
340 size_t cnt{};
341 for (auto i = forward<ITERATOR_OF_ADDABLE> (start); i != end; ++i) {
342 Remove (i->first);
343 ++cnt;
344 }
345 return cnt;
346 }
347 template <typename T, typename KEY_TYPE, typename TRAITS>
348 template <typename RESULT_CONTAINER, invocable<T> ELEMENT_MAPPER>
349 inline RESULT_CONTAINER KeyedCollection<T, KEY_TYPE, TRAITS>::Map (ELEMENT_MAPPER&& elementMapper) const
350 requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, typename RESULT_CONTAINER::value_type> or
351 convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, optional<typename RESULT_CONTAINER::value_type>>)
352 {
353 if constexpr (same_as<RESULT_CONTAINER, KeyedCollection>) {
354 // clone the rep so we retain the this' intrinsic properties (besides data, eg extractor, ordering, reptype)
355 return inherited::template Map<RESULT_CONTAINER> (forward<ELEMENT_MAPPER> (elementMapper),
356 RESULT_CONTAINER{_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().CloneEmpty ()});
357 }
358 else {
359 return inherited::template Map<RESULT_CONTAINER> (forward<ELEMENT_MAPPER> (elementMapper)); // default Iterable<> interpretation
360 }
361 }
362 template <typename T, typename KEY_TYPE, typename TRAITS>
363 template <derived_from<Iterable<T>> RESULT_CONTAINER, predicate<T> INCLUDE_PREDICATE>
364 inline auto KeyedCollection<T, KEY_TYPE, TRAITS>::Where (INCLUDE_PREDICATE&& includeIfTrue) const -> RESULT_CONTAINER
365 {
366 if constexpr (same_as<RESULT_CONTAINER, KeyedCollection>) {
367 // clone the rep so we retain the this' intrindic properties (besides data, eg extractor, ordering, reptype)
368 return inherited::template Where<RESULT_CONTAINER> (
369 forward<INCLUDE_PREDICATE> (includeIfTrue), RESULT_CONTAINER{_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().CloneEmpty ()});
370 }
371 else {
372 return inherited::template Where<RESULT_CONTAINER> (forward<INCLUDE_PREDICATE> (includeIfTrue)); // default Iterable<> interpretation
373 }
374 }
375 template <typename T, typename KEY_TYPE, typename TRAITS>
377 {
378 return EqualsComparer{}(*this, rhs);
379 }
380 template <typename T, typename KEY_TYPE, typename TRAITS>
382 {
383 return EqualsComparer{}(*this, rhs);
384 }
385 template <typename T, typename KEY_TYPE, typename TRAITS>
387 {
388 Add (item);
389 return *this;
390 }
391 template <typename T, typename KEY_TYPE, typename TRAITS>
393 {
394 AddAll (items);
395 return *this;
396 }
397 template <typename T, typename KEY_TYPE, typename TRAITS>
399 {
400 Remove (item);
401 return *this;
402 }
403 template <typename T, typename KEY_TYPE, typename TRAITS>
405 {
406 RemoveAll (items);
407 return *this;
408 }
409 template <typename T, typename KEY_TYPE, typename TRAITS>
412 RemoveAll ();
413 }
414 template <typename T, typename KEY_TYPE, typename TRAITS>
415 inline void KeyedCollection<T, KEY_TYPE, TRAITS>::erase (ArgByValueType<value_type> item)
416 {
417 this->Remove (item);
418 }
419 template <typename T, typename KEY_TYPE, typename TRAITS>
421 {
422 Iterator<T> nextI{nullptr};
423 this->Remove (i, &nextI);
424 return nextI;
425 }
426 template <typename T, typename KEY_TYPE, typename TRAITS>
428 -> tuple<_IRep*, Iterator<value_type>>
429 {
430 Require (not i.AtEnd ());
431 using element_type = typename inherited::_SharedByValueRepType::element_type;
432 Iterator<value_type> patchedIterator = i;
433 element_type* writableRep = this->_fRep.rwget ([&] (const element_type& prevRepPtr) -> typename inherited::_SharedByValueRepType::shared_ptr_type {
434 return Debug::UncheckedDynamicCast<const _IRep&> (prevRepPtr).CloneAndPatchIterator (&patchedIterator);
435 });
436 AssertNotNull (writableRep);
437 return make_tuple (Debug::UncheckedDynamicCast<_IRep*> (writableRep), move (patchedIterator));
438 }
439 template <typename T, typename KEY_TYPE, typename TRAITS>
440 inline void KeyedCollection<T, KEY_TYPE, TRAITS>::_AssertRepValidType () const
441 {
443 [[maybe_unused]] _SafeReadRepAccessor<_IRep> ignored{this};
444 }
445 }
446
447 /*
448 ********************************************************************************
449 ********** KeyedCollection<T, KEY_TYPE, TRAITS>::EqualsComparer ****************
450 ********************************************************************************
451 */
452 template <typename T, typename KEY_TYPE, typename TRAITS>
453 inline bool KeyedCollection<T, KEY_TYPE, TRAITS>::EqualsComparer::operator() (const KeyedCollection& lhs, const KeyedCollection& rhs) const
454 {
455 return operator() (lhs, static_cast<const Iterable<T>&> (rhs)); // use common-code
456 }
457 template <typename T, typename KEY_TYPE, typename TRAITS>
458 bool KeyedCollection<T, KEY_TYPE, TRAITS>::EqualsComparer::operator() (const KeyedCollection& lhs, const Iterable<value_type>& rhs) const
459 {
462 if (&lhsR._ConstGetRep () == &rhsR._ConstGetRep ()) {
463 // not such an unlikely test result since we use lazy copy, but this test is only an optimization and not logically required
464 return true;
465 }
466 // Check length, so we don't need to check both iterators for end/done
467 if (lhsR._ConstGetRep ().size () != rhsR._ConstGetRep ().size ()) {
468 return false;
469 }
470
471 /*
472 * Order is meaningless for KeyedCollection<>, so treat like set. Iterate over Iterable<T> on rhs, and check for contains
473 * on LHS (known to have relatively fast lookup).
474 *
475 * Leverage fact we know by this point the two iterables have the same length.
476 */
477 for (const auto& ri : rhs) {
478 if (not lhs.Contains (ri)) {
479 return false;
480 }
481 }
482 return true;
484 template <typename T, typename KEY_TYPE, typename TRAITS>
486 {
487 return operator() (rhs, lhs); // use commutativity of ==
488 }
489
490}
#define AssertNotNull(p)
Definition Assertions.h:334
#define qStroika_Foundation_Debug_AssertionsChecked
The qStroika_Foundation_Debug_AssertionsChecked flag determines if assertions are checked and validat...
Definition Assertions.h:49
#define RequireExpression(c)
Definition Assertions.h:268
#define Verify(c)
Definition Assertions.h:420
a cross between Mapping<KEY, T> and Collection<T> and Set<T>
nonvirtual KeyedCollection & operator+=(ArgByValueType< value_type > item)
nonvirtual bool operator==(const KeyedCollection &rhs) const
nonvirtual value_type LookupValue(ArgByValueType< KeyType > key, ArgByValueType< value_type > defaultValue=value_type{}) const
nonvirtual void erase(ArgByValueType< value_type > item)
nonvirtual bool Add(ArgByValueType< value_type > item)
nonvirtual KeyedCollection & operator-=(ArgByValueType< value_type > item)
nonvirtual bool Contains(ArgByValueType< KeyType > item) const
nonvirtual KeyExtractorType GetKeyExtractor() const
nonvirtual bool RemoveIf(ArgByValueType< KeyType > item)
nonvirtual RESULT_CONTAINER Where(INCLUDE_PREDICATE &&includeIfTrue) const
KeyedCollection(KEY_EQUALS_COMPARER &&keyComparer=KEY_EQUALS_COMPARER{})
nonvirtual KeyEqualityComparerType GetKeyEqualityComparer() const
typename TRAITS::KeyExtractorType KeyExtractorType
nonvirtual void Remove(const Iterator< value_type > &i, const Iterator< value_type > *nextI=nullptr)
Remove the argument value (which must exist) from the KeyedCollection.
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 unsigned int AddAll(ITERATOR_OF_ADDABLE &&start, ITERATOR_OF_ADDABLE2 &&end)
nonvirtual optional< value_type > Lookup(ArgByValueType< KeyType > key) const
nonvirtual RESULT_CONTAINER Map(ELEMENT_MAPPER &&elementMapper) const
'override' Iterable<>::Map () function so RESULT_CONTAINER defaults to KeyedCollection,...
nonvirtual value_type LookupChecked(ArgByValueType< KeyType > key, THROW_IF_MISSING &&throwIfMissing) const
nonvirtual Iterable< KeyType > Keys() const
Implementation detail for iterator implementors.
Definition Iterable.h:1743
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:238
nonvirtual CONTAINER_OF_T As(CONTAINER_OF_T_CONSTRUCTOR_ARGS... args) const
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:253
nonvirtual bool AtEnd() const
AtEnd () means there is nothing left in this iterator (a synonym for (it == container....
Definition Iterator.inl:143
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
Definition Throw.inl:43