Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Bijection.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 ******************** Bijection_Base::InjectivityViolation **********************
19 ********************************************************************************
20 */
21 inline Bijection_Base::InjectivityViolation::InjectivityViolation ()
22 : inherited{"Injectivity violation"sv}
23 {
24 }
25
26 /*
27 ********************************************************************************
28 ******************** Bijection<DOMAIN_TYPE, RANGE_TYPE> ************************
29 ********************************************************************************
30 */
31 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
33 requires (IEqualsComparer<equal_to<DOMAIN_TYPE>, DOMAIN_TYPE> and IEqualsComparer<equal_to<RANGE_TYPE>, RANGE_TYPE>)
34 : Bijection{equal_to<DOMAIN_TYPE>{}, equal_to<RANGE_TYPE>{}}
35 {
36 _AssertRepValidType ();
37 }
38 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
39 template <IEqualsComparer<DOMAIN_TYPE> DOMAIN_EQUALS_COMPARER, IEqualsComparer<RANGE_TYPE> RANGE_EQUALS_COMPARER>
40 inline Bijection<DOMAIN_TYPE, RANGE_TYPE>::Bijection (DOMAIN_EQUALS_COMPARER&& domainEqualsComparer, RANGE_EQUALS_COMPARER&& rangeEqualsComparer)
41 : Bijection{DataExchange::ValidationStrategy::eAssertion, forward<DOMAIN_EQUALS_COMPARER> (domainEqualsComparer),
42 forward<RANGE_EQUALS_COMPARER> (rangeEqualsComparer)}
43 {
44 _AssertRepValidType ();
45 }
46 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
47 template <IEqualsComparer<DOMAIN_TYPE> DOMAIN_EQUALS_COMPARER, IEqualsComparer<RANGE_TYPE> RANGE_EQUALS_COMPARER>
49 DOMAIN_EQUALS_COMPARER&& domainEqualsComparer, RANGE_EQUALS_COMPARER&& rangeEqualsComparer)
50 : inherited{Factory::Bijection_Factory<DOMAIN_TYPE, RANGE_TYPE, remove_cvref_t<DOMAIN_EQUALS_COMPARER>, remove_cvref_t<RANGE_EQUALS_COMPARER>>::Default () (
51 injectivityCheckPolicy, forward<DOMAIN_EQUALS_COMPARER> (domainEqualsComparer), forward<RANGE_EQUALS_COMPARER> (rangeEqualsComparer))}
52 {
53 _AssertRepValidType ();
54 }
55 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
56 inline Bijection<DOMAIN_TYPE, RANGE_TYPE>::Bijection (const initializer_list<value_type>& src)
57 requires (IEqualsComparer<equal_to<DOMAIN_TYPE>, DOMAIN_TYPE> and IEqualsComparer<equal_to<RANGE_TYPE>, RANGE_TYPE>)
58 : Bijection{}
59 {
60 AddAll (src);
61 _AssertRepValidType ();
62 }
63 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
64 template <IEqualsComparer<DOMAIN_TYPE> DOMAIN_EQUALS_COMPARER, IEqualsComparer<RANGE_TYPE> RANGE_EQUALS_COMPARER>
65 inline Bijection<DOMAIN_TYPE, RANGE_TYPE>::Bijection (DOMAIN_EQUALS_COMPARER&& domainEqualsComparer,
66 RANGE_EQUALS_COMPARER&& rangeEqualsComparer, const initializer_list<value_type>& src)
67 : Bijection{forward<DOMAIN_EQUALS_COMPARER> (domainEqualsComparer), forward<RANGE_EQUALS_COMPARER> (rangeEqualsComparer)}
68 {
69 AddAll (src);
70 _AssertRepValidType ();
71 }
72#if !qCompilerAndStdLib_RequiresNotMatchInlineOutOfLineForTemplateClassBeingDefined_Buggy
73 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
74 template <IIterableOfTo<KeyValuePair<DOMAIN_TYPE, RANGE_TYPE>> ITERABLE_OF_ADDABLE>
75 inline Bijection<DOMAIN_TYPE, RANGE_TYPE>::Bijection (ITERABLE_OF_ADDABLE&& src)
76 requires (not derived_from<remove_cvref_t<ITERABLE_OF_ADDABLE>, Bijection<DOMAIN_TYPE, RANGE_TYPE>>)
77 : Bijection{}
78 {
79 AddAll (forward<ITERABLE_OF_ADDABLE> (src));
80 _AssertRepValidType ();
81 }
82#endif
83 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
84 template <IEqualsComparer<DOMAIN_TYPE> DOMAIN_EQUALS_COMPARER, IEqualsComparer<RANGE_TYPE> RANGE_EQUALS_COMPARER, IIterableOfTo<KeyValuePair<DOMAIN_TYPE, RANGE_TYPE>> ITERABLE_OF_ADDABLE>
85 inline Bijection<DOMAIN_TYPE, RANGE_TYPE>::Bijection (DOMAIN_EQUALS_COMPARER&& domainEqualsComparer,
86 RANGE_EQUALS_COMPARER&& rangeEqualsComparer, ITERABLE_OF_ADDABLE&& src)
87 : Bijection{forward<DOMAIN_EQUALS_COMPARER> (domainEqualsComparer), forward<RANGE_EQUALS_COMPARER> (rangeEqualsComparer)}
88 {
89 AddAll (forward<ITERABLE_OF_ADDABLE> (src));
90 _AssertRepValidType ();
91 }
92 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
93 template <IInputIterator<KeyValuePair<DOMAIN_TYPE, RANGE_TYPE>> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2>
94 Bijection<DOMAIN_TYPE, RANGE_TYPE>::Bijection (ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
95 requires (IEqualsComparer<equal_to<DOMAIN_TYPE>, DOMAIN_TYPE> and IEqualsComparer<equal_to<RANGE_TYPE>, RANGE_TYPE>)
96 : Bijection{}
97 {
98 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE2> (end));
99 _AssertRepValidType ();
100 }
101 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
102 template <IEqualsComparer<DOMAIN_TYPE> DOMAIN_EQUALS_COMPARER, IEqualsComparer<RANGE_TYPE> RANGE_EQUALS_COMPARER,
103 IInputIterator<KeyValuePair<DOMAIN_TYPE, RANGE_TYPE>> ITERATOR_OF_ADDABLE, sentinel_for<remove_cvref_t<ITERATOR_OF_ADDABLE>> ITERATOR_OF_ADDABLE2>
104 Bijection<DOMAIN_TYPE, RANGE_TYPE>::Bijection (DOMAIN_EQUALS_COMPARER&& domainEqualsComparer, RANGE_EQUALS_COMPARER&& rangeEqualsComparer,
105 ITERATOR_OF_ADDABLE&& start, ITERATOR_OF_ADDABLE2&& end)
106 : Bijection{forward<DOMAIN_EQUALS_COMPARER> (domainEqualsComparer), forward<RANGE_EQUALS_COMPARER> (rangeEqualsComparer)}
107 {
108 AddAll (forward<ITERATOR_OF_ADDABLE> (start), forward<ITERATOR_OF_ADDABLE2> (end));
109 _AssertRepValidType ();
110 }
111 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
112 inline Bijection<DOMAIN_TYPE, RANGE_TYPE>::Bijection (const shared_ptr<_IRep>& src) noexcept
113 : inherited{src}
114 {
115 RequireNotNull (src);
116 _AssertRepValidType ();
117 }
118 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
119 inline Bijection<DOMAIN_TYPE, RANGE_TYPE>::Bijection (shared_ptr<_IRep>&& src) noexcept
120 : inherited{(RequireExpression (src != nullptr), move (src))}
121 {
122 _AssertRepValidType ();
123 }
124 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
125 inline auto Bijection<DOMAIN_TYPE, RANGE_TYPE>::GetDomainEqualsComparer () const -> DomainEqualsCompareFunctionType
126 {
127 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().GetDomainEqualsComparer ();
128 }
129 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
130 inline auto Bijection<DOMAIN_TYPE, RANGE_TYPE>::GetRangeEqualsComparer () const -> RangeEqualsCompareFunctionType
131 {
132 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().GetRangeEqualsComparer ();
133 }
134 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
136 {
137 // need inherited temporarily til we remove deprecated Map function
138 //return this->template Map<DOMAIN_TYPE> ([] (const pair<DOMAIN_TYPE, RANGE_TYPE>& elt) { return elt.first; });
139 return this->inherited::template Map<Iterable<DOMAIN_TYPE>> ([] (const pair<DOMAIN_TYPE, RANGE_TYPE>& elt) { return elt.first; });
140 }
141 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
143 {
144 // need inherited temporarily til we remove deprecated Map function
145 //return this->Map<RANGE_TYPE> ([] (const pair<DOMAIN_TYPE, RANGE_TYPE>& elt) { return elt.second; });
146 return this->inherited::template Map<Iterable<RANGE_TYPE>> ([] (const pair<DOMAIN_TYPE, RANGE_TYPE>& elt) { return elt.second; });
147 }
148 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
149 inline bool Bijection<DOMAIN_TYPE, RANGE_TYPE>::Lookup (ArgByValueType<DomainType> key, RangeType* item) const
150 {
151 if (item == nullptr) {
152 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, nullptr);
153 }
154 else {
155 optional<RangeType> tmp;
156 if (_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, &tmp)) {
157 *item = *tmp;
158 return true;
159 }
160 return false;
161 }
162 }
163 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
164 inline bool Bijection<DOMAIN_TYPE, RANGE_TYPE>::Lookup (ArgByValueType<DomainType> key, optional<RangeType>* item) const
165 {
166 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, item);
167 }
168 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
169 inline optional<RANGE_TYPE> Bijection<DOMAIN_TYPE, RANGE_TYPE>::Lookup (ArgByValueType<DomainType> key) const
170 {
171 optional<RANGE_TYPE> r;
172 [[maybe_unused]] bool result = _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, &r);
173 Ensure (result == r.has_value ());
174 return r;
175 }
176 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
177 inline bool Bijection<DOMAIN_TYPE, RANGE_TYPE>::Lookup (ArgByValueType<DomainType> key, nullptr_t) const
178 {
179 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, nullptr);
180 }
181 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
182 inline RANGE_TYPE Bijection<DOMAIN_TYPE, RANGE_TYPE>::LookupValue (ArgByValueType<DomainType> key, ArgByValueType<RangeType> defaultValue) const
183 {
184 optional<RANGE_TYPE> r = Lookup (key);
185 return r.has_value () ? *r : defaultValue;
186 }
187 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
188 inline bool Bijection<DOMAIN_TYPE, RANGE_TYPE>::InverseLookup (ArgByValueType<RangeType> key, DomainType* item) const
189 {
190 if (item == nullptr) {
191 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().InverseLookup (key, nullptr);
192 }
193 else {
194 optional<DomainType> tmp;
195 if (_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().InverseLookup (key, &tmp)) {
196 *item = *tmp;
197 return true;
198 }
199 return false;
200 }
201 }
202 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
203 inline bool Bijection<DOMAIN_TYPE, RANGE_TYPE>::InverseLookup (ArgByValueType<RangeType> key, optional<DomainType>* item) const
204 {
205 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().InverseLookup (key, item);
206 }
207 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
208 inline optional<DOMAIN_TYPE> Bijection<DOMAIN_TYPE, RANGE_TYPE>::InverseLookup (ArgByValueType<RangeType> key) const
209 {
210 optional<DOMAIN_TYPE> r;
211 [[maybe_unused]] bool result = _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().InverseLookup (key, &r);
212 Ensure (result == r.has_value ());
213 return r;
214 }
215 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
216 inline bool Bijection<DOMAIN_TYPE, RANGE_TYPE>::InverseLookup (ArgByValueType<RangeType> key, nullptr_t) const
217 {
218 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().InverseLookup (key, nullptr);
219 }
220 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
221 inline DOMAIN_TYPE Bijection<DOMAIN_TYPE, RANGE_TYPE>::InverseLookupValue (ArgByValueType<RangeType> key, ArgByValueType<DomainType> defaultValue) const
222 {
223 optional<DOMAIN_TYPE> r = InverseLookup (key);
224 return r.has_value () ? *r : defaultValue;
225 }
226 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
228 {
229 vector<RANGE_TYPE> tmp;
230 tmp.reserve (values.size ());
231 for (const auto& i : values) {
232 tmp.push_back (*Lookup (i));
233 }
234 return Iterable<RANGE_TYPE>{tmp};
235 }
236 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
238 {
239 vector<DOMAIN_TYPE> tmp;
240 tmp.reserve (values.size ());
241 for (const auto& i : values) {
242 tmp.push_back (*InverseLookup (i));
243 }
244 return Iterable<DOMAIN_TYPE>{move (tmp)};
245 }
246 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
247 template <typename RESULT_CONTAINER, invocable<pair<DOMAIN_TYPE, RANGE_TYPE>> ELEMENT_MAPPER>
248 inline RESULT_CONTAINER Bijection<DOMAIN_TYPE, RANGE_TYPE>::Map (ELEMENT_MAPPER&& elementMapper) const
249 requires (convertible_to<invoke_result_t<ELEMENT_MAPPER, pair<DOMAIN_TYPE, RANGE_TYPE>>, typename RESULT_CONTAINER::value_type> or
250 convertible_to<invoke_result_t<ELEMENT_MAPPER, pair<DOMAIN_TYPE, RANGE_TYPE>>, optional<typename RESULT_CONTAINER::value_type>>)
251 {
252 if constexpr (same_as<RESULT_CONTAINER, Bijection>) {
253 // clone the rep so we retain any ordering function/etc, rep type
254 return inherited::template Where<RESULT_CONTAINER> (
255 forward<ELEMENT_MAPPER> (elementMapper), RESULT_CONTAINER{_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().CloneEmpty ()});
256 }
257 else {
258 return inherited::template Where<RESULT_CONTAINER> (forward<ELEMENT_MAPPER> (elementMapper)); // default Iterable<> implementation then...
259 }
260 }
261 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
262 template <derived_from<Iterable<pair<DOMAIN_TYPE, RANGE_TYPE>>> RESULT_CONTAINER, predicate<pair<DOMAIN_TYPE, RANGE_TYPE>> INCLUDE_PREDICATE>
263 inline auto Bijection<DOMAIN_TYPE, RANGE_TYPE>::Where (INCLUDE_PREDICATE&& includeIfTrue) const -> RESULT_CONTAINER
264 {
265 if constexpr (same_as<RESULT_CONTAINER, Bijection>) {
266 // clone the rep so we retain any ordering function/etc, rep type
267 return inherited::template Where<RESULT_CONTAINER> (
268 forward<INCLUDE_PREDICATE> (includeIfTrue), RESULT_CONTAINER{_SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().CloneEmpty ()});
269 }
270 else {
271 return inherited::template Where<RESULT_CONTAINER> (forward<INCLUDE_PREDICATE> (includeIfTrue)); // default Iterable<> implementation then...
272 }
273 }
274 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
276 {
277 // @todo - fix very primitive implementation - could use Generator instead?, generator avoids copy of data, and just copies includeIfTrue filter function
278 _SafeReadRepAccessor<_IRep> lhs{this};
279 Bijection result = lhs._ConstGetRep ().CloneEmpty ();
280 for (const auto& i : *this) {
281 if (domainValues.Contains (i.first, this->GetDomainEqualsComparer ())) {
282 result.Add (i);
283 }
284 }
285 return result;
286 }
287 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
289 {
290 // @todo - fix very primitive implementation - could use Generator instead?, generator avoids copy of data, and just copies includeIfTrue filter function
291 _SafeReadRepAccessor<_IRep> lhs{this};
292 Bijection result = lhs._ConstGetRep ().CloneEmpty ();
293 for (const auto& i : *this) {
294 if (rangeValues.Contains (i.second, this->GetRangeEqualsComparer ())) {
295 result.Add (i);
296 }
297 }
298 return result;
299 }
300 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
301 inline bool Bijection<DOMAIN_TYPE, RANGE_TYPE>::ContainsDomainElement (ArgByValueType<DomainType> key) const
302 {
303 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Lookup (key, nullptr);
304 }
305 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
306 inline bool Bijection<DOMAIN_TYPE, RANGE_TYPE>::ContainsRangeElement (ArgByValueType<RangeType> v) const
307 {
308 // REIMPLEMENT USING InverseLookup()!!! @todo
309 for (value_type t : *this) {
310 if (GetRangeEqualsComparer () (t.second, v)) {
311 return true;
312 }
313 }
314 return false;
315 }
316 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
317 inline void Bijection<DOMAIN_TYPE, RANGE_TYPE>::Add (ArgByValueType<DomainType> key, ArgByValueType<RangeType> newElt)
318 {
319 _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().Add (key, newElt);
320 }
321 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
322 template <typename ADDABLE_T>
323 inline void Bijection<DOMAIN_TYPE, RANGE_TYPE>::Add (ADDABLE_T&& p)
324 requires (convertible_to<ADDABLE_T, pair<DOMAIN_TYPE, RANGE_TYPE>> or convertible_to<ADDABLE_T, KeyValuePair<DOMAIN_TYPE, RANGE_TYPE>>)
325 {
326 if constexpr (is_convertible_v<remove_cvref_t<ADDABLE_T>, value_type>) {
327 _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().Add (p.first, p.second);
328 }
329 else {
330 static_assert (is_convertible_v<ADDABLE_T, Common::KeyValuePair<DomainType, RangeType>>);
331 _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().Add (p.fKey, p.fValue);
332 }
333 }
334 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
335 template <IInputIterator<KeyValuePair<DOMAIN_TYPE, RANGE_TYPE>> COPY_FROM_ITERATOR_KEYVALUE, sentinel_for<remove_cvref_t<COPY_FROM_ITERATOR_KEYVALUE>> COPY_FROM_ITERATOR_KEYVALUE2>
336 void Bijection<DOMAIN_TYPE, RANGE_TYPE>::AddAll (COPY_FROM_ITERATOR_KEYVALUE&& start, COPY_FROM_ITERATOR_KEYVALUE2&& end)
337 {
338 for (auto i = forward<COPY_FROM_ITERATOR_KEYVALUE> (start); i != forward<COPY_FROM_ITERATOR_KEYVALUE2> (end); ++i) {
339 Add (*i);
340 }
341 }
342 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
343 template <IIterableOfTo<KeyValuePair<DOMAIN_TYPE, RANGE_TYPE>> CONTAINER_OF_KEYVALUE>
344 inline void Bijection<DOMAIN_TYPE, RANGE_TYPE>::AddAll (const CONTAINER_OF_KEYVALUE& items)
345 {
346 // see http://stroika-bugs.sophists.com/browse/STK-645
347 /*
348 * Note - unlike some other containers - we don't need to check for this != &s because if we
349 * attempt to add items that already exist, it would do nothing to our iteration
350 * and therefore not lead to an infinite loop.
351 */
352 AddAll (std::begin (items), std::end (items));
353 }
354 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
355 inline void Bijection<DOMAIN_TYPE, RANGE_TYPE>::RemoveDomainElement (ArgByValueType<DomainType> d)
356 {
357 _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().RemoveDomainElement (d);
358 }
359 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
360 inline void Bijection<DOMAIN_TYPE, RANGE_TYPE>::RemoveRangeElement (ArgByValueType<RangeType> r)
361 {
362 _SafeReadWriteRepAccessor<_IRep>{this}._GetWriteableRep ().RemoveRangeElement (r);
363 }
364 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
366 {
367 Require (not i.Done ());
368 auto [writerRep, patchedIterator] = _GetWritableRepAndPatchAssociatedIterator (i);
369 writerRep->Remove (patchedIterator, nextI);
370 }
371 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
373 {
374 _SafeReadRepAccessor<_IRep> tmp{this}; // important to use READ not WRITE accessor, because write accessor would have already cloned the data
375 if (not tmp._ConstGetRep ().empty ()) {
376 this->_fRep = tmp._ConstGetRep ().CloneEmpty ();
377 }
378 }
379 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
380 template <predicate<pair<DOMAIN_TYPE, RANGE_TYPE>> PREDICATE>
382 {
383 size_t nRemoved{};
384 for (Iterator<pair<DOMAIN_TYPE, RANGE_TYPE>> i = this->begin (); i != this->end ();) {
385 if (p (*i)) {
386 Remove (i, &i);
387 ++nRemoved;
388 }
389 else {
390 ++i;
391 }
392 }
393 return nRemoved;
394 }
395 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
396 template <typename TARGET_CONTAINER>
397 TARGET_CONTAINER Bijection<DOMAIN_TYPE, RANGE_TYPE>::Inverse () const
398 {
399 TARGET_CONTAINER r;
400 for (value_type i : *this) {
401 r.Add (i.second, i.first);
402 }
403 return r;
404 }
405 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
406 template <typename CONTAINER_PAIR_RANGE_DOMAIN>
407 inline CONTAINER_PAIR_RANGE_DOMAIN Bijection<DOMAIN_TYPE, RANGE_TYPE>::As () const
408 {
409 // @todo change this to constructible_from....
410 if constexpr (derived_from<CONTAINER_PAIR_RANGE_DOMAIN, Iterable<pair<DOMAIN_TYPE, RANGE_TYPE>>>) {
411 return CONTAINER_PAIR_RANGE_DOMAIN{this->begin (), this->end ()};
412 }
413 else {
414 // STL containers may require the two iterator arguments to be of the same type
415 using BIT = decltype (this->begin ());
416 return CONTAINER_PAIR_RANGE_DOMAIN{this->begin (), BIT{this->end ()}};
417 }
418 }
419 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
421 {
422 RemoveAll ();
423 }
424 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
426 {
427 Iterator<value_type> nextI{nullptr};
428 this->Remove (i, &nextI);
429 return nextI;
430 }
431 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
432 template <IIterableOfTo<KeyValuePair<DOMAIN_TYPE, RANGE_TYPE>> ITERABLE_OF_ADDABLE>
434 {
435 AddAll (items);
436 return *this;
437 }
438 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
439 template <IIterableOfTo<KeyValuePair<DOMAIN_TYPE, RANGE_TYPE>> ITERABLE_OF_ADDABLE>
440 inline Bijection<DOMAIN_TYPE, RANGE_TYPE>& Bijection<DOMAIN_TYPE, RANGE_TYPE>::operator-= (const ITERABLE_OF_ADDABLE& items)
441 {
442 RemoveAll (items);
443 return *this;
444 }
445 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
447 -> tuple<_IRep*, Iterator<value_type>>
448 {
449 Require (not i.Done ());
450 using element_type = typename inherited::_SharedByValueRepType::element_type;
451 Iterator<value_type> patchedIterator = i;
452 element_type* writableRep = this->_fRep.rwget ([&] (const element_type& prevRepPtr) -> typename inherited::_SharedByValueRepType::shared_ptr_type {
453 return Debug::UncheckedDynamicCast<const _IRep&> (prevRepPtr).CloneAndPatchIterator (&patchedIterator);
454 });
455 AssertNotNull (writableRep);
456 return make_tuple (Debug::UncheckedDynamicCast<_IRep*> (writableRep), move (patchedIterator));
457 }
458 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
460 {
462 _SafeReadRepAccessor<_IRep>{this};
463 }
464 }
465 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
467 {
468 return _SafeReadRepAccessor<_IRep>{this}._ConstGetRep ().Equals (_SafeReadRepAccessor<_IRep>{&rhs}._ConstGetRep ());
469 }
470
471 /*
472 ********************************************************************************
473 ************** Bijection<DOMAIN_TYPE, RANGE_TYPE>::_IRep ***********************
474 ********************************************************************************
475 */
476 template <typename DOMAIN_TYPE, typename RANGE_TYPE>
478 {
479 if (this == &rhs) {
480 return true;
481 }
482 // If sizes differ, the Bijections differ
483 if (this->size () != rhs.size ()) {
484 return false;
485 }
486 // Since both sides are the same size, we can iterate over one, and make sure the key/values in the first
487 // are present, and with the same Bijection in the second.
488 for (auto i = this->MakeIterator (); not i.Done (); ++i) {
489 optional<RangeType> tmp;
490 if (not rhs.Lookup (i->first, &tmp) or not GetRangeEqualsComparer () (*tmp, i->second)) {
491 return false;
492 }
493 }
494 return true;
495 }
496
497}
#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
Bijection allows for the bijective (1-1) association of two elements.
Definition Bijection.h:103
nonvirtual void RemoveDomainElement(ArgByValueType< DomainType > d)
nonvirtual void RemoveAll()
RemoveAll removes all, or all matching (predicate, iterator range, equals comparer or whatever) items...
nonvirtual Iterable< DomainType > MapToDomain(const Iterable< RangeType > &values) const
nonvirtual Iterator< value_type > erase(const Iterator< value_type > &i)
STL-ish alias for Remove ().
nonvirtual void RemoveRangeElement(ArgByValueType< RangeType > r)
nonvirtual Bijection WhereDomainIntersects(const Iterable< DomainType > &domainValues) const
nonvirtual void Remove(const Iterator< value_type > &i, Iterator< value_type > *nextI=nullptr)
nonvirtual Bijection WhereRangeIntersects(const Iterable< RangeType > &rangeValues) const
nonvirtual CONTAINER_PAIR_RANGE_DOMAIN As() const
nonvirtual Iterable< DomainType > Preimage() const
nonvirtual void Add(ArgByValueType< DomainType > key, ArgByValueType< RangeType > newElt)
nonvirtual Bijection & operator+=(const ITERABLE_OF_ADDABLE &items)
nonvirtual RESULT_CONTAINER Where(INCLUDE_PREDICATE &&includeIfTrue) const
Like Iterable<T>::Where, but returning a bijection - subset of this bijection where includeIfTrue is ...
nonvirtual optional< DomainType > InverseLookup(ArgByValueType< RangeType > key) const
nonvirtual Bijection & operator-=(const ITERABLE_OF_ADDABLE &items)
nonvirtual RESULT_CONTAINER Map(ELEMENT_MAPPER &&elementMapper) const
'override' Iterable<>::Map () function so RESULT_CONTAINER defaults to Bijection, and improve that ca...
typename inherited::value_type value_type
Definition Bijection.h:120
nonvirtual Iterable< RangeType > MapToRange(const Iterable< DomainType > &values) const
nonvirtual DomainType InverseLookupValue(ArgByValueType< RangeType > key, ArgByValueType< DomainType > defaultValue=DomainType()) const
nonvirtual optional< RangeType > Lookup(ArgByValueType< DomainType > key) const
nonvirtual bool ContainsRangeElement(ArgByValueType< RangeType > v) const
nonvirtual Iterable< RangeType > Image() const
nonvirtual RangeType LookupValue(ArgByValueType< DomainType > key, ArgByValueType< RangeType > defaultValue=RangeType()) const
nonvirtual bool ContainsDomainElement(ArgByValueType< DomainType > key) const
nonvirtual bool operator==(const Bijection &rhs) const
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 void AddAll(const CONTAINER_OF_KEYVALUE &items)
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
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