Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qflatmap_p.h
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QFLATMAP_P_H
6#define QFLATMAP_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists for the convenience
13// of a number of Qt sources files. This header file may change from
14// version to version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtCore/qcontainertools_impl.h>
20#include "qlist.h"
21#include <QtCore/qtclasshelpermacros.h>
22#include "private/qglobal_p.h"
23
24#include <algorithm>
25#include <functional>
26#include <initializer_list>
27#include <iterator>
28#include <numeric>
29#include <type_traits>
30#include <utility>
31#include <vector>
32
33QT_BEGIN_NAMESPACE
34
35/*
36 QFlatMap provides an associative container backed by sorted sequential
37 containers. By default, QList is used.
38
39 Keys and values are stored in two separate containers. This provides improved
40 cache locality for key iteration and makes keys() and values() fast
41 operations.
42
43 One can customize the underlying container type by passing the KeyContainer
44 and MappedContainer template arguments:
45 QFlatMap<float, int, std::less<float>, std::vector<float>, std::vector<int>>
46*/
47
48namespace Qt {
49
51
52} // namespace Qt
53
54template <class Key, class T, class Compare>
55class QFlatMapValueCompare : protected Compare
56{
57public:
59 QFlatMapValueCompare(const Compare &key_compare)
60 : Compare(key_compare)
61 {
62 }
63
64 using value_type = std::pair<const Key, T>;
65 static constexpr bool is_comparator_noexcept = noexcept(
66 std::declval<Compare>()(std::declval<const Key &>(), std::declval<const Key &>()));
67
68 bool operator()(const value_type &lhs, const value_type &rhs) const
70 {
71 return Compare::operator()(lhs.first, rhs.first);
72 }
73};
74
75template<class Key, class T, class Compare = std::less<Key>, class KeyContainer = QList<Key>,
76 class MappedContainer = QList<T>>
77class QFlatMap : private QFlatMapValueCompare<Key, T, Compare>
78{
79 static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
80public:
81 using key_type = Key;
82 using mapped_type = T;
83 using value_compare = QFlatMapValueCompare<Key, T, Compare>;
85 using key_container_type = KeyContainer;
86 using mapped_container_type = MappedContainer;
88 using key_compare = Compare;
89
95
97 {
98 public:
100 using value_type = std::pair<const Key, T>;
101 using reference = std::pair<const Key &, T &>;
103 using iterator_category = std::random_access_iterator_tag;
104
105 iterator() = default;
106
108 : c(ac), i(ai)
109 {
110 }
111
113 {
114 return { c->keys[i], c->values[i] };
115 }
116
118 {
119 return { operator*() };
120 }
121
122 bool operator==(const iterator &o) const
123 {
124 return c == o.c && i == o.i;
125 }
126
127 bool operator!=(const iterator &o) const
128 {
129 return !operator==(o);
130 }
131
133 {
134 ++i;
135 return *this;
136 }
137
139 {
140
141 iterator r = *this;
142 ++*this;
143 return r;
144 }
145
147 {
148 --i;
149 return *this;
150 }
151
153 {
154 iterator r = *this;
155 --*this;
156 return r;
157 }
158
160 {
161 i += n;
162 return *this;
163 }
164
166 {
167 iterator ret = a;
168 return ret += n;
169 }
170
172 {
173 return n + a;
174 }
175
177 {
178 i -= n;
179 return *this;
180 }
181
183 {
184 iterator ret = a;
185 return ret -= n;
186 }
187
188 friend difference_type operator-(const iterator b, const iterator a)
189 {
190 return b.i - a.i;
191 }
192
194 {
195 size_type k = i + n;
196 return { c->keys[k], c->values[k] };
197 }
198
199 bool operator<(const iterator &other) const
200 {
201 return i < other.i;
202 }
203
204 bool operator>(const iterator &other) const
205 {
206 return i > other.i;
207 }
208
209 bool operator<=(const iterator &other) const
210 {
211 return i <= other.i;
212 }
213
214 bool operator>=(const iterator &other) const
215 {
216 return i >= other.i;
217 }
218
219 const Key &key() const { return c->keys[i]; }
220 T &value() const { return c->values[i]; }
221
222 private:
223 containers *c = nullptr;
224 size_type i = 0;
225 friend QFlatMap;
226 };
227
229 {
230 public:
232 using value_type = std::pair<const Key, const T>;
233 using reference = std::pair<const Key &, const T &>;
235 using iterator_category = std::random_access_iterator_tag;
236
237 const_iterator() = default;
238
240 : c(ac), i(ai)
241 {
242 }
243
245 : c(o.c), i(o.i)
246 {
247 }
248
250 {
251 return { c->keys[i], c->values[i] };
252 }
253
255 {
256 return { operator*() };
257 }
258
259 bool operator==(const const_iterator &o) const
260 {
261 return c == o.c && i == o.i;
262 }
263
264 bool operator!=(const const_iterator &o) const
265 {
266 return !operator==(o);
267 }
268
270 {
271 ++i;
272 return *this;
273 }
274
276 {
277
278 const_iterator r = *this;
279 ++*this;
280 return r;
281 }
282
284 {
285 --i;
286 return *this;
287 }
288
290 {
291 const_iterator r = *this;
292 --*this;
293 return r;
294 }
295
297 {
298 i += n;
299 return *this;
300 }
301
303 {
304 const_iterator ret = a;
305 return ret += n;
306 }
307
309 {
310 return n + a;
311 }
312
314 {
315 i -= n;
316 return *this;
317 }
318
320 {
321 const_iterator ret = a;
322 return ret -= n;
323 }
324
326 {
327 return b.i - a.i;
328 }
329
331 {
332 size_type k = i + n;
333 return { c->keys[k], c->values[k] };
334 }
335
336 bool operator<(const const_iterator &other) const
337 {
338 return i < other.i;
339 }
340
341 bool operator>(const const_iterator &other) const
342 {
343 return i > other.i;
344 }
345
346 bool operator<=(const const_iterator &other) const
347 {
348 return i <= other.i;
349 }
350
351 bool operator>=(const const_iterator &other) const
352 {
353 return i >= other.i;
354 }
355
356 const Key &key() const { return c->keys[i]; }
357 const T &value() const { return c->values[i]; }
358
359 private:
360 const containers *c = nullptr;
361 size_type i = 0;
362 friend QFlatMap;
363 };
364
365private:
366 template <class, class = void>
367 struct is_marked_transparent_type : std::false_type { };
368
369 template <class X>
371
372 template <class X>
373 using is_marked_transparent = typename std::enable_if<
375
376 template <typename It>
377 using is_compatible_iterator = typename std::enable_if<
379
380public:
381 QFlatMap() = default;
382
383 explicit QFlatMap(const key_container_type &keys, const mapped_container_type &values)
384 : c{keys, values}
385 {
386 ensureOrderedUnique();
387 }
388
389 explicit QFlatMap(key_container_type &&keys, const mapped_container_type &values)
390 : c{std::move(keys), values}
391 {
392 ensureOrderedUnique();
393 }
394
395 explicit QFlatMap(const key_container_type &keys, mapped_container_type &&values)
396 : c{keys, std::move(values)}
397 {
398 ensureOrderedUnique();
399 }
400
402 : c{std::move(keys), std::move(values)}
403 {
404 ensureOrderedUnique();
405 }
406
407 explicit QFlatMap(std::initializer_list<value_type> lst)
408 : QFlatMap(lst.begin(), lst.end())
409 {
410 }
411
412 template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
413 explicit QFlatMap(InputIt first, InputIt last)
414 {
415 initWithRange(first, last);
416 ensureOrderedUnique();
417 }
418
420 const mapped_container_type &values)
421 : c{keys, values}
422 {
423 }
424
426 const mapped_container_type &values)
427 : c{std::move(keys), values}
428 {
429 }
430
432 mapped_container_type &&values)
433 : c{keys, std::move(values)}
434 {
435 }
436
438 mapped_container_type &&values)
439 : c{std::move(keys), std::move(values)}
440 {
441 }
442
443 explicit QFlatMap(Qt::OrderedUniqueRange_t, std::initializer_list<value_type> lst)
444 : QFlatMap(Qt::OrderedUniqueRange, lst.begin(), lst.end())
445 {
446 }
447
448 template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
449 explicit QFlatMap(Qt::OrderedUniqueRange_t, InputIt first, InputIt last)
450 {
451 initWithRange(first, last);
452 }
453
454 explicit QFlatMap(const Compare &compare)
455 : value_compare(compare)
456 {
457 }
458
459 explicit QFlatMap(const key_container_type &keys, const mapped_container_type &values,
460 const Compare &compare)
461 : value_compare(compare), c{keys, values}
462 {
463 ensureOrderedUnique();
464 }
465
466 explicit QFlatMap(key_container_type &&keys, const mapped_container_type &values,
467 const Compare &compare)
468 : value_compare(compare), c{std::move(keys), values}
469 {
470 ensureOrderedUnique();
471 }
472
473 explicit QFlatMap(const key_container_type &keys, mapped_container_type &&values,
474 const Compare &compare)
475 : value_compare(compare), c{keys, std::move(values)}
476 {
477 ensureOrderedUnique();
478 }
479
481 const Compare &compare)
482 : value_compare(compare), c{std::move(keys), std::move(values)}
483 {
484 ensureOrderedUnique();
485 }
486
487 explicit QFlatMap(std::initializer_list<value_type> lst, const Compare &compare)
488 : QFlatMap(lst.begin(), lst.end(), compare)
489 {
490 }
491
492 template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
493 explicit QFlatMap(InputIt first, InputIt last, const Compare &compare)
494 : value_compare(compare)
495 {
496 initWithRange(first, last);
497 ensureOrderedUnique();
498 }
499
501 const mapped_container_type &values, const Compare &compare)
502 : value_compare(compare), c{keys, values}
503 {
504 }
505
507 const mapped_container_type &values, const Compare &compare)
508 : value_compare(compare), c{std::move(keys), values}
509 {
510 }
511
513 mapped_container_type &&values, const Compare &compare)
514 : value_compare(compare), c{keys, std::move(values)}
515 {
516 }
517
519 mapped_container_type &&values, const Compare &compare)
520 : value_compare(compare), c{std::move(keys), std::move(values)}
521 {
522 }
523
524 explicit QFlatMap(Qt::OrderedUniqueRange_t, std::initializer_list<value_type> lst,
525 const Compare &compare)
526 : QFlatMap(Qt::OrderedUniqueRange, lst.begin(), lst.end(), compare)
527 {
528 }
529
530 template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
531 explicit QFlatMap(Qt::OrderedUniqueRange_t, InputIt first, InputIt last, const Compare &compare)
532 : value_compare(compare)
533 {
534 initWithRange(first, last);
535 }
536
537 size_type count() const noexcept { return c.keys.size(); }
538 size_type size() const noexcept { return c.keys.size(); }
539 size_type capacity() const noexcept { return c.keys.capacity(); }
540 bool isEmpty() const noexcept { return c.keys.empty(); }
541 bool empty() const noexcept { return c.keys.empty(); }
542 containers extract() && { return std::move(c); }
543 const key_container_type &keys() const noexcept { return c.keys; }
544 const mapped_container_type &values() const noexcept { return c.values; }
545
547 {
548 c.keys.reserve(s);
549 c.values.reserve(s);
550 }
551
552 void clear()
553 {
554 c.keys.clear();
555 c.values.clear();
556 }
557
558 bool remove(const Key &key)
559 {
560 return do_remove(find(key));
561 }
562
563 template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
564 bool remove(const X &key)
565 {
566 return do_remove(find(key));
567 }
568
570 {
571 c.values.erase(toValuesIterator(it));
572 return fromKeysIterator(c.keys.erase(toKeysIterator(it)));
573 }
574
575 T take(const Key &key)
576 {
577 return do_take(find(key));
578 }
579
580 template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
581 T take(const X &key)
582 {
583 return do_take(find(key));
584 }
585
586 bool contains(const Key &key) const
587 {
588 return find(key) != end();
589 }
590
591 template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
592 bool contains(const X &key) const
593 {
594 return find(key) != end();
595 }
596
597 T value(const Key &key, const T &defaultValue) const
598 {
599 auto it = find(key);
600 return it == end() ? defaultValue : it.value();
601 }
602
603 template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
604 T value(const X &key, const T &defaultValue) const
605 {
606 auto it = find(key);
607 return it == end() ? defaultValue : it.value();
608 }
609
610 T value(const Key &key) const
611 {
612 auto it = find(key);
613 if (it == end())
614 return T();
615 return it.value();
616 }
617
618 template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
619 T value(const X &key) const
620 {
621 auto it = find(key);
622 if (it == end())
623 return T();
624 return it.value();
625 }
626
627 T &operator[](const Key &key)
628 {
629 return try_emplace(key).first.value();
630 }
631
632 T &operator[](Key &&key)
633 {
634 return try_emplace(std::move(key)).first.value();
635 }
636
637 T operator[](const Key &key) const
638 {
639 return value(key);
640 }
641
642 std::pair<iterator, bool> insert(const Key &key, const T &value)
643 {
644 return try_emplace(key, value);
645 }
646
647 std::pair<iterator, bool> insert(Key &&key, const T &value)
648 {
649 return try_emplace(std::move(key), value);
650 }
651
652 std::pair<iterator, bool> insert(const Key &key, T &&value)
653 {
654 return try_emplace(key, std::move(value));
655 }
656
657 std::pair<iterator, bool> insert(Key &&key, T &&value)
658 {
659 return try_emplace(std::move(key), std::move(value));
660 }
661
662 template <typename...Args>
663 std::pair<iterator, bool> try_emplace(const Key &key, Args&&...args)
664 {
665 auto it = lower_bound(key);
666 if (it == end() || key_compare::operator()(key, it.key())) {
667 c.values.emplace(toValuesIterator(it), std::forward<Args>(args)...);
668 return { fromKeysIterator(c.keys.insert(toKeysIterator(it), key)), true };
669 } else {
670 return {it, false};
671 }
672 }
673
674 template <typename...Args>
675 std::pair<iterator, bool> try_emplace(Key &&key, Args&&...args)
676 {
677 auto it = lower_bound(key);
678 if (it == end() || key_compare::operator()(key, it.key())) {
679 c.values.emplace(toValuesIterator(it), std::forward<Args>(args)...);
680 return { fromKeysIterator(c.keys.insert(toKeysIterator(it), std::move(key))), true };
681 } else {
682 return {it, false};
683 }
684 }
685
686 template <typename M>
687 std::pair<iterator, bool> insert_or_assign(const Key &key, M &&obj)
688 {
689 auto r = try_emplace(key, std::forward<M>(obj));
690 if (!r.second)
691 *toValuesIterator(r.first) = std::forward<M>(obj);
692 return r;
693 }
694
695 template <typename M>
696 std::pair<iterator, bool> insert_or_assign(Key &&key, M &&obj)
697 {
698 auto r = try_emplace(std::move(key), std::forward<M>(obj));
699 if (!r.second)
700 *toValuesIterator(r.first) = std::forward<M>(obj);
701 return r;
702 }
703
704 template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
705 void insert(InputIt first, InputIt last)
706 {
707 insertRange(first, last);
708 }
709
710 // ### Merge with the templated version above
711 // once we can use std::disjunction in is_compatible_iterator.
712 void insert(const value_type *first, const value_type *last)
713 {
714 insertRange(first, last);
715 }
716
717 template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
718 void insert(Qt::OrderedUniqueRange_t, InputIt first, InputIt last)
719 {
720 insertOrderedUniqueRange(first, last);
721 }
722
723 // ### Merge with the templated version above
724 // once we can use std::disjunction in is_compatible_iterator.
725 void insert(Qt::OrderedUniqueRange_t, const value_type *first, const value_type *last)
726 {
727 insertOrderedUniqueRange(first, last);
728 }
729
730 iterator begin() { return { &c, 0 }; }
731 const_iterator begin() const { return { &c, 0 }; }
732 const_iterator cbegin() const { return begin(); }
734 iterator end() { return { &c, c.keys.size() }; }
735 const_iterator end() const { return { &c, c.keys.size() }; }
736 const_iterator cend() const { return end(); }
737 const_iterator constEnd() const { return cend(); }
738 std::reverse_iterator<iterator> rbegin() { return std::reverse_iterator<iterator>(end()); }
739 std::reverse_iterator<const_iterator> rbegin() const
740 {
741 return std::reverse_iterator<const_iterator>(end());
742 }
743 std::reverse_iterator<const_iterator> crbegin() const { return rbegin(); }
744 std::reverse_iterator<iterator> rend() {
745 return std::reverse_iterator<iterator>(begin());
746 }
747 std::reverse_iterator<const_iterator> rend() const
748 {
749 return std::reverse_iterator<const_iterator>(begin());
750 }
751 std::reverse_iterator<const_iterator> crend() const { return rend(); }
752
753 iterator lower_bound(const Key &key)
754 {
755 auto cit = std::as_const(*this).lower_bound(key);
756 return { &c, cit.i };
757 }
758
759 template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
760 iterator lower_bound(const X &key)
761 {
762 auto cit = std::as_const(*this).lower_bound(key);
763 return { &c, cit.i };
764 }
765
766 const_iterator lower_bound(const Key &key) const
767 {
768 return fromKeysIterator(std::lower_bound(c.keys.begin(), c.keys.end(), key, key_comp()));
769 }
770
771 template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
772 const_iterator lower_bound(const X &key) const
773 {
774 return fromKeysIterator(std::lower_bound(c.keys.begin(), c.keys.end(), key, key_comp()));
775 }
776
777 iterator find(const Key &key)
778 {
779 return { &c, std::as_const(*this).find(key).i };
780 }
781
782 template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
783 iterator find(const X &key)
784 {
785 return { &c, std::as_const(*this).find(key).i };
786 }
787
788 const_iterator find(const Key &key) const
789 {
790 auto it = lower_bound(key);
791 if (it != end()) {
792 if (!key_compare::operator()(key, it.key()))
793 return it;
794 it = end();
795 }
796 return it;
797 }
798
799 template <class X, class Y = Compare, is_marked_transparent<Y> = nullptr>
800 const_iterator find(const X &key) const
801 {
802 auto it = lower_bound(key);
803 if (it != end()) {
804 if (!key_compare::operator()(key, it.key()))
805 return it;
806 it = end();
807 }
808 return it;
809 }
810
811 template <typename Predicate>
812 size_type remove_if(Predicate pred)
813 {
814 const auto indirect_call_to_pred = [pred = std::move(pred)](iterator it) {
815 using Pair = decltype(*it);
816 using K = decltype(it.key());
817 using V = decltype(it.value());
818 using P = Predicate;
819 if constexpr (std::is_invocable_v<P, K, V>) {
820 return pred(it.key(), it.value());
821 } else if constexpr (std::is_invocable_v<P, Pair> && !std::is_invocable_v<P, K>) {
822 return pred(*it);
823 } else if constexpr (std::is_invocable_v<P, K> && !std::is_invocable_v<P, Pair>) {
824 return pred(it.key());
825 } else {
826 static_assert(QtPrivate::type_dependent_false<Predicate>(),
827 "Don't know how to call the predicate.\n"
828 "Options:\n"
829 "- pred(*it)\n"
830 "- pred(it.key(), it.value())\n"
831 "- pred(it.key())");
832 }
833 };
834
835 auto first = begin();
836 const auto last = end();
837
838 // find_if prefix loop
839 while (first != last && !indirect_call_to_pred(first))
840 ++first;
841
842 if (first == last)
843 return 0; // nothing to do
844
845 // we know that we need to remove *first
846
847 auto kdest = toKeysIterator(first);
848 auto vdest = toValuesIterator(first);
849
850 ++first;
851
852 auto k = std::next(kdest);
853 auto v = std::next(vdest);
854
855 // Main Loop
856 // - first is used only for indirect_call_to_pred
857 // - operations are done on k, v
858 // Loop invariants:
859 // - first, k, v are pointing to the same element
860 // - [begin(), first[, [c.keys.begin(), k[, [c.values.begin(), v[: already processed
861 // - [first, end()[, [k, c.keys.end()[, [v, c.values.end()[: still to be processed
862 // - [c.keys.begin(), kdest[ and [c.values.begin(), vdest[ are keepers
863 // - [kdest, k[, [vdest, v[ are considered removed
864 // - kdest is not c.keys.end()
865 // - vdest is not v.values.end()
866 while (first != last) {
867 if (!indirect_call_to_pred(first)) {
868 // keep *first, aka {*k, *v}
869 *kdest = std::move(*k);
870 *vdest = std::move(*v);
871 ++kdest;
872 ++vdest;
873 }
874 ++k;
875 ++v;
876 ++first;
877 }
878
879 const size_type r = std::distance(kdest, c.keys.end());
880 c.keys.erase(kdest, c.keys.end());
881 c.values.erase(vdest, c.values.end());
882 return r;
883 }
884
885 key_compare key_comp() const noexcept
886 {
887 return static_cast<key_compare>(*this);
888 }
889
890 value_compare value_comp() const noexcept
891 {
892 return static_cast<value_compare>(*this);
893 }
894
895private:
896 bool do_remove(iterator it)
897 {
898 if (it != end()) {
899 erase(it);
900 return true;
901 }
902 return false;
903 }
904
905 T do_take(iterator it)
906 {
907 if (it == end())
908 return {};
909 return [&] {
910 T result = std::move(it.value());
911 erase(it);
912 return result;
913 }();
914 }
915
916 template <class InputIt, is_compatible_iterator<InputIt> = nullptr>
917 void initWithRange(InputIt first, InputIt last)
918 {
919 QtPrivate::reserveIfForwardIterator(this, first, last);
920 while (first != last) {
921 c.keys.push_back(first->first);
922 c.values.push_back(first->second);
923 ++first;
924 }
925 }
926
927 iterator fromKeysIterator(typename key_container_type::iterator kit)
928 {
929 return { &c, static_cast<size_type>(std::distance(c.keys.begin(), kit)) };
930 }
931
932 const_iterator fromKeysIterator(typename key_container_type::const_iterator kit) const
933 {
934 return { &c, static_cast<size_type>(std::distance(c.keys.begin(), kit)) };
935 }
936
937 typename key_container_type::iterator toKeysIterator(iterator it)
938 {
939 return c.keys.begin() + it.i;
940 }
941
942 typename mapped_container_type::iterator toValuesIterator(iterator it)
943 {
944 return c.values.begin() + it.i;
945 }
946
947 template <class InputIt>
948 void insertRange(InputIt first, InputIt last)
949 {
950 size_type i = c.keys.size();
951 c.keys.resize(i + std::distance(first, last));
952 c.values.resize(c.keys.size());
953 for (; first != last; ++first, ++i) {
954 c.keys[i] = first->first;
955 c.values[i] = first->second;
956 }
957 ensureOrderedUnique();
958 }
959
960 class IndexedKeyComparator
961 {
962 public:
963 IndexedKeyComparator(const QFlatMap *am)
964 : m(am)
965 {
966 }
967
968 bool operator()(size_type i, size_type k) const
969 {
970 return m->key_comp()(m->c.keys[i], m->c.keys[k]);
971 }
972
973 private:
974 const QFlatMap *m;
975 };
976
977 template <class InputIt>
978 void insertOrderedUniqueRange(InputIt first, InputIt last)
979 {
980 const size_type s = c.keys.size();
981 c.keys.resize(s + std::distance(first, last));
982 c.values.resize(c.keys.size());
983 for (size_type i = s; first != last; ++first, ++i) {
984 c.keys[i] = first->first;
985 c.values[i] = first->second;
986 }
987
988 std::vector<size_type> p(size_t(c.keys.size()));
989 std::iota(p.begin(), p.end(), 0);
990 std::inplace_merge(p.begin(), p.begin() + s, p.end(), IndexedKeyComparator(this));
991 applyPermutation(p);
992 makeUnique();
993 }
994
995 void ensureOrderedUnique()
996 {
997 std::vector<size_type> p(size_t(c.keys.size()));
998 std::iota(p.begin(), p.end(), 0);
999 std::stable_sort(p.begin(), p.end(), IndexedKeyComparator(this));
1000 applyPermutation(p);
1001 makeUnique();
1002 }
1003
1004 void applyPermutation(const std::vector<size_type> &p)
1005 {
1006 const size_type s = c.keys.size();
1007 std::vector<bool> done(s);
1008 for (size_type i = 0; i < s; ++i) {
1009 if (done[i])
1010 continue;
1011 done[i] = true;
1012 size_type j = i;
1013 size_type k = p[i];
1014 while (i != k) {
1015 qSwap(c.keys[j], c.keys[k]);
1016 qSwap(c.values[j], c.values[k]);
1017 done[k] = true;
1018 j = k;
1019 k = p[j];
1020 }
1021 }
1022 }
1023
1024 void makeUnique()
1025 {
1026 // std::unique, but over two ranges
1027 auto equivalent = [this](const auto &lhs, const auto &rhs) {
1028 return !key_compare::operator()(lhs, rhs) && !key_compare::operator()(rhs, lhs);
1029 };
1030 const auto kb = c.keys.begin();
1031 const auto ke = c.keys.end();
1032 auto k = std::adjacent_find(kb, ke, equivalent);
1033 if (k == ke)
1034 return;
1035
1036 // equivalent keys found, we need to do actual work:
1037 auto v = std::next(c.values.begin(), std::distance(kb, k));
1038
1039 auto kdest = k;
1040 auto vdest = v;
1041
1042 ++k;
1043 ++v;
1044
1045 // Loop Invariants:
1046 //
1047 // - [keys.begin(), kdest] and [values.begin(), vdest] are unique
1048 // - k is not keys.end(), v is not values.end()
1049 // - [next(k), keys.end()[ and [next(v), values.end()[ still need to be checked
1050 while ((++v, ++k) != ke) {
1051 if (!equivalent(*kdest, *k)) {
1052 *++kdest = std::move(*k);
1053 *++vdest = std::move(*v);
1054 }
1055 }
1056
1057 c.keys.erase(std::next(kdest), ke);
1058 c.values.erase(std::next(vdest), c.values.end());
1059 }
1060
1061 containers c;
1062};
1063
1064template <class Key, class T,
1065 qsizetype N = QVarLengthArrayDefaultPrealloc,
1066 class Compare = std::less<Key>>
1067using QVarLengthFlatMap = QFlatMap<Key, T, Compare, QVarLengthArray<Key, N>, QVarLengthArray<T, N>>;
1068
1069QT_END_NAMESPACE
1070
1071#endif // QFLATMAP_P_H
bool operator()(const value_type &lhs, const value_type &rhs) const noexcept(is_comparator_noexcept)
Definition qflatmap_p.h:68
std::pair< const Key, T > value_type
Definition qflatmap_p.h:64
QFlatMapValueCompare()=default
static constexpr bool is_comparator_noexcept
Definition qflatmap_p.h:65
QFlatMapValueCompare(const Compare &key_compare)
Definition qflatmap_p.h:59
bool operator>=(const const_iterator &other) const
Definition qflatmap_p.h:351
friend const_iterator operator+(size_type n, const const_iterator a)
Definition qflatmap_p.h:302
const_iterator(const containers *ac, size_type ai)
Definition qflatmap_p.h:239
const_iterator & operator-=(size_type n)
Definition qflatmap_p.h:313
const_iterator operator++(int)
Definition qflatmap_p.h:275
bool operator>(const const_iterator &other) const
Definition qflatmap_p.h:341
friend difference_type operator-(const const_iterator b, const const_iterator a)
Definition qflatmap_p.h:325
std::random_access_iterator_tag iterator_category
Definition qflatmap_p.h:235
reference operator*() const
Definition qflatmap_p.h:249
const_iterator & operator++()
Definition qflatmap_p.h:269
bool operator==(const const_iterator &o) const
Definition qflatmap_p.h:259
reference operator[](size_type n) const
Definition qflatmap_p.h:330
pointer operator->() const
Definition qflatmap_p.h:254
bool operator<(const const_iterator &other) const
Definition qflatmap_p.h:336
bool operator<=(const const_iterator &other) const
Definition qflatmap_p.h:346
bool operator!=(const const_iterator &o) const
Definition qflatmap_p.h:264
const_iterator & operator+=(size_type n)
Definition qflatmap_p.h:296
std::pair< const Key, const T > value_type
Definition qflatmap_p.h:232
friend const_iterator operator-(const const_iterator a, size_type n)
Definition qflatmap_p.h:319
const Key & key() const
Definition qflatmap_p.h:356
std::pair< const Key &, const T & > reference
Definition qflatmap_p.h:233
const T & value() const
Definition qflatmap_p.h:357
friend const_iterator operator+(const const_iterator a, size_type n)
Definition qflatmap_p.h:308
const_iterator & operator--()
Definition qflatmap_p.h:283
const_iterator operator--(int)
Definition qflatmap_p.h:289
iterator(containers *ac, size_type ai)
Definition qflatmap_p.h:107
bool operator>(const iterator &other) const
Definition qflatmap_p.h:204
reference operator[](size_type n) const
Definition qflatmap_p.h:193
iterator operator--(int)
Definition qflatmap_p.h:152
iterator & operator-=(size_type n)
Definition qflatmap_p.h:176
T & value() const
Definition qflatmap_p.h:220
const Key & key() const
Definition qflatmap_p.h:219
std::random_access_iterator_tag iterator_category
Definition qflatmap_p.h:103
friend iterator operator-(const iterator a, size_type n)
Definition qflatmap_p.h:182
friend iterator operator+(size_type n, const iterator a)
Definition qflatmap_p.h:165
pointer operator->() const
Definition qflatmap_p.h:117
bool operator==(const iterator &o) const
Definition qflatmap_p.h:122
iterator & operator--()
Definition qflatmap_p.h:146
reference operator*() const
Definition qflatmap_p.h:112
bool operator>=(const iterator &other) const
Definition qflatmap_p.h:214
iterator & operator++()
Definition qflatmap_p.h:132
bool operator<(const iterator &other) const
Definition qflatmap_p.h:199
std::pair< const Key &, T & > reference
Definition qflatmap_p.h:101
bool operator<=(const iterator &other) const
Definition qflatmap_p.h:209
bool operator!=(const iterator &o) const
Definition qflatmap_p.h:127
iterator operator++(int)
Definition qflatmap_p.h:138
friend iterator operator+(const iterator a, size_type n)
Definition qflatmap_p.h:171
std::pair< const Key, T > value_type
Definition qflatmap_p.h:100
iterator & operator+=(size_type n)
Definition qflatmap_p.h:159
friend difference_type operator-(const iterator b, const iterator a)
Definition qflatmap_p.h:188
bool isEmpty() const noexcept
Definition qflatmap_p.h:540
bool empty() const noexcept
Definition qflatmap_p.h:541
QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys, const mapped_container_type &values, const Compare &compare)
Definition qflatmap_p.h:500
QFlatMap(Qt::OrderedUniqueRange_t, InputIt first, InputIt last)
Definition qflatmap_p.h:449
std::reverse_iterator< const_iterator > crend() const
Definition qflatmap_p.h:751
containers extract() &&
Definition qflatmap_p.h:542
QFlatMap(const key_container_type &keys, mapped_container_type &&values, const Compare &compare)
Definition qflatmap_p.h:473
size_type count() const noexcept
Definition qflatmap_p.h:537
QFlatMap(key_container_type &&keys, mapped_container_type &&values)
Definition qflatmap_p.h:401
std::pair< iterator, bool > insert_or_assign(const Key &key, M &&obj)
Definition qflatmap_p.h:687
T value(const Key &key) const
Definition qflatmap_p.h:610
const_iterator lower_bound(const X &key) const
Definition qflatmap_p.h:772
const_iterator begin() const
Definition qflatmap_p.h:731
Key key_type
Definition qflatmap_p.h:81
T mapped_type
Definition qflatmap_p.h:82
iterator begin()
Definition qflatmap_p.h:730
const_iterator lower_bound(const Key &key) const
Definition qflatmap_p.h:766
std::reverse_iterator< const_iterator > rbegin() const
Definition qflatmap_p.h:739
void insert(Qt::OrderedUniqueRange_t, const value_type *first, const value_type *last)
Definition qflatmap_p.h:725
QFlatMapValueCompare< Key, T, Compare > value_compare
Definition qflatmap_p.h:83
QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys, const mapped_container_type &values, const Compare &compare)
Definition qflatmap_p.h:506
QFlatMap(const Compare &compare)
Definition qflatmap_p.h:454
std::pair< iterator, bool > insert(Key &&key, T &&value)
Definition qflatmap_p.h:657
std::reverse_iterator< const_iterator > crbegin() const
Definition qflatmap_p.h:743
T & operator[](const Key &key)
Definition qflatmap_p.h:627
key_compare key_comp() const noexcept
Definition qflatmap_p.h:885
iterator find(const X &key)
Definition qflatmap_p.h:783
bool contains(const X &key) const
Definition qflatmap_p.h:592
Compare key_compare
Definition qflatmap_p.h:88
std::pair< iterator, bool > insert(const Key &key, T &&value)
Definition qflatmap_p.h:652
iterator end()
Definition qflatmap_p.h:734
bool contains(const Key &key) const
Definition qflatmap_p.h:586
const_iterator find(const Key &key) const
Definition qflatmap_p.h:788
T value(const X &key) const
Definition qflatmap_p.h:619
std::reverse_iterator< iterator > rbegin()
Definition qflatmap_p.h:738
void insert(Qt::OrderedUniqueRange_t, InputIt first, InputIt last)
Definition qflatmap_p.h:718
iterator erase(iterator it)
Definition qflatmap_p.h:569
const_iterator cbegin() const
Definition qflatmap_p.h:732
iterator lower_bound(const Key &key)
Definition qflatmap_p.h:753
T & operator[](Key &&key)
Definition qflatmap_p.h:632
const key_container_type & keys() const noexcept
Definition qflatmap_p.h:543
typename key_container_type::size_type size_type
Definition qflatmap_p.h:87
QFlatMap(key_container_type &&keys, const mapped_container_type &values)
Definition qflatmap_p.h:389
T value(const X &key, const T &defaultValue) const
Definition qflatmap_p.h:604
size_type remove_if(Predicate pred)
Definition qflatmap_p.h:812
QFlatMap(key_container_type &&keys, const mapped_container_type &values, const Compare &compare)
Definition qflatmap_p.h:466
QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys, mapped_container_type &&values)
Definition qflatmap_p.h:437
const_iterator constBegin() const
Definition qflatmap_p.h:733
iterator find(const Key &key)
Definition qflatmap_p.h:777
QFlatMap(Qt::OrderedUniqueRange_t, std::initializer_list< value_type > lst, const Compare &compare)
Definition qflatmap_p.h:524
bool remove(const Key &key)
Definition qflatmap_p.h:558
const_iterator cend() const
Definition qflatmap_p.h:736
QFlatMap()=default
QFlatMap(key_container_type &&keys, mapped_container_type &&values, const Compare &compare)
Definition qflatmap_p.h:480
const_iterator constEnd() const
Definition qflatmap_p.h:737
QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys, mapped_container_type &&values, const Compare &compare)
Definition qflatmap_p.h:512
void insert(const value_type *first, const value_type *last)
Definition qflatmap_p.h:712
typename value_compare::value_type value_type
Definition qflatmap_p.h:84
QFlatMap(Qt::OrderedUniqueRange_t, std::initializer_list< value_type > lst)
Definition qflatmap_p.h:443
QFlatMap(InputIt first, InputIt last)
Definition qflatmap_p.h:413
const mapped_container_type & values() const noexcept
Definition qflatmap_p.h:544
const_iterator find(const X &key) const
Definition qflatmap_p.h:800
void reserve(size_type s)
Definition qflatmap_p.h:546
T take(const Key &key)
Definition qflatmap_p.h:575
QFlatMap(const key_container_type &keys, mapped_container_type &&values)
Definition qflatmap_p.h:395
QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys, mapped_container_type &&values)
Definition qflatmap_p.h:431
iterator lower_bound(const X &key)
Definition qflatmap_p.h:760
KeyContainer key_container_type
Definition qflatmap_p.h:85
std::pair< iterator, bool > insert(const Key &key, const T &value)
Definition qflatmap_p.h:642
QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys, const mapped_container_type &values)
Definition qflatmap_p.h:425
MappedContainer mapped_container_type
Definition qflatmap_p.h:86
QFlatMap(InputIt first, InputIt last, const Compare &compare)
Definition qflatmap_p.h:493
T value(const Key &key, const T &defaultValue) const
Definition qflatmap_p.h:597
bool remove(const X &key)
Definition qflatmap_p.h:564
std::reverse_iterator< iterator > rend()
Definition qflatmap_p.h:744
QFlatMap(const key_container_type &keys, const mapped_container_type &values)
Definition qflatmap_p.h:383
void clear()
Definition qflatmap_p.h:552
std::pair< iterator, bool > try_emplace(Key &&key, Args &&...args)
Definition qflatmap_p.h:675
const_iterator end() const
Definition qflatmap_p.h:735
void insert(InputIt first, InputIt last)
Definition qflatmap_p.h:705
std::pair< iterator, bool > try_emplace(const Key &key, Args &&...args)
Definition qflatmap_p.h:663
QFlatMap(const key_container_type &keys, const mapped_container_type &values, const Compare &compare)
Definition qflatmap_p.h:459
value_compare value_comp() const noexcept
Definition qflatmap_p.h:890
T take(const X &key)
Definition qflatmap_p.h:581
std::reverse_iterator< const_iterator > rend() const
Definition qflatmap_p.h:747
size_type size() const noexcept
Definition qflatmap_p.h:538
size_type capacity() const noexcept
Definition qflatmap_p.h:539
T operator[](const Key &key) const
Definition qflatmap_p.h:637
std::pair< iterator, bool > insert_or_assign(Key &&key, M &&obj)
Definition qflatmap_p.h:696
QFlatMap(std::initializer_list< value_type > lst, const Compare &compare)
Definition qflatmap_p.h:487
QFlatMap(Qt::OrderedUniqueRange_t, const key_container_type &keys, const mapped_container_type &values)
Definition qflatmap_p.h:419
QFlatMap(Qt::OrderedUniqueRange_t, key_container_type &&keys, mapped_container_type &&values, const Compare &compare)
Definition qflatmap_p.h:518
QFlatMap(std::initializer_list< value_type > lst)
Definition qflatmap_p.h:407
QFlatMap(Qt::OrderedUniqueRange_t, InputIt first, InputIt last, const Compare &compare)
Definition qflatmap_p.h:531
std::pair< iterator, bool > insert(Key &&key, const T &value)
Definition qflatmap_p.h:647
Definition qlist.h:81
Definition qcompare.h:110
QT_DEFINE_TAG(OrderedUniqueRange)
mapped_container_type values
Definition qflatmap_p.h:93
key_container_type keys
Definition qflatmap_p.h:92