Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Set.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4
6#include "Stroika/Foundation/Common/Concepts.h"
9
11
12 /*
13 ********************************************************************************
14 ************************************* Set<T> ***********************************
15 ********************************************************************************
16 */
17 template <typename T>
18 inline Set<T>::Set ()
19 requires (IEqualsComparer<equal_to<T>, T>)
20 : Set{equal_to<value_type>{}}
21 {
22 _AssertRepValidType ();
23 }
24 template <typename T>
25 template <IEqualsComparer<T> EQUALS_COMPARER>
26 inline Set<T>::Set (EQUALS_COMPARER&& equalsComparer)
27 : inherited{Factory::Set_Factory<T, remove_cvref_t<EQUALS_COMPARER>>::Default () (forward<EQUALS_COMPARER> (equalsComparer))}
28 {
29 _AssertRepValidType ();
30 }
31 template <typename T>
32 inline Set<T>::Set (const initializer_list<value_type>& src)
33 requires (IEqualsComparer<equal_to<T>, T>)
34 : Set{}
35 {
36 AddAll (src);
37 _AssertRepValidType ();
38 }
39 template <typename T>
40 template <IEqualsComparer<T> EQUALS_COMPARER>
41 inline Set<T>::Set (EQUALS_COMPARER&& equalsComparer, const initializer_list<value_type>& src)
42 : Set{forward<EQUALS_COMPARER> (equalsComparer)}
43 {
44 AddAll (src);
45 _AssertRepValidType ();
46 }
47#if !qCompilerAndStdLib_RequiresNotMatchInlineOutOfLineForTemplateClassBeingDefined_Buggy
48 template <typename T>
49 template <IIterableOfTo<T> ITERABLE_OF_ADDABLE>
50 requires (not derived_from<remove_cvref_t<ITERABLE_OF_ADDABLE>, Set<T>>)
51 inline Set<T>::Set (ITERABLE_OF_ADDABLE&& src)
52 : Set{}
53 {
54 AddAll (forward<ITERABLE_OF_ADDABLE> (src));
55 _AssertRepValidType ();
56 }
57#endif
58 template <typename T>
59 template <IEqualsComparer<T> EQUALS_COMPARER, IIterableOfTo<T> ITERABLE_OF_ADDABLE>
60 inline Set<T>::Set (EQUALS_COMPARER&& equalsComparer, ITERABLE_OF_ADDABLE&& src)
61 : Set{forward<EQUALS_COMPARER> (equalsComparer)}
62 {
63 AddAll (forward<ITERABLE_OF_ADDABLE> (src));
64 _AssertRepValidType ();
65 }
66 template <typename T>
67 inline Set<T>::Set (const shared_ptr<_IRep>& src) noexcept
68 : inherited{src}
69 {
70 _AssertRepValidType ();
71 }
72 template <typename T>
73 inline Set<T>::Set (shared_ptr<_IRep>&& src) noexcept
74 : inherited{(RequireExpression (src != nullptr), move (src))}
75 {
76 _AssertRepValidType ();
77 }
78 template <typename T>
79 template <IInputIterator<T> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2>
80 inline Set<T>::Set (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
81 requires (IEqualsComparer<equal_to<T>, T>)
82 : Set{}
83 {
84 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE2> (end));
85 _AssertRepValidType ();
86 }
87 template <typename T>
88 template <IEqualsComparer<T> EQUALS_COMPARER, IInputIterator<T> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2>
89 inline Set<T>::Set (EQUALS_COMPARER&& equalsComparer, ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
90 : Set{forward<EQUALS_COMPARER> (equalsComparer)}
91 {
92 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE2> (end));
93 _AssertRepValidType ();
94 }
95 template <typename T>
97 {
98 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().GetElementEqualsComparer ();
99 }
100 template <typename T>
101 inline bool Set<T>::Contains (ArgByValueType<value_type> item) const
102 {
103 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (item, nullptr, nullptr);
104 }
105 template <typename T>
106 inline bool Set<T>::contains (ArgByValueType<value_type> item) const
107 {
108 return Contains (item);
109 }
110 template <typename T>
112 {
113 return items.All ([&] (ArgByValueType<T> i) { return this->Contains (i); });
114 }
115 template <typename T>
117 {
118 return items.Any ([&] (ArgByValueType<T> i) { return this->Contains (i); });
119 }
120 template <typename T>
121 bool Set<T>::IsSubsetOf (const Set& superset) const
122 {
123 for (const auto& i : *this) {
124 if (not superset.Contains (i)) {
125 return false;
126 }
127 }
128 return true;
129 }
130 template <typename T>
131 inline auto Set<T>::Lookup (ArgByValueType<value_type> item) const -> optional<value_type>
132 {
133 optional<value_type> r;
134 _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (item, &r, nullptr);
135 return r; // don't move due to return value optimization
136 }
137 template <typename T>
138 inline void Set<T>::Add (ArgByValueType<value_type> item)
139 {
140 _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().Add (item);
141 }
142 template <typename T>
143 inline bool Set<T>::AddIf (ArgByValueType<value_type> item)
144 {
145 /*
146 * Note, this is an non-performance optimal implementation, but is not a race, because from the outside
147 * if someone calls AddIf() - they don't know/care if this call or another at the same time is doing the
148 * addition. Any 'race' would be in the logical of the calling code.
149 */
150 if (Contains (item)) {
151 return false;
152 }
153 else {
154 Add (item);
155 return true;
156 }
157 }
158 template <typename T>
159 template <IInputIterator<T> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2>
160 void Set<T>::AddAll (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
161 {
162 _SafeReadWriteRepAccessor<_IRep> tmp{this};
163 for (auto i = forward<ITERATOR_OF_ADDABLE> (start); i != forward<ITERATOR_OF_ADDABLE2> (end); ++i) {
164 tmp._GetWriteableRep ().Add (*i);
165 }
166 }
167 template <typename T>
168 template <IIterableOfTo<T> ITERABLE_OF_ADDABLE>
169 inline void Set<T>::AddAll (ITERABLE_OF_ADDABLE&& items)
170 {
171 if constexpr (std::is_convertible_v<remove_cvref_t<ITERABLE_OF_ADDABLE>*, const Iterable<value_type>*>) {
172 // very rare corner case
173 if (static_cast<const Iterable<value_type>*> (this) == static_cast<const Iterable<value_type>*> (&items)) [[unlikely]] {
174 vector<value_type> copy{std::begin (items), Iterator<value_type>{std::end (items)}}; // because you can not iterate over a container while modifying it
175 AddAll (std::begin (copy), std::end (copy));
176 return;
177 }
178 }
179 AddAll (std::begin (items), std::end (items));
180 }
181 template <typename T>
182 inline void Set<T>::Remove (ArgByValueType<value_type> item)
183 {
184 Verify (_SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().RemoveIf (item));
185 }
186 template <typename T>
187 inline void Set<T>::Remove (const Iterator<value_type>& i, Iterator<value_type>* nextI)
188 {
189 Require (not i.Done ());
190 auto [writerRep, patchedIterator] = _GetWritableRepAndPatchAssociatedIterator (i);
191 writerRep->Remove (patchedIterator, nextI);
192 }
193 template <typename T>
194 inline bool Set<T>::RemoveIf (ArgByValueType<value_type> item)
195 {
196 return _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().RemoveIf (item);
197 }
198 template <typename T>
199 template <IInputIterator<T> ITERATOR_OF_ADDABLE>
200 inline size_t Set<T>::RemoveAll (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE&& end)
201 {
202 size_t cnt{};
203 for (auto i = forward<ITERATOR_OF_ADDABLE> (start); i != end; ++i) {
204 ++cnt;
205 Remove (*i);
206 }
207 return cnt;
208 }
209 template <typename T>
210 template <IIterableOfTo<T> ITERABLE_OF_ADDABLE>
211 inline size_t Set<T>::RemoveAll (const ITERABLE_OF_ADDABLE& s)
212 {
213 return RemoveAll (std::begin (s), std::end (s));
214 }
215 template <typename T>
216 inline void Set<T>::RemoveAll ()
217 {
218 _SafeReadRepAccessor<_IRep> tmp{this}; // important to use READ not WRITE accessor, because write accessor would have already cloned the data
219 if (not tmp._ConstGetRep ().empty ()) {
220 this->_fRep = tmp._ConstGetRep ().CloneEmpty ();
221 }
222 }
223 template <typename T>
224 template <predicate<T> PREDICATE>
225 size_t Set<T>::RemoveAll (PREDICATE&& p)
226 {
227 size_t nRemoved{};
228 for (Iterator<T> i = this->begin (); i != this->end ();) {
229 if (p (*i)) {
230 Remove (i, &i);
231 ++nRemoved;
232 }
233 else {
234 ++i;
235 }
236 }
237 return nRemoved;
238 }
239 template <typename T>
240 template <typename RESULT_CONTAINER, invocable<T> ELEMENT_MAPPER>
241 inline RESULT_CONTAINER Set<T>::Map (ELEMENT_MAPPER&& elementMapper) const
242 requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, typename RESULT_CONTAINER::value_type> or
243 convertible_to<invoke_result_t<ELEMENT_MAPPER, T>, optional<typename RESULT_CONTAINER::value_type>>)
244 {
245 if constexpr (same_as<RESULT_CONTAINER, Set>) {
246 // clone the rep so we retain the ordering function, etc
247 return inherited::template Map<RESULT_CONTAINER> (forward<ELEMENT_MAPPER> (elementMapper),
248 RESULT_CONTAINER{_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().CloneEmpty ()});
249 }
250 else {
251 return inherited::template Map<RESULT_CONTAINER> (forward<ELEMENT_MAPPER> (elementMapper)); // inherited impl fine for this case
252 }
254 template <typename T>
255 template <derived_from<Iterable<T>> RESULT_CONTAINER, predicate<T> INCLUDE_PREDICATE>
256 inline RESULT_CONTAINER Set<T>::Where (INCLUDE_PREDICATE&& includeIfTrue) const
257 {
258 if constexpr (same_as<RESULT_CONTAINER, Set>) {
259 // clone the rep so we retain the ordering function
260 return inherited::template Where<RESULT_CONTAINER> (
261 forward<INCLUDE_PREDICATE> (includeIfTrue), RESULT_CONTAINER{_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().CloneEmpty ()});
262 }
263 else {
264 return inherited::template Where<RESULT_CONTAINER> (forward<INCLUDE_PREDICATE> (includeIfTrue)); // default Iterable<> interpretation
265 }
266 }
267 template <typename T>
269 {
270 for (const auto& i : rhs) {
271 if (Contains (i)) {
272 return true;
273 }
274 }
275 return false;
276 }
277 template <typename T>
278 inline bool Set<T>::Intersects (const Set& lhs, const Iterable<value_type>& rhs)
279 {
280 return lhs.Intersects (rhs);
281 }
282 template <typename T>
283 inline bool Set<T>::Intersects (const Iterable<value_type>& lhs, const Set& rhs)
284 {
285 return rhs.Intersects (lhs);
286 }
287 template <typename T>
288 inline bool Set<T>::Intersects (const Set& lhs, const Set& rhs)
289 {
290 // intersection operation is commutative; and O(N) in side we iterate over, and < O(N) in side we do lookups
291 // on, so do iteration on shorter side
292 if (lhs.size () < rhs.size ()) {
293 return rhs.Intersects (static_cast<const Iterable<T>&> (lhs));
294 }
295 else {
296 return lhs.Intersects (static_cast<const Iterable<T>&> (rhs));
297 }
298 }
299 template <typename T>
301 {
302 using namespace Stroika::Foundation::Common;
303 Set result{this->CloneEmpty ()};
304 /*
305 * note: TRIED using Apply() - and didn't seem to help performance --LGP 2021-11-08
306 */
307 for (const auto& i : rhs) {
308 if (Contains (i)) {
309 result.Add (i);
310 }
311 }
312 return result;
314 template <typename T>
315 inline Set<T> Set<T>::Intersection (const Set& lhs, const Iterable<value_type>& rhs)
316 {
317 return lhs.Intersection (rhs);
318 }
319 template <typename T>
320 inline Set<T> Set<T>::Intersection (const Iterable<T>& lhs, const Set& rhs)
321 {
322 return rhs.Intersection (lhs);
323 }
324 template <typename T>
325 inline Set<T> Set<T>::Intersection (const Set& lhs, const Set& rhs)
326 {
327 // Require (lhs.GetElementEqualsComparer () == rhs.GetElementEqualsComparer ()); Not LITERALLY required, but results undefined if these comparers produce different answers
328 // union operation is commutative; and O(N) in side we iterate over, and < O(N) in side we do lookups
329 // on, so do iteration on shorter side
330 if (lhs.size () < rhs.size ()) {
331 return rhs.Intersection (static_cast<const Iterable<T>&> (lhs));
332 }
333 else {
334 return lhs.Intersection (static_cast<const Iterable<T>&> (rhs));
335 }
337 template <typename T>
338 inline Set<T> Set<T>::Union (const Iterable<value_type>& rhs) const
339 {
340 Set r = *this;
341 r.AddAll (rhs);
342 return r;
343 }
344 template <typename T>
345 inline Set<T> Set<T>::Union (ArgByValueType<value_type> rhs) const
346 {
347 Set r = *this;
348 r.Add (rhs);
349 return r;
350 }
351 template <typename T>
352 inline Set<T> Set<T>::Union (const Set& lhs, const Iterable<value_type>& rhs)
353 {
354 return lhs.Union (rhs);
355 }
356 template <typename T>
357 inline Set<T> Set<T>::Union (const Iterable<value_type>& lhs, const Set& rhs)
358 {
359 // union operation is commutative
360 return rhs.Union (lhs);
361 }
362 template <typename T>
363 inline Set<T> Set<T>::Union (const Set& lhs, const Set& rhs)
364 {
365 // Require (lhs.GetElementEqualsComparer () == rhs.GetElementEqualsComparer ()); Not LITERALLY required, but results undefined if these comparers produce diffrent answers
366 // union operation is commutative; and O(N) in side we iterate over, and < O(N) in side we do lookups
367 // on, so do iteration on shorter side
368 if (lhs.size () < rhs.size ()) {
369 return rhs.Union (static_cast<const Iterable<T>&> (lhs));
370 }
371 else {
372 return lhs.Union (static_cast<const Iterable<T>&> (rhs));
373 }
374 }
375 template <typename T>
376 Set<T> Set<T>::Difference (const Set& rhs) const
377 {
378 using namespace Stroika::Foundation::Common;
379 Set result{this->CloneEmpty ()};
380 /*
381 * whether its better to incrementally create the result set, or better to incrementally remove
382 * from the result set (performance wise) (probably) depends on how close *this and rhs are to one another.
383 *
384 * note: TRIED using Apply() - and didn't seem to help performance --LGP 2021-11-08
385 */
386 for (const auto& i : *this) {
387 if (not rhs.Contains (i)) {
388 result.Add (i);
389 }
390 }
391 return result;
392 }
393 template <typename T>
394 Set<T> Set<T>::Difference (const Iterable<value_type>& rhs) const
395 {
396 /*
397 * We could iterate (doubly nested loop) over both *this and rhs, and that would avoid constructing
398 * an intermediate object. However, in the INNER loop, we would do an O(N) operation, and this way we
399 * probably have an (O(Log(N)) operation in the inner loop. At least for larger containers, that
400 * makes sense (except for requiring more memory temporarily). For smaller ones, it probably doesn't matter.
401 *
402 * OR - maybe better, could CLONE this, and iterate over rhs, and just remove els as needed. for special case where nothing removed
403 * that would be faster (because of COW), and maybe in general faster.
404 *
405 * OR return Difference (Set{this->GetElementEqualsComparer (), rhs});
406 *
407 * note: TRIED using Apply() - and didn't seem to help performance --LGP 2021-11-08
408 */
409 Set<T> result = *this;
410 for (const auto& i : rhs) {
411 result.RemoveIf (i);
412 }
413 return result;
414 }
415 template <typename T>
416 Set<T> Set<T>::Difference (ArgByValueType<value_type> rhs) const
417 {
418 /*
419 * Could implement as return Difference (Set{rhs});
420 * But due to COW in SharedByValue, this is better if 'rhs' not found in this.
421 */
422 Set<T> result = *this;
423 result.RemoveIf (rhs);
424 return result;
425 }
426 template <typename T>
428 {
429 Add (item);
430 return *this;
431 }
432 template <typename T>
434 {
435 AddAll (items);
436 return *this;
437 }
438 template <typename T>
440 {
441 RemoveIf (item);
442 return *this;
443 }
444 template <typename T>
446 {
447 RemoveAll (items);
448 return *this;
449 }
450 template <typename T>
452 {
453 *this = Intersection (items);
454 return *this;
455 }
456 template <typename T>
457 inline void Set<T>::clear ()
458 {
459 RemoveAll ();
460 }
461 template <typename T>
463 {
464 Iterator<value_type> r{nullptr};
465 _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (item, nullptr, &r);
466 return move (r);
467 }
468 template <typename T>
469 inline auto Set<T>::insert (ArgByValueType<value_type> item) -> pair<const_iterator, bool>
471 auto i = AddIf (item);
472 return make_pair (this->find (item), i);
473 }
474 template <typename T>
475 inline auto Set<T>::insert (const_iterator /*ignored*/, ArgByValueType<value_type> item) -> pair<const_iterator, bool>
476 {
477 return this->insert (item);
478 }
479 template <typename T>
480 template <class InputIt>
481 inline void Set<T>::insert (InputIt first, InputIt last)
482 {
483 AddAll (first, last);
484 }
485 template <typename T>
486 inline void Set<T>::insert (initializer_list<T> ilist)
487 {
488 AddAll (ilist);
489 }
490 template <typename T>
492 {
493 Remove (item);
494 }
495 template <typename T>
497 {
498 Iterator<T> nextI{nullptr};
499 this->Remove (i, &nextI);
500 return nextI;
501 }
502 template <typename T>
503 inline auto Set<T>::CloneEmpty () const -> Set
504 {
505 return Set{_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().CloneEmpty ()};
506 }
507 template <typename T>
508 auto Set<T>::_GetWritableRepAndPatchAssociatedIterator (const Iterator<value_type>& i) -> tuple<_IRep*, Iterator<value_type>>
510 Require (not i.Done ());
511 using element_type = typename inherited::_SharedByValueRepType::element_type;
512 Iterator<value_type> patchedIterator = i;
513 element_type* writableRep = this->_fRep.rwget ([&] (const element_type& prevRepPtr) -> typename inherited::_SharedByValueRepType::shared_ptr_type {
514 return Debug::UncheckedDynamicCast<const _IRep&> (prevRepPtr).CloneAndPatchIterator (&patchedIterator);
515 });
516 AssertNotNull (writableRep);
517 return make_tuple (Debug::UncheckedDynamicCast<_IRep*> (writableRep), move (patchedIterator));
518 }
519 template <typename T>
520 inline void Set<T>::_AssertRepValidType () const
521 {
523 [[maybe_unused]] _SafeReadRepAccessor<_IRep> ignored{this};
525 }
526 template <typename T>
527 inline bool Set<T>::operator== (const Set& rhs) const
528 {
529 return EqualsComparer{}(*this, rhs);
530 }
531 template <typename T>
532 inline bool Set<T>::operator== (const Iterable<value_type>& rhs) const
533 {
534 return EqualsComparer{}(*this, rhs);
535 }
536
537 /*
538 ********************************************************************************
539 ******************************** Set<T>::_IRep *********************************
540 ********************************************************************************
541 */
542 template <typename T>
544 {
545 // for some reps, this is fast (vector, std::map), but others its quite slow, and not that great a test.
546 // so for now, just iterate to see
547 constexpr bool kCanUseGetLengthAsOptimizationCheck_ = false;
548 if (this == &rhs) {
549 return true;
550 }
551 if (kCanUseGetLengthAsOptimizationCheck_) {
552 if (this->size () != rhs.size ()) {
553 return false;
554 }
555 }
556 // Note - no need to iterate over rhs because we checked sizes the same
557 [[maybe_unused]] size_t rhsSize{};
558 for (auto i = rhs.MakeIterator (); not i.Done (); ++i) {
559 if (not Lookup (*i, nullptr, nullptr)) {
560 return false;
561 }
562 ++rhsSize;
563 }
564 if (not kCanUseGetLengthAsOptimizationCheck_) {
565 return rhsSize == this->size ();
566 }
567 return true;
568 }
569
570 /*
571 ********************************************************************************
572 ************************* Set<T>::EqualsComparer *******************************
573 ********************************************************************************
574 */
575 template <typename T>
576 inline bool Set<T>::EqualsComparer::operator() (const Set& lhs, const Set& rhs) const
577 {
578 bool result = _SafeReadRepAccessor<_IRep>{&lhs}._ConstGetRep ().Equals (_SafeReadRepAccessor<_IRep>{&rhs}._ConstGetRep ());
579 Ensure (result == _SafeReadRepAccessor<_IRep>{&rhs}._ConstGetRep ().Equals (_SafeReadRepAccessor<_IRep>{&lhs}._ConstGetRep ())); // if this fails caller probably provided incompatible LHS/RHS comparers
580 return result;
581 }
582 template <typename T>
583 inline bool Set<T>::EqualsComparer::operator() (const Set& lhs, const Iterable<value_type>& rhs) const
584 {
585 return _SafeReadRepAccessor<_IRep>{&lhs}._ConstGetRep ().Equals (_SafeReadRepAccessor<typename Iterable<T>::_IRep>{&rhs}._ConstGetRep ());
586 }
587 template <typename T>
588 inline bool Set<T>::EqualsComparer::operator() (const Iterable<value_type>& lhs, const Set& rhs) const
589 {
590 return _SafeReadRepAccessor<_IRep>{&rhs}._ConstGetRep ().Equals (_SafeReadRepAccessor<typename Iterable<T>::_IRep>{&lhs}._ConstGetRep ());
591 }
592
593 /*
594 ********************************************************************************
595 ******************************* Set<T> operators *******************************
596 ********************************************************************************
597 */
598 template <typename T>
599 inline Set<T> operator+ (const Set<T>& lhs, const Iterable<T>& rhs)
600 {
601 return lhs.Union (rhs);
602 }
603 template <typename T>
604 inline Set<T> operator+ (const Set<T>& lhs, const T& rhs)
605 {
606 return lhs.Union (rhs);
607 }
608 template <typename T>
609 inline Set<T> operator- (const Set<T>& lhs, const Iterable<T>& rhs)
610 {
611 return lhs.Difference (rhs);
612 }
613 template <typename T>
614 inline Set<T> operator- (const Set<T>& lhs, const T& rhs)
615 {
616 return lhs.Difference (rhs);
617 }
618 template <typename T>
619 inline Set<T> operator^ (const Set<T>& lhs, const Iterable<T>& rhs)
620 {
621 return lhs.Intersection (rhs);
622 }
623 template <typename T>
624 inline Set<T> operator^ (const Iterable<T>& lhs, const Set<T>& rhs)
625 {
626 return rhs.Intersection (lhs); // intersection is commutative
627 }
628 template <typename T>
629 inline Set<T> operator^ (const Set<T>& lhs, const Set<T>& rhs)
630 {
631 return lhs.Intersection (rhs);
632 }
633
634}
#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 bool _Equals_Reference_Implementation(const typename Iterable< value_type >::_IRep &rhs) const
Definition Set.inl:543
virtual bool Lookup(ArgByValueType< value_type > item, optional< value_type > *oResult, Iterator< value_type > *iResult) const =0
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
Definition Set.h:105
nonvirtual Set & operator^=(const Iterable< value_type > &items)
Definition Set.inl:451
nonvirtual bool contains(ArgByValueType< value_type > item) const
Definition Set.inl:106
nonvirtual bool ContainsAny(const Iterable< value_type > &items) const
Definition Set.inl:116
nonvirtual Iterator< value_type > find(ArgByValueType< value_type > item) const
Definition Set.inl:462
nonvirtual optional< value_type > Lookup(ArgByValueType< value_type > item) const
Definition Set.inl:131
nonvirtual ElementEqualityComparerType GetElementEqualsComparer() const
Definition Set.inl:96
nonvirtual bool AddIf(ArgByValueType< value_type > item)
Definition Set.inl:143
nonvirtual bool Intersects(const Iterable< value_type > &rhs) const
return true iff the Intersection () is non-empty
Definition Set.inl:268
nonvirtual bool IsSubsetOf(const Set &superset) const
Definition Set.inl:121
nonvirtual Set CloneEmpty() const
for return Set<T> { s->GetEqualsComparer(); } - except more efficient - clones settings/dynamic subty...
Definition Set.inl:503
nonvirtual void Remove(ArgByValueType< value_type > item)
Remove the item (given by value or iterator pointing to it) from the contain. The item MUST exist.
Definition Set.inl:182
nonvirtual RESULT_CONTAINER Map(ELEMENT_MAPPER &&elementMapper) const
'override' Iterable<>::Map () function so RESULT_CONTAINER defaults to Set, and improve that case to ...
nonvirtual RESULT_CONTAINER Where(INCLUDE_PREDICATE &&includeIfTrue) const
nonvirtual Set & operator+=(ArgByValueType< value_type > item)
Definition Set.inl:427
nonvirtual bool operator==(const Set &rhs) const
Definition Set.inl:527
nonvirtual bool ContainsAll(const Iterable< value_type > &items) const
Definition Set.inl:111
nonvirtual bool RemoveIf(ArgByValueType< value_type > item)
Definition Set.inl:194
typename inherited::value_type value_type
Definition Set.h:122
nonvirtual void erase(ArgByValueType< value_type > item)
STL-ish alias for Remove ().
Definition Set.inl:491
nonvirtual Set & operator-=(ArgByValueType< value_type > item)
Definition Set.inl:439
nonvirtual pair< const_iterator, bool > insert(ArgByValueType< value_type > item)
Definition Set.inl:469
nonvirtual void Add(ArgByValueType< value_type > item)
Definition Set.inl:138
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 Set.inl:508
nonvirtual void AddAll(ITERATOR_OF_ADDABLE &&start, ITERATOR_OF_ADDABLE2 &&end)
Implementation detail for iterator implementors.
Definition Iterable.h:1569
virtual Iterator< value_type > MakeIterator() const =0
Iterable<T> is a base class for containers which easily produce an Iterator<T> to traverse them.
Definition Iterable.h:237
nonvirtual bool Any() const
Any() same as not empty (); Any (includeIfTrue) returns true iff includeIfTrue returns true on any va...
nonvirtual bool All(const function< bool(ArgByValueType< T >)> &testEachElt) const
return true iff argument predicate returns true for each element of the iterable
Definition Iterable.inl:940
nonvirtual size_t size() const
Returns the number of items contained.
Definition Iterable.inl:300
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
conditional_t<(sizeof(CHECK_T)<=2 *sizeof(void *)) and is_trivially_copyable_v< CHECK_T >, CHECK_T, const CHECK_T & > ArgByValueType
This is an alias for 'T' - but how we want to pass it on stack as formal parameter.
Definition TypeHints.h:32
Set< T > operator^(const Set< T > &lhs, const Iterable< T > &rhs)
Definition Set.inl:619
Collection< T > operator+(const Iterable< T > &lhs, const Collection< T > &rhs)
Set< T > operator-(const Set< T > &lhs, const Iterable< T > &rhs)
Definition Set.inl:609
Compare Set<>s or Iterable<>s for equality.
Definition Set.h:611