Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qmap.h
Go to the documentation of this file.
1// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
2// Copyright (C) 2021 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#ifndef QMAP_H
6#define QMAP_H
7
8#include <QtCore/qhashfunctions.h>
9#include <QtCore/qiterator.h>
10#include <QtCore/qlist.h>
11#include <QtCore/qrefcount.h>
12#include <QtCore/qpair.h>
13#include <QtCore/qshareddata.h>
14#include <QtCore/qshareddata_impl.h>
15
16#include <functional>
17#include <initializer_list>
18#include <map>
19#include <algorithm>
20
22
23// common code shared between QMap and QMultimap
24template <typename AMap>
25class QMapData : public QSharedData
26{
27public:
28 using Map = AMap;
29 using Key = typename Map::key_type;
30 using T = typename Map::mapped_type;
31 using value_type = typename Map::value_type;
32 using size_type = typename Map::size_type;
33 using iterator = typename Map::iterator;
34 using const_iterator = typename Map::const_iterator;
35
36 static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
37 static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
38
40
41 QMapData() = default;
42 explicit QMapData(const Map &other)
43 : m(other)
44 {}
45
46 explicit QMapData(Map &&other)
47 : m(std::move(other))
48 {}
49
50 // used in remove(); copies from source all the values not matching key.
51 // returns how many were NOT copied (removed).
53 {
54 Q_ASSERT(m.empty());
55
56 size_type result = 0;
57 const auto &keyCompare = source.key_comp();
58 const auto filter = [&result, &key, &keyCompare](const auto &v)
59 {
60 if (!keyCompare(key, v.first) && !keyCompare(v.first, key)) {
61 // keys are equivalent (neither a<b nor b<a) => found it
62 ++result;
63 return true;
64 }
65 return false;
66 };
67
68 std::remove_copy_if(source.cbegin(), source.cend(),
69 std::inserter(m, m.end()),
70 filter);
71 return result;
72 }
73
74 // used in key(T), count(Key, T), find(key, T), etc; returns a
75 // comparator object suitable for algorithms with std::(multi)map
76 // iterators.
77 static auto valueIsEqualTo(const T &value)
78 {
79 return [&value](const auto &v) { return v.second == value; };
80 }
81
82 Key key(const T &value, const Key &defaultKey) const
83 {
84 auto i = std::find_if(m.cbegin(),
85 m.cend(),
87 if (i != m.cend())
88 return i->first;
89
90 return defaultKey;
91 }
92
93 QList<Key> keys() const
94 {
95 QList<Key> result;
96 result.reserve(m.size());
97
98 const auto extractKey = [](const auto &v) { return v.first; };
99
100 std::transform(m.cbegin(),
101 m.cend(),
102 std::back_inserter(result),
103 extractKey);
104 return result;
105 }
106
107 QList<Key> keys(const T &value) const
108 {
109 QList<Key> result;
110 result.reserve(m.size());
111 // no std::transform_if...
112 for (const auto &v : m) {
113 if (v.second == value)
114 result.append(v.first);
115 }
116 result.shrink_to_fit();
117 return result;
118 }
119
120 QList<T> values() const
121 {
122 QList<T> result;
123 result.reserve(m.size());
124
125 const auto extractValue = [](const auto &v) { return v.second; };
126
127 std::transform(m.cbegin(),
128 m.cend(),
129 std::back_inserter(result),
130 extractValue);
131 return result;
132 }
133
134 size_type count(const Key &key) const
135 {
136 return m.count(key);
137 }
138
139 // Used in erase. Allocates a new QMapData and copies, from this->m,
140 // the elements not in the [first, last) range. The return contains
141 // the new QMapData and an iterator in its map pointing at the first
142 // element after the erase.
147
149 {
151 result.data = new QMapData;
152 result.it = result.data->m.end();
153 const auto newDataEnd = result.it;
154
155 auto i = m.begin();
156 const auto e = m.end();
157
158 // copy over all the elements before first
159 while (i != first) {
160 result.it = result.data->m.insert(newDataEnd, *i);
161 ++i;
162 }
163
164 // skip until last
165 while (i != last)
166 ++i;
167
168 // copy from last to the end
169 while (i != e) {
170 result.data->m.insert(newDataEnd, *i);
171 ++i;
172 }
173
174 if (result.it != newDataEnd)
175 ++result.it;
176
177 return result;
178 }
179};
180
181//
182// QMap
183//
184
185template <class Key, class T>
186class QMap
187{
188 using Map = std::map<Key, T>;
189 using MapData = QMapData<Map>;
191
192 friend class QMultiMap<Key, T>;
193
194public:
195 using key_type = Key;
196 using mapped_type = T;
199
200 QMap() = default;
201
202 // implicitly generated special member functions are OK!
203
204 void swap(QMap<Key, T> &other) noexcept
205 {
206 d.swap(other.d);
207 }
208
209 QMap(std::initializer_list<std::pair<Key, T>> list)
210 {
211 for (auto &p : list)
212 insert(p.first, p.second);
213 }
214
215 explicit QMap(const std::map<Key, T> &other)
216 : d(other.empty() ? nullptr : new MapData(other))
217 {
218 }
219
220 explicit QMap(std::map<Key, T> &&other)
221 : d(other.empty() ? nullptr : new MapData(std::move(other)))
222 {
223 }
224
225 std::map<Key, T> toStdMap() const &
226 {
227 if (d)
228 return d->m;
229 return {};
230 }
231
232 std::map<Key, T> toStdMap() &&
233 {
234 if (d) {
235 if (d.isShared())
236 return d->m;
237 else
238 return std::move(d->m);
239 }
240
241 return {};
242 }
243
244#ifndef Q_QDOC
245 template <typename AKey = Key, typename AT = T> friend
247 {
248 if (lhs.d == rhs.d)
249 return true;
250 if (!lhs.d)
251 return rhs == lhs;
252 Q_ASSERT(lhs.d);
253 return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
254 }
255
256 template <typename AKey = Key, typename AT = T> friend
258 {
259 return !(lhs == rhs);
260 }
261 // TODO: add the other comparison operators; std::map has them.
262#else
263 friend bool operator==(const QMap &lhs, const QMap &rhs);
264 friend bool operator!=(const QMap &lhs, const QMap &rhs);
265#endif // Q_QDOC
266
267 size_type size() const { return d ? size_type(d->m.size()) : size_type(0); }
268
269 bool isEmpty() const { return d ? d->m.empty() : true; }
270
271 void detach()
272 {
273 if (d)
274 d.detach();
275 else
276 d.reset(new MapData);
277 }
278
279 bool isDetached() const noexcept
280 {
281 return d ? !d.isShared() : false; // false makes little sense, but that's shared_null's behavior...
282 }
283
284 bool isSharedWith(const QMap<Key, T> &other) const noexcept
285 {
286 return d == other.d; // also this makes little sense?
287 }
288
289 void clear()
290 {
291 if (!d)
292 return;
293
294 if (!d.isShared())
295 d->m.clear();
296 else
297 d.reset();
298 }
299
301 {
302 if (!d)
303 return 0;
304
305 if (!d.isShared())
306 return size_type(d->m.erase(key));
307
308 MapData *newData = new MapData;
309 size_type result = newData->copyIfNotEquivalentTo(d->m, key);
310
311 d.reset(newData);
312
313 return result;
314 }
315
316 template <typename Predicate>
317 size_type removeIf(Predicate pred)
318 {
319 return QtPrivate::associative_erase_if(*this, pred);
320 }
321
322 T take(const Key &key)
323 {
324 if (!d)
325 return T();
326
327 const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
328 // TODO: improve. There is no need of copying all the
329 // elements (the one to be removed can be skipped).
330 detach();
331
332 auto i = d->m.find(key);
333 if (i != d->m.end()) {
334 T result(std::move(i->second));
335 d->m.erase(i);
336 return result;
337 }
338 return T();
339 }
340
341 bool contains(const Key &key) const
342 {
343 if (!d)
344 return false;
345 auto i = d->m.find(key);
346 return i != d->m.end();
347 }
348
349 Key key(const T &value, const Key &defaultKey = Key()) const
350 {
351 if (!d)
352 return defaultKey;
353
354 return d->key(value, defaultKey);
355 }
356
357 T value(const Key &key, const T &defaultValue = T()) const
358 {
359 if (!d)
360 return defaultValue;
361 const auto i = d->m.find(key);
362 if (i != d->m.cend())
363 return i->second;
364 return defaultValue;
365 }
366
367 T &operator[](const Key &key)
368 {
369 const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
370 detach();
371 auto i = d->m.find(key);
372 if (i == d->m.end())
373 i = d->m.insert({key, T()}).first;
374 return i->second;
375 }
376
377 // CHANGE: return T, not const T!
378 T operator[](const Key &key) const
379 {
380 return value(key);
381 }
382
383 QList<Key> keys() const
384 {
385 if (!d)
386 return {};
387 return d->keys();
388 }
389
390 QList<Key> keys(const T &value) const
391 {
392 if (!d)
393 return {};
394 return d->keys(value);
395 }
396
397 QList<T> values() const
398 {
399 if (!d)
400 return {};
401 return d->values();
402 }
403
404 size_type count(const Key &key) const
405 {
406 if (!d)
407 return 0;
408 return d->count(key);
409 }
410
412 {
413 return size();
414 }
415
416 inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
417 inline const Key &lastKey() const { Q_ASSERT(!isEmpty()); return (--constEnd()).key(); }
418
419 inline T &first() { Q_ASSERT(!isEmpty()); return *begin(); }
420 inline const T &first() const { Q_ASSERT(!isEmpty()); return *constBegin(); }
421 inline T &last() { Q_ASSERT(!isEmpty()); return *(--end()); }
422 inline const T &last() const { Q_ASSERT(!isEmpty()); return *(--constEnd()); }
423
424 class const_iterator;
425
427 {
428 friend class QMap<Key, T>;
429 friend class const_iterator;
430
431 typename Map::iterator i;
432 explicit iterator(typename Map::iterator it) : i(it) {}
433 public:
434 using iterator_category = std::bidirectional_iterator_tag;
436 using value_type = T;
437 using pointer = T *;
438 using reference = T &;
439
440 iterator() = default;
441
442 const Key &key() const { return i->first; }
443 T &value() const { return i->second; }
444 T &operator*() const { return i->second; }
445 T *operator->() const { return &i->second; }
446 friend bool operator==(const iterator &lhs, const iterator &rhs) { return lhs.i == rhs.i; }
447 friend bool operator!=(const iterator &lhs, const iterator &rhs) { return lhs.i != rhs.i; }
448
450 {
451 ++i;
452 return *this;
453 }
455 {
456 iterator r = *this;
457 ++i;
458 return r;
459 }
461 {
462 --i;
463 return *this;
464 }
466 {
467 iterator r = *this;
468 --i;
469 return r;
470 }
471
472#if QT_DEPRECATED_SINCE(6, 0)
473 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
475 friend iterator operator+(iterator it, difference_type j) { return std::next(it, j); }
476
477 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
479 friend iterator operator-(iterator it, difference_type j) { return std::prev(it, j); }
480
481 QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMap iterators are not random access")
482 iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
483
484 QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMap iterators are not random access")
485 iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
486
487 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
489 friend iterator operator+(difference_type j, iterator it) { return std::next(it, j); }
490
491 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
493 friend iterator operator-(difference_type j, iterator it) { return std::prev(it, j); }
494#endif
495 };
496
498 {
499 friend class QMap<Key, T>;
500 typename Map::const_iterator i;
501 explicit const_iterator(typename Map::const_iterator it) : i(it) {}
502
503 public:
504 using iterator_category = std::bidirectional_iterator_tag;
506 using value_type = T;
507 using pointer = const T *;
508 using reference = const T &;
509
510 const_iterator() = default;
512
513 const Key &key() const { return i->first; }
514 const T &value() const { return i->second; }
515 const T &operator*() const { return i->second; }
516 const T *operator->() const { return &i->second; }
517 friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i == rhs.i; }
518 friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i != rhs.i; }
519
521 {
522 ++i;
523 return *this;
524 }
526 {
527 const_iterator r = *this;
528 ++i;
529 return r;
530 }
532 {
533 --i;
534 return *this;
535 }
537 {
538 const_iterator r = *this;
539 --i;
540 return r;
541 }
542
543#if QT_DEPRECATED_SINCE(6, 0)
544 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
546 friend const_iterator operator+(const_iterator it, difference_type j) { return std::next(it, j); }
547
548 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
550 friend const_iterator operator-(const_iterator it, difference_type j) { return std::prev(it, j); }
551
552 QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMap iterators are not random access")
553 const_iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
554
555 QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMap iterators are not random access")
556 const_iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
557
558 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
560 friend const_iterator operator+(difference_type j, const_iterator it) { return std::next(it, j); }
561
562 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
564 friend const_iterator operator-(difference_type j, const_iterator it) { return std::prev(it, j); }
565#endif
566 };
567
569 {
571
572 public:
576 typedef const Key *pointer;
577 typedef const Key &reference;
578
579 key_iterator() = default;
580 explicit key_iterator(const_iterator o) : i(o) { }
581
582 const Key &operator*() const { return i.key(); }
583 const Key *operator->() const { return &i.key(); }
584 bool operator==(key_iterator o) const { return i == o.i; }
585 bool operator!=(key_iterator o) const { return i != o.i; }
586
587 inline key_iterator &operator++() { ++i; return *this; }
588 inline key_iterator operator++(int) { return key_iterator(i++);}
589 inline key_iterator &operator--() { --i; return *this; }
590 inline key_iterator operator--(int) { return key_iterator(i--); }
591 const_iterator base() const { return i; }
592 };
593
594 typedef QKeyValueIterator<const Key&, const T&, const_iterator> const_key_value_iterator;
595 typedef QKeyValueIterator<const Key&, T&, iterator> key_value_iterator;
596
597 // STL style
598 iterator begin() { detach(); return iterator(d->m.begin()); }
599 const_iterator begin() const { if (!d) return const_iterator(); return const_iterator(d->m.cbegin()); }
600 const_iterator constBegin() const { return begin(); }
601 const_iterator cbegin() const { return begin(); }
602 iterator end() { detach(); return iterator(d->m.end()); }
603 const_iterator end() const { if (!d) return const_iterator(); return const_iterator(d->m.end()); }
604 const_iterator constEnd() const { return end(); }
605 const_iterator cend() const { return end(); }
607 key_iterator keyEnd() const { return key_iterator(end()); }
614 auto asKeyValueRange() & { return QtPrivate::QKeyValueRange(*this); }
615 auto asKeyValueRange() const & { return QtPrivate::QKeyValueRange(*this); }
616 auto asKeyValueRange() && { return QtPrivate::QKeyValueRange(std::move(*this)); }
617 auto asKeyValueRange() const && { return QtPrivate::QKeyValueRange(std::move(*this)); }
618
620 {
621 return erase(it, std::next(it));
622 }
623
625 {
626 if (!d)
627 return iterator();
628
629 if (!d.isShared())
630 return iterator(d->m.erase(afirst.i, alast.i));
631
632 auto result = d->erase(afirst.i, alast.i);
633 d.reset(result.data);
634 return iterator(result.it);
635 }
636
637 // more Qt
640
642 {
643 const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
644 detach();
645 return iterator(d->m.find(key));
646 }
647
649 {
650 if (!d)
651 return const_iterator();
652 return const_iterator(d->m.find(key));
653 }
654
656 {
657 return find(key);
658 }
659
661 {
662 const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
663 detach();
664 return iterator(d->m.lower_bound(key));
665 }
666
668 {
669 if (!d)
670 return const_iterator();
671 return const_iterator(d->m.lower_bound(key));
672 }
673
675 {
676 const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
677 detach();
678 return iterator(d->m.upper_bound(key));
679 }
680
682 {
683 if (!d)
684 return const_iterator();
685 return const_iterator(d->m.upper_bound(key));
686 }
687
688 iterator insert(const Key &key, const T &value)
689 {
690 const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
691 // TODO: improve. In case of assignment, why copying first?
692 detach();
693 return iterator(d->m.insert_or_assign(key, value).first);
694 }
695
697 {
698 // TODO: improve. In case of assignment, why copying first?
699 typename Map::const_iterator dpos;
700 const auto copy = d.isShared() ? *this : QMap(); // keep `key`/`value` alive across the detach
701 if (!d || d.isShared()) {
702 auto posDistance = d ? std::distance(d->m.cbegin(), pos.i) : 0;
703 detach();
704 dpos = std::next(d->m.cbegin(), posDistance);
705 } else {
706 dpos = pos.i;
707 }
708 return iterator(d->m.insert_or_assign(dpos, key, value));
709 }
710
711 void insert(const QMap<Key, T> &map)
712 {
713 // TODO: improve. In case of assignment, why copying first?
714 if (map.isEmpty())
715 return;
716
717 detach();
718
719#ifdef __cpp_lib_node_extract
720 auto copy = map.d->m;
721 copy.merge(std::move(d->m));
722 d->m = std::move(copy);
723#else
724 // this is a std::copy, but we can't use std::inserter (need insert_or_assign...).
725 // copy in reverse order, trying to make effective use of insertionHint.
726 auto insertionHint = d->m.end();
727 auto mapIt = map.d->m.crbegin();
728 auto end = map.d->m.crend();
729 for (; mapIt != end; ++mapIt)
730 insertionHint = d->m.insert_or_assign(insertionHint, mapIt->first, mapIt->second);
731#endif
732 }
733
734 void insert(QMap<Key, T> &&map)
735 {
736 if (!map.d || map.d->m.empty())
737 return;
738
739 if (map.d.isShared()) {
740 // fall back to a regular copy
741 insert(map);
742 return;
743 }
744
745 detach();
746
747#ifdef __cpp_lib_node_extract
748 map.d->m.merge(std::move(d->m));
749 *this = std::move(map);
750#else
751 // same as above
752 auto insertionHint = d->m.end();
753 auto mapIt = map.d->m.crbegin();
754 auto end = map.d->m.crend();
755 for (; mapIt != end; ++mapIt)
756 insertionHint = d->m.insert_or_assign(insertionHint, std::move(mapIt->first), std::move(mapIt->second));
757#endif
758 }
759
760 // STL compatibility
761 inline bool empty() const
762 {
763 return isEmpty();
764 }
765
766 std::pair<iterator, iterator> equal_range(const Key &akey)
767 {
768 const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
769 detach();
770 auto result = d->m.equal_range(akey);
771 return {iterator(result.first), iterator(result.second)};
772 }
773
774 std::pair<const_iterator, const_iterator> equal_range(const Key &akey) const
775 {
776 if (!d)
777 return {};
778 auto result = d->m.equal_range(akey);
779 return {const_iterator(result.first), const_iterator(result.second)};
780 }
781
782private:
783#ifdef Q_QDOC
784 friend size_t qHash(const QMap &key, size_t seed = 0);
785#else
786# if defined(Q_CC_GHS) || defined (Q_CC_MSVC)
787 // GHS and MSVC tries to intantiate qHash() for the noexcept running into a
788 // non-SFINAE'ed hard error... Create an artificial SFINAE context as a
789 // work-around:
790 template <typename M, std::enable_if_t<std::is_same_v<M, QMap>, bool> = true>
792# else
793 using M = QMap;
794 friend size_t
795# endif
796 qHash(const M &key, size_t seed = 0)
797 noexcept(QHashPrivate::noexceptPairHash<typename M::key_type, typename M::mapped_type>())
798 {
799 if (!key.d)
800 return seed;
801 // don't use qHashRange to avoid its compile-time overhead:
802 return std::accumulate(key.d->m.begin(), key.d->m.end(), seed,
804 }
805#endif // !Q_QDOC
806};
807
810
811template <typename Key, typename T, typename Predicate>
812qsizetype erase_if(QMap<Key, T> &map, Predicate pred)
813{
815}
816
817
818//
819// QMultiMap
820//
821
822template <class Key, class T>
824{
825 using Map = std::multimap<Key, T>;
826 using MapData = QMapData<Map>;
828
829public:
830 using key_type = Key;
831 using mapped_type = T;
834
835 QMultiMap() = default;
836
837 // implicitly generated special member functions are OK!
838
839 QMultiMap(std::initializer_list<std::pair<Key,T>> list)
840 {
841 for (auto &p : list)
842 insert(p.first, p.second);
843 }
844
845 void swap(QMultiMap<Key, T> &other) noexcept
846 {
847 d.swap(other.d);
848 }
849
850 explicit QMultiMap(const QMap<Key, T> &other)
851 : d(other.isEmpty() ? nullptr : new MapData)
852 {
853 if (d) {
854 Q_ASSERT(other.d);
855 d->m.insert(other.d->m.begin(),
856 other.d->m.end());
857 }
858 }
859
860 explicit QMultiMap(QMap<Key, T> &&other)
861 : d(other.isEmpty() ? nullptr : new MapData)
862 {
863 if (d) {
864 Q_ASSERT(other.d);
865 if (other.d.isShared()) {
866 d->m.insert(other.d->m.begin(),
867 other.d->m.end());
868 } else {
869#ifdef __cpp_lib_node_extract
870 d->m.merge(std::move(other.d->m));
871#else
872 d->m.insert(std::make_move_iterator(other.d->m.begin()),
873 std::make_move_iterator(other.d->m.end()));
874#endif
875 }
876 }
877 }
878
879 explicit QMultiMap(const std::multimap<Key, T> &other)
880 : d(other.empty() ? nullptr : new MapData(other))
881 {
882 }
883
884 explicit QMultiMap(std::multimap<Key, T> &&other)
885 : d(other.empty() ? nullptr : new MapData(std::move(other)))
886 {
887 }
888
889 // CHANGE: return type
890 Q_DECL_DEPRECATED_X("Use toStdMultiMap instead")
892 {
893 return toStdMultiMap();
894 }
895
896 std::multimap<Key, T> toStdMultiMap() const &
897 {
898 if (d)
899 return d->m;
900 return {};
901 }
902
903 std::multimap<Key, T> toStdMultiMap() &&
904 {
905 if (d) {
906 if (d.isShared())
907 return d->m;
908 else
909 return std::move(d->m);
910 }
911
912 return {};
913 }
914
915#ifndef Q_QDOC
916 template <typename AKey = Key, typename AT = T> friend
918 {
919 if (lhs.d == rhs.d)
920 return true;
921 if (!lhs.d)
922 return rhs == lhs;
923 Q_ASSERT(lhs.d);
924 return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
925 }
926
927 template <typename AKey = Key, typename AT = T> friend
929 {
930 return !(lhs == rhs);
931 }
932 // TODO: add the other comparison operators; std::multimap has them.
933#else
934 friend bool operator==(const QMultiMap &lhs, const QMultiMap &rhs);
935 friend bool operator!=(const QMultiMap &lhs, const QMultiMap &rhs);
936#endif // Q_QDOC
937
938 size_type size() const { return d ? size_type(d->m.size()) : size_type(0); }
939
940 bool isEmpty() const { return d ? d->m.empty() : true; }
941
942 void detach()
943 {
944 if (d)
945 d.detach();
946 else
947 d.reset(new MapData);
948 }
949
950 bool isDetached() const noexcept
951 {
952 return d ? !d.isShared() : false; // false makes little sense, but that's shared_null's behavior...
953 }
954
955 bool isSharedWith(const QMultiMap<Key, T> &other) const noexcept
956 {
957 return d == other.d; // also this makes little sense?
958 }
959
960 void clear()
961 {
962 if (!d)
963 return;
964
965 if (!d.isShared())
966 d->m.clear();
967 else
968 d.reset();
969 }
970
972 {
973 if (!d)
974 return 0;
975
976 if (!d.isShared())
977 return size_type(d->m.erase(key));
978
979 MapData *newData = new MapData;
980 size_type result = newData->copyIfNotEquivalentTo(d->m, key);
981
982 d.reset(newData);
983
984 return result;
985 }
986
987 size_type remove(const Key &key, const T &value)
988 {
989 if (!d)
990 return 0;
991
992 // key and value may belong to this map. As such, we need to copy
993 // them to ensure they stay valid throughout the iteration below
994 // (which may destroy them)
995 const Key keyCopy = key;
996 const T valueCopy = value;
997
998 // TODO: improve. Copy over only the elements not to be removed.
999 detach();
1000
1001 size_type result = 0;
1002 const auto &keyCompare = d->m.key_comp();
1003
1004 auto i = d->m.find(keyCopy);
1005 const auto e = d->m.end();
1006
1007 while (i != e && !keyCompare(keyCopy, i->first)) {
1008 if (i->second == valueCopy) {
1009 i = d->m.erase(i);
1010 ++result;
1011 } else {
1012 ++i;
1013 }
1014 }
1015
1016 return result;
1017 }
1018
1019 template <typename Predicate>
1020 size_type removeIf(Predicate pred)
1021 {
1022 return QtPrivate::associative_erase_if(*this, pred);
1023 }
1024
1025 T take(const Key &key)
1026 {
1027 if (!d)
1028 return T();
1029
1030 const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
1031
1032 // TODO: improve. There is no need of copying all the
1033 // elements (the one to be removed can be skipped).
1034 detach();
1035
1036 auto i = d->m.find(key);
1037 if (i != d->m.end()) {
1038 T result(std::move(i->second));
1039 d->m.erase(i);
1040 return result;
1041 }
1042 return T();
1043 }
1044
1045 bool contains(const Key &key) const
1046 {
1047 if (!d)
1048 return false;
1049 auto i = d->m.find(key);
1050 return i != d->m.end();
1051 }
1052
1053 bool contains(const Key &key, const T &value) const
1054 {
1055 return find(key, value) != end();
1056 }
1057
1058 Key key(const T &value, const Key &defaultKey = Key()) const
1059 {
1060 if (!d)
1061 return defaultKey;
1062
1063 return d->key(value, defaultKey);
1064 }
1065
1066 T value(const Key &key, const T &defaultValue = T()) const
1067 {
1068 if (!d)
1069 return defaultValue;
1070 const auto i = d->m.find(key);
1071 if (i != d->m.cend())
1072 return i->second;
1073 return defaultValue;
1074 }
1075
1076 QList<Key> keys() const
1077 {
1078 if (!d)
1079 return {};
1080 return d->keys();
1081 }
1082
1083 QList<Key> keys(const T &value) const
1084 {
1085 if (!d)
1086 return {};
1087 return d->keys(value);
1088 }
1089
1090 QList<Key> uniqueKeys() const
1091 {
1092 QList<Key> result;
1093 if (!d)
1094 return result;
1095
1096 result.reserve(size());
1097
1098 std::unique_copy(keyBegin(), keyEnd(),
1099 std::back_inserter(result));
1100
1101 result.shrink_to_fit();
1102 return result;
1103 }
1104
1105 QList<T> values() const
1106 {
1107 if (!d)
1108 return {};
1109 return d->values();
1110 }
1111
1112 QList<T> values(const Key &key) const
1113 {
1114 QList<T> result;
1115 const auto range = equal_range(key);
1116 result.reserve(std::distance(range.first, range.second));
1117 std::copy(range.first, range.second, std::back_inserter(result));
1118 return result;
1119 }
1120
1121 size_type count(const Key &key) const
1122 {
1123 if (!d)
1124 return 0;
1125 return d->count(key);
1126 }
1127
1128 size_type count(const Key &key, const T &value) const
1129 {
1130 if (!d)
1131 return 0;
1132
1133 // TODO: improve; no need of scanning the equal_range twice.
1134 auto range = d->m.equal_range(key);
1135
1136 return size_type(std::count_if(range.first,
1137 range.second,
1138 MapData::valueIsEqualTo(value)));
1139 }
1140
1141 inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
1142 inline const Key &lastKey() const { Q_ASSERT(!isEmpty()); return std::next(constEnd(), -1).key(); }
1143
1144 inline T &first() { Q_ASSERT(!isEmpty()); return *begin(); }
1145 inline const T &first() const { Q_ASSERT(!isEmpty()); return *constBegin(); }
1146 inline T &last() { Q_ASSERT(!isEmpty()); return *std::next(end(), -1); }
1147 inline const T &last() const { Q_ASSERT(!isEmpty()); return *std::next(constEnd(), -1); }
1148
1149 class const_iterator;
1150
1152 {
1153 friend class QMultiMap<Key, T>;
1154 friend class const_iterator;
1155
1156 typename Map::iterator i;
1157 explicit iterator(typename Map::iterator it) : i(it) {}
1158 public:
1159 using iterator_category = std::bidirectional_iterator_tag;
1161 using value_type = T;
1162 using pointer = T *;
1163 using reference = T &;
1164
1165 iterator() = default;
1166
1167 const Key &key() const { return i->first; }
1168 T &value() const { return i->second; }
1169 T &operator*() const { return i->second; }
1170 T *operator->() const { return &i->second; }
1171 friend bool operator==(const iterator &lhs, const iterator &rhs) { return lhs.i == rhs.i; }
1172 friend bool operator!=(const iterator &lhs, const iterator &rhs) { return lhs.i != rhs.i; }
1173
1175 {
1176 ++i;
1177 return *this;
1178 }
1180 {
1181 iterator r = *this;
1182 ++i;
1183 return r;
1184 }
1186 {
1187 --i;
1188 return *this;
1189 }
1191 {
1192 iterator r = *this;
1193 --i;
1194 return r;
1195 }
1196
1197#if QT_DEPRECATED_SINCE(6, 0)
1198 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1200 friend iterator operator+(iterator it, difference_type j) { return std::next(it, j); }
1201
1202 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1204 friend iterator operator-(iterator it, difference_type j) { return std::prev(it, j); }
1205
1206 QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMultiMap iterators are not random access")
1207 iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
1208
1209 QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMultiMap iterators are not random access")
1210 iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
1211
1212 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1214 friend iterator operator+(difference_type j, iterator it) { return std::next(it, j); }
1215
1216 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1218 friend iterator operator-(difference_type j, iterator it) { return std::prev(it, j); }
1219#endif
1220 };
1221
1223 {
1224 friend class QMultiMap<Key, T>;
1225 typename Map::const_iterator i;
1226 explicit const_iterator(typename Map::const_iterator it) : i(it) {}
1227
1228 public:
1229 using iterator_category = std::bidirectional_iterator_tag;
1231 using value_type = T;
1232 using pointer = const T *;
1233 using reference = const T &;
1234
1235 const_iterator() = default;
1237
1238 const Key &key() const { return i->first; }
1239 const T &value() const { return i->second; }
1240 const T &operator*() const { return i->second; }
1241 const T *operator->() const { return &i->second; }
1242 friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i == rhs.i; }
1243 friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i != rhs.i; }
1244
1246 {
1247 ++i;
1248 return *this;
1249 }
1251 {
1252 const_iterator r = *this;
1253 ++i;
1254 return r;
1255 }
1257 {
1258 --i;
1259 return *this;
1260 }
1262 {
1263 const_iterator r = *this;
1264 --i;
1265 return r;
1266 }
1267
1268#if QT_DEPRECATED_SINCE(6, 0)
1269 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1271 friend const_iterator operator+(const_iterator it, difference_type j) { return std::next(it, j); }
1272
1273 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1275 friend const_iterator operator-(const_iterator it, difference_type j) { return std::prev(it, j); }
1276
1277 QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMultiMap iterators are not random access")
1278 const_iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
1279
1280 QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMultiMap iterators are not random access")
1281 const_iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
1282
1283 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1285 friend const_iterator operator+(difference_type j, const_iterator it) { return std::next(it, j); }
1286
1287 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1289 friend const_iterator operator-(difference_type j, const_iterator it) { return std::prev(it, j); }
1290#endif
1291 };
1292
1294 {
1296
1297 public:
1301 typedef const Key *pointer;
1302 typedef const Key &reference;
1303
1304 key_iterator() = default;
1306
1307 const Key &operator*() const { return i.key(); }
1308 const Key *operator->() const { return &i.key(); }
1309 bool operator==(key_iterator o) const { return i == o.i; }
1310 bool operator!=(key_iterator o) const { return i != o.i; }
1311
1312 inline key_iterator &operator++() { ++i; return *this; }
1313 inline key_iterator operator++(int) { return key_iterator(i++);}
1314 inline key_iterator &operator--() { --i; return *this; }
1315 inline key_iterator operator--(int) { return key_iterator(i--); }
1316 const_iterator base() const { return i; }
1317 };
1318
1319 typedef QKeyValueIterator<const Key&, const T&, const_iterator> const_key_value_iterator;
1320 typedef QKeyValueIterator<const Key&, T&, iterator> key_value_iterator;
1321
1322 // STL style
1323 iterator begin() { detach(); return iterator(d->m.begin()); }
1324 const_iterator begin() const { if (!d) return const_iterator(); return const_iterator(d->m.cbegin()); }
1325 const_iterator constBegin() const { return begin(); }
1326 const_iterator cbegin() const { return begin(); }
1327 iterator end() { detach(); return iterator(d->m.end()); }
1328 const_iterator end() const { if (!d) return const_iterator(); return const_iterator(d->m.end()); }
1329 const_iterator constEnd() const { return end(); }
1330 const_iterator cend() const { return end(); }
1332 key_iterator keyEnd() const { return key_iterator(end()); }
1339 auto asKeyValueRange() & { return QtPrivate::QKeyValueRange(*this); }
1340 auto asKeyValueRange() const & { return QtPrivate::QKeyValueRange(*this); }
1341 auto asKeyValueRange() && { return QtPrivate::QKeyValueRange(std::move(*this)); }
1342 auto asKeyValueRange() const && { return QtPrivate::QKeyValueRange(std::move(*this)); }
1343
1345 {
1346 return erase(it, std::next(it));
1347 }
1348
1350 {
1351 if (!d)
1352 return iterator();
1353
1354 if (!d.isShared())
1355 return iterator(d->m.erase(afirst.i, alast.i));
1356
1357 auto result = d->erase(afirst.i, alast.i);
1358 d.reset(result.data);
1359 return iterator(result.it);
1360 }
1361
1362 // more Qt
1365
1367 {
1368 return size();
1369 }
1370
1372 {
1373 const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
1374 detach();
1375 return iterator(d->m.find(key));
1376 }
1377
1379 {
1380 if (!d)
1381 return const_iterator();
1382 return const_iterator(d->m.find(key));
1383 }
1384
1386 {
1387 return find(key);
1388 }
1389
1390 iterator find(const Key &key, const T &value)
1391 {
1392 const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
1393
1394 detach();
1395
1396 auto range = d->m.equal_range(key);
1397 auto i = std::find_if(range.first, range.second,
1398 MapData::valueIsEqualTo(value));
1399
1400 if (i != range.second)
1401 return iterator(i);
1402 return iterator(d->m.end());
1403 }
1404
1405 const_iterator find(const Key &key, const T &value) const
1406 {
1407 if (!d)
1408 return const_iterator();
1409
1410 auto range = d->m.equal_range(key);
1411 auto i = std::find_if(range.first, range.second,
1412 MapData::valueIsEqualTo(value));
1413
1414 if (i != range.second)
1415 return const_iterator(i);
1416 return const_iterator(d->m.end());
1417 }
1418
1419 const_iterator constFind(const Key &key, const T &value) const
1420 {
1421 return find(key, value);
1422 }
1423
1425 {
1426 const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
1427 detach();
1428 return iterator(d->m.lower_bound(key));
1429 }
1430
1432 {
1433 if (!d)
1434 return const_iterator();
1435 return const_iterator(d->m.lower_bound(key));
1436 }
1437
1439 {
1440 const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
1441 detach();
1442 return iterator(d->m.upper_bound(key));
1443 }
1444
1446 {
1447 if (!d)
1448 return const_iterator();
1449 return const_iterator(d->m.upper_bound(key));
1450 }
1451
1452 iterator insert(const Key &key, const T &value)
1453 {
1454 const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
1455 detach();
1456 // note that std::multimap inserts at the end of an equal_range for a key,
1457 // QMultiMap at the beginning.
1458 auto i = d->m.lower_bound(key);
1459 return iterator(d->m.insert(i, {key, value}));
1460 }
1461
1463 {
1464 const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
1465 typename Map::const_iterator dpos;
1466 if (!d || d.isShared()) {
1467 auto posDistance = d ? std::distance(d->m.cbegin(), pos.i) : 0;
1468 detach();
1469 dpos = std::next(d->m.cbegin(), posDistance);
1470 } else {
1471 dpos = pos.i;
1472 }
1473 return iterator(d->m.insert(dpos, {key, value}));
1474 }
1475
1476#if QT_DEPRECATED_SINCE(6, 0)
1477 QT_DEPRECATED_VERSION_X_6_0("Use insert() instead")
1478 iterator insertMulti(const Key &key, const T &value)
1479 {
1480 return insert(key, value);
1481 }
1482 QT_DEPRECATED_VERSION_X_6_0("Use insert() instead")
1483 iterator insertMulti(const_iterator pos, const Key &key, const T &value)
1484 {
1485 return insert(pos, key, value);
1486 }
1487
1488 QT_DEPRECATED_VERSION_X_6_0("Use unite() instead")
1489 void insert(const QMultiMap<Key, T> &map)
1490 {
1491 unite(map);
1492 }
1493
1494 QT_DEPRECATED_VERSION_X_6_0("Use unite() instead")
1495 void insert(QMultiMap<Key, T> &&map)
1496 {
1497 unite(std::move(map));
1498 }
1499#endif
1500
1501 iterator replace(const Key &key, const T &value)
1502 {
1503 const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
1504
1505 // TODO: improve. No need of copying and then overwriting.
1506 detach();
1507
1508 // Similarly, improve here (e.g. lower_bound and hinted insert);
1509 // there's no insert_or_assign on multimaps
1510 auto i = d->m.find(key);
1511 if (i != d->m.end())
1512 i->second = value;
1513 else
1514 i = d->m.insert({key, value});
1515
1516 return iterator(i);
1517 }
1518
1519 // STL compatibility
1520 inline bool empty() const { return isEmpty(); }
1521
1522 std::pair<iterator, iterator> equal_range(const Key &akey)
1523 {
1524 const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
1525 detach();
1526 auto result = d->m.equal_range(akey);
1527 return {iterator(result.first), iterator(result.second)};
1528 }
1529
1530 std::pair<const_iterator, const_iterator> equal_range(const Key &akey) const
1531 {
1532 if (!d)
1533 return {};
1534 auto result = d->m.equal_range(akey);
1535 return {const_iterator(result.first), const_iterator(result.second)};
1536 }
1537
1539 {
1540 if (other.isEmpty())
1541 return *this;
1542
1543 detach();
1544
1545 auto copy = other.d->m;
1546#ifdef __cpp_lib_node_extract
1547 copy.merge(std::move(d->m));
1548#else
1549 copy.insert(std::make_move_iterator(d->m.begin()),
1550 std::make_move_iterator(d->m.end()));
1551#endif
1552 d->m = std::move(copy);
1553 return *this;
1554 }
1555
1556 QMultiMap &unite(QMultiMap<Key, T> &&other)
1557 {
1558 if (!other.d || other.d->m.empty())
1559 return *this;
1560
1561 if (other.d.isShared()) {
1562 // fall back to a regular copy
1563 unite(other);
1564 return *this;
1565 }
1566
1567 detach();
1568
1569#ifdef __cpp_lib_node_extract
1570 other.d->m.merge(std::move(d->m));
1571#else
1572 other.d->m.insert(std::make_move_iterator(d->m.begin()),
1573 std::make_move_iterator(d->m.end()));
1574#endif
1575 *this = std::move(other);
1576 return *this;
1577 }
1578};
1579
1582
1583template <typename Key, typename T>
1584QMultiMap<Key, T> operator+(const QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
1585{
1586 auto result = lhs;
1587 result += rhs;
1588 return result;
1589}
1590
1591template <typename Key, typename T>
1592QMultiMap<Key, T> operator+=(QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
1593{
1594 return lhs.unite(rhs);
1595}
1596
1597template <typename Key, typename T, typename Predicate>
1598qsizetype erase_if(QMultiMap<Key, T> &map, Predicate pred)
1599{
1601}
1602
1604
1605#endif // QMAP_H
std::pair< QString, QString > value_type
Definition qlist.h:93
QList< T > values() const
Definition qmap.h:120
typename Map::iterator iterator
Definition qmap.h:33
EraseResult erase(const_iterator first, const_iterator last) const
Definition qmap.h:148
Key key(const T &value, const Key &defaultKey) const
Definition qmap.h:82
QMapData(Map &&other)
Definition qmap.h:46
typename Map::size_type size_type
Definition qmap.h:32
Map m
Definition qmap.h:39
QList< Key > keys(const T &value) const
Definition qmap.h:107
QMapData()=default
AMap Map
Definition qmap.h:28
typename Map::mapped_type T
Definition qmap.h:30
size_type count(const Key &key) const
Definition qmap.h:134
typename Map::const_iterator const_iterator
Definition qmap.h:34
typename Map::value_type value_type
Definition qmap.h:31
size_type copyIfNotEquivalentTo(const Map &source, const Key &key)
Definition qmap.h:52
static auto valueIsEqualTo(const T &value)
Definition qmap.h:77
typename Map::key_type Key
Definition qmap.h:29
QMapData(const Map &other)
Definition qmap.h:42
QList< Key > keys() const
Definition qmap.h:93
const_iterator operator++(int)
Definition qmap.h:525
friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs)
Definition qmap.h:518
const T & value() const
Definition qmap.h:514
const_iterator & operator++()
Definition qmap.h:520
const Key & key() const
Definition qmap.h:513
const_iterator()=default
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs)
Definition qmap.h:517
const T * operator->() const
Definition qmap.h:516
const T & reference
Definition qmap.h:508
const T * pointer
Definition qmap.h:507
Q_IMPLICIT const_iterator(const iterator &o)
Definition qmap.h:511
qptrdiff difference_type
Definition qmap.h:505
const_iterator & operator--()
Definition qmap.h:531
const_iterator operator--(int)
Definition qmap.h:536
std::bidirectional_iterator_tag iterator_category
Definition qmap.h:504
const T & operator*() const
Definition qmap.h:515
qptrdiff difference_type
Definition qmap.h:435
iterator operator++(int)
Definition qmap.h:454
friend bool operator==(const iterator &lhs, const iterator &rhs)
Definition qmap.h:446
const Key & key() const
Definition qmap.h:442
iterator operator--(int)
Definition qmap.h:465
T & value() const
Definition qmap.h:443
iterator()=default
T * operator->() const
Definition qmap.h:445
iterator & operator--()
Definition qmap.h:460
T & reference
Definition qmap.h:438
std::bidirectional_iterator_tag iterator_category
Definition qmap.h:434
friend bool operator!=(const iterator &lhs, const iterator &rhs)
Definition qmap.h:447
T & operator*() const
Definition qmap.h:444
T * pointer
Definition qmap.h:437
iterator & operator++()
Definition qmap.h:449
key_iterator(const_iterator o)
Definition qmap.h:580
key_iterator()=default
const_iterator::iterator_category iterator_category
Definition qmap.h:573
key_iterator & operator--()
Definition qmap.h:589
key_iterator & operator++()
Definition qmap.h:587
const Key * pointer
Definition qmap.h:576
const_iterator base() const
Definition qmap.h:591
const Key & reference
Definition qmap.h:577
const Key * operator->() const
Definition qmap.h:583
key_iterator operator--(int)
Definition qmap.h:590
const Key & operator*() const
Definition qmap.h:582
key_iterator operator++(int)
Definition qmap.h:588
bool operator==(key_iterator o) const
Definition qmap.h:584
const_iterator::difference_type difference_type
Definition qmap.h:574
bool operator!=(key_iterator o) const
Definition qmap.h:585
Definition qmap.h:187
iterator insert(const Key &key, const T &value)
Definition qmap.h:688
auto asKeyValueRange() &&
Definition qmap.h:616
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:357
QList< Key > keys(const T &value) const
Definition qmap.h:390
const_iterator end() const
Definition qmap.h:603
iterator erase(const_iterator it)
Definition qmap.h:619
key_value_iterator keyValueEnd()
Definition qmap.h:609
auto asKeyValueRange() &
Definition qmap.h:614
T & last()
Definition qmap.h:421
bool contains(const Key &key) const
Definition qmap.h:341
size_type count(const Key &key) const
Definition qmap.h:404
iterator insert(const_iterator pos, const Key &key, const T &value)
Definition qmap.h:696
std::map< Key, T > toStdMap() const &
Definition qmap.h:225
const_iterator cend() const
Definition qmap.h:605
QMap()=default
QList< T > values() const
Definition qmap.h:397
T & operator[](const Key &key)
Definition qmap.h:367
std::pair< const_iterator, const_iterator > equal_range(const Key &akey) const
Definition qmap.h:774
qptrdiff difference_type
Definition qmap.h:197
QKeyValueIterator< const Key &, T &, iterator > key_value_iterator
Definition qmap.h:595
size_type remove(const Key &key)
Definition qmap.h:300
const_key_value_iterator constKeyValueEnd() const
Definition qmap.h:613
const_iterator cbegin() const
Definition qmap.h:601
const_iterator lowerBound(const Key &key) const
Definition qmap.h:667
friend size_t qHash(const M &key, size_t seed=0) noexcept(QHashPrivate::noexceptPairHash< typename M::key_type, typename M::mapped_type >())
Definition qmap.h:796
const_iterator constFind(const Key &key) const
Definition qmap.h:655
T mapped_type
Definition qmap.h:196
void clear()
Definition qmap.h:289
QList< Key > keys() const
Definition qmap.h:383
bool isSharedWith(const QMap< Key, T > &other) const noexcept
Definition qmap.h:284
const_key_value_iterator constKeyValueBegin() const
Definition qmap.h:611
iterator find(const Key &key)
Definition qmap.h:641
void detach()
Definition qmap.h:271
void insert(const QMap< Key, T > &map)
Definition qmap.h:711
iterator lowerBound(const Key &key)
Definition qmap.h:660
iterator Iterator
Definition qmap.h:638
bool isEmpty() const
Definition qmap.h:269
const_iterator ConstIterator
Definition qmap.h:639
T & first()
Definition qmap.h:419
size_type count() const
Definition qmap.h:411
qsizetype size_type
Definition qmap.h:198
iterator begin()
Definition qmap.h:598
const Key & firstKey() const
Definition qmap.h:416
T operator[](const Key &key) const
Definition qmap.h:378
const_key_value_iterator keyValueEnd() const
Definition qmap.h:612
const Key & lastKey() const
Definition qmap.h:417
QMap(std::map< Key, T > &&other)
Definition qmap.h:220
iterator end()
Definition qmap.h:602
Key key_type
Definition qmap.h:195
iterator upperBound(const Key &key)
Definition qmap.h:674
iterator erase(const_iterator afirst, const_iterator alast)
Definition qmap.h:624
const_iterator constBegin() const
Definition qmap.h:600
const_iterator begin() const
Definition qmap.h:599
friend QTypeTraits::compare_eq_result_container< QMap, AKey, AT > operator!=(const QMap &lhs, const QMap &rhs)
Definition qmap.h:257
size_type removeIf(Predicate pred)
Definition qmap.h:317
size_type size() const
Definition qmap.h:267
key_iterator keyBegin() const
Definition qmap.h:606
auto asKeyValueRange() const &&
Definition qmap.h:617
bool empty() const
Definition qmap.h:761
const_key_value_iterator keyValueBegin() const
Definition qmap.h:610
key_value_iterator keyValueBegin()
Definition qmap.h:608
const T & first() const
Definition qmap.h:420
std::map< Key, T > toStdMap() &&
Definition qmap.h:232
std::pair< iterator, iterator > equal_range(const Key &akey)
Definition qmap.h:766
void insert(QMap< Key, T > &&map)
Definition qmap.h:734
bool isDetached() const noexcept
Definition qmap.h:279
QMap(const std::map< Key, T > &other)
Definition qmap.h:215
QMap(std::initializer_list< std::pair< Key, T > > list)
Definition qmap.h:209
Key key(const T &value, const Key &defaultKey=Key()) const
Definition qmap.h:349
const_iterator constEnd() const
Definition qmap.h:604
const_iterator upperBound(const Key &key) const
Definition qmap.h:681
key_iterator keyEnd() const
Definition qmap.h:607
QKeyValueIterator< const Key &, const T &, const_iterator > const_key_value_iterator
Definition qmap.h:594
auto asKeyValueRange() const &
Definition qmap.h:615
const_iterator find(const Key &key) const
Definition qmap.h:648
const T & last() const
Definition qmap.h:422
T take(const Key &key)
Definition qmap.h:322
void swap(QMap< Key, T > &other) noexcept
Definition qmap.h:204
friend QTypeTraits::compare_eq_result_container< QMap, AKey, AT > operator==(const QMap &lhs, const QMap &rhs)
Definition qmap.h:246
friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs)
Definition qmap.h:1243
Q_IMPLICIT const_iterator(const iterator &o)
Definition qmap.h:1236
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs)
Definition qmap.h:1242
const_iterator & operator--()
Definition qmap.h:1256
const T * operator->() const
Definition qmap.h:1241
const Key & key() const
Definition qmap.h:1238
const_iterator & operator++()
Definition qmap.h:1245
const_iterator operator--(int)
Definition qmap.h:1261
const T & operator*() const
Definition qmap.h:1240
const T & value() const
Definition qmap.h:1239
const_iterator operator++(int)
Definition qmap.h:1250
std::bidirectional_iterator_tag iterator_category
Definition qmap.h:1229
friend bool operator==(const iterator &lhs, const iterator &rhs)
Definition qmap.h:1171
T * operator->() const
Definition qmap.h:1170
iterator & operator++()
Definition qmap.h:1174
const Key & key() const
Definition qmap.h:1167
T & value() const
Definition qmap.h:1168
qptrdiff difference_type
Definition qmap.h:1160
friend bool operator!=(const iterator &lhs, const iterator &rhs)
Definition qmap.h:1172
std::bidirectional_iterator_tag iterator_category
Definition qmap.h:1159
iterator & operator--()
Definition qmap.h:1185
iterator operator++(int)
Definition qmap.h:1179
iterator operator--(int)
Definition qmap.h:1190
T & operator*() const
Definition qmap.h:1169
bool operator==(key_iterator o) const
Definition qmap.h:1309
const Key & operator*() const
Definition qmap.h:1307
const_iterator::difference_type difference_type
Definition qmap.h:1299
const_iterator base() const
Definition qmap.h:1316
key_iterator(const_iterator o)
Definition qmap.h:1305
key_iterator operator++(int)
Definition qmap.h:1313
const Key * operator->() const
Definition qmap.h:1308
const_iterator::iterator_category iterator_category
Definition qmap.h:1298
const Key * pointer
Definition qmap.h:1301
const Key & reference
Definition qmap.h:1302
bool operator!=(key_iterator o) const
Definition qmap.h:1310
key_iterator & operator--()
Definition qmap.h:1314
key_iterator & operator++()
Definition qmap.h:1312
key_iterator operator--(int)
Definition qmap.h:1315
size_type count(const Key &key) const
Definition qmap.h:1121
const_iterator find(const Key &key, const T &value) const
Definition qmap.h:1405
auto asKeyValueRange() const &&
Definition qmap.h:1342
QList< Key > keys(const T &value) const
Definition qmap.h:1083
iterator lowerBound(const Key &key)
Definition qmap.h:1424
size_type removeIf(Predicate pred)
Definition qmap.h:1020
iterator replace(const Key &key, const T &value)
Definition qmap.h:1501
friend QTypeTraits::compare_eq_result_container< QMultiMap, AKey, AT > operator!=(const QMultiMap &lhs, const QMultiMap &rhs)
Definition qmap.h:928
const_key_value_iterator constKeyValueEnd() const
Definition qmap.h:1338
QMultiMap & unite(const QMultiMap &other)
Definition qmap.h:1538
QMultiMap(std::multimap< Key, T > &&other)
Definition qmap.h:884
QList< Key > keys() const
Definition qmap.h:1076
QMultiMap(const QMap< Key, T > &other)
Definition qmap.h:850
const_iterator constFind(const Key &key) const
Definition qmap.h:1385
const_key_value_iterator keyValueBegin() const
Definition qmap.h:1335
QMultiMap(QMap< Key, T > &&other)
Definition qmap.h:860
friend QTypeTraits::compare_eq_result_container< QMultiMap, AKey, AT > operator==(const QMultiMap &lhs, const QMultiMap &rhs)
Definition qmap.h:917
const_iterator constEnd() const
Definition qmap.h:1329
bool contains(const Key &key) const
Definition qmap.h:1045
std::multimap< Key, T > toStdMultiMap() const &
Definition qmap.h:896
qptrdiff difference_type
Definition qmap.h:832
key_value_iterator keyValueEnd()
Definition qmap.h:1334
iterator end()
Definition qmap.h:1327
bool isSharedWith(const QMultiMap< Key, T > &other) const noexcept
Definition qmap.h:955
std::multimap< Key, T > toStdMap() const
Definition qmap.h:891
const_key_value_iterator constKeyValueBegin() const
Definition qmap.h:1336
const_iterator constFind(const Key &key, const T &value) const
Definition qmap.h:1419
size_type count() const
Definition qmap.h:1366
key_iterator keyBegin() const
Definition qmap.h:1331
const Key & firstKey() const
Definition qmap.h:1141
std::multimap< Key, T > toStdMultiMap() &&
Definition qmap.h:903
const_iterator find(const Key &key) const
Definition qmap.h:1378
QList< T > values(const Key &key) const
Definition qmap.h:1112
T mapped_type
Definition qmap.h:831
auto asKeyValueRange() const &
Definition qmap.h:1340
size_type count(const Key &key, const T &value) const
Definition qmap.h:1128
bool contains(const Key &key, const T &value) const
Definition qmap.h:1053
QKeyValueIterator< const Key &, const T &, const_iterator > const_key_value_iterator
Definition qmap.h:1319
bool empty() const
Definition qmap.h:1520
QMultiMap(std::initializer_list< std::pair< Key, T > > list)
Definition qmap.h:839
qsizetype size_type
Definition qmap.h:833
Key key_type
Definition qmap.h:830
const_iterator end() const
Definition qmap.h:1328
const_iterator upperBound(const Key &key) const
Definition qmap.h:1445
QMultiMap(const std::multimap< Key, T > &other)
Definition qmap.h:879
void detach()
Definition qmap.h:942
const_iterator ConstIterator
Definition qmap.h:1364
size_type remove(const Key &key, const T &value)
Definition qmap.h:987
bool isEmpty() const
Definition qmap.h:940
key_iterator keyEnd() const
Definition qmap.h:1332
std::pair< const_iterator, const_iterator > equal_range(const Key &akey) const
Definition qmap.h:1530
iterator find(const Key &key)
Definition qmap.h:1371
iterator insert(const Key &key, const T &value)
Definition qmap.h:1452
iterator erase(const_iterator it)
Definition qmap.h:1344
const T & last() const
Definition qmap.h:1147
T & last()
Definition qmap.h:1146
const Key & lastKey() const
Definition qmap.h:1142
const_iterator begin() const
Definition qmap.h:1324
size_type size() const
Definition qmap.h:938
const T & first() const
Definition qmap.h:1145
const_iterator constBegin() const
Definition qmap.h:1325
QMultiMap()=default
size_type remove(const Key &key)
Definition qmap.h:971
const_iterator cbegin() const
Definition qmap.h:1326
iterator insert(const_iterator pos, const Key &key, const T &value)
Definition qmap.h:1462
T value(const Key &key, const T &defaultValue=T()) const
Definition qmap.h:1066
iterator upperBound(const Key &key)
Definition qmap.h:1438
iterator Iterator
Definition qmap.h:1363
void swap(QMultiMap< Key, T > &other) noexcept
Definition qmap.h:845
QKeyValueIterator< const Key &, T &, iterator > key_value_iterator
Definition qmap.h:1320
std::pair< iterator, iterator > equal_range(const Key &akey)
Definition qmap.h:1522
iterator erase(const_iterator afirst, const_iterator alast)
Definition qmap.h:1349
void clear()
Definition qmap.h:960
key_value_iterator keyValueBegin()
Definition qmap.h:1333
iterator find(const Key &key, const T &value)
Definition qmap.h:1390
const_key_value_iterator keyValueEnd() const
Definition qmap.h:1337
auto asKeyValueRange() &
Definition qmap.h:1339
bool isDetached() const noexcept
Definition qmap.h:950
iterator begin()
Definition qmap.h:1323
QList< Key > uniqueKeys() const
Definition qmap.h:1090
auto asKeyValueRange() &&
Definition qmap.h:1341
Key key(const T &value, const Key &defaultKey=Key()) const
Definition qmap.h:1058
const_iterator lowerBound(const Key &key) const
Definition qmap.h:1431
T take(const Key &key)
Definition qmap.h:1025
T & first()
Definition qmap.h:1144
QList< T > values() const
Definition qmap.h:1105
const_iterator cend() const
Definition qmap.h:1330
\inmodule QtCore
Definition qshareddata.h:19
#define this
Definition dialogs.cpp:9
QMap< QString, QString > map
[6]
QMultiMap< int, QWidget * > multimap
[28]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_equal_container< Container, T >... >, bool > compare_eq_result_container
Definition qtypeinfo.h:337
auto associative_erase_if(Container &c, Predicate &pred)
QKeyValueRange(Map &) -> QKeyValueRange< Map & >
decltype( std::declval< std::enable_if_t<(sizeof...(T) > 0)> >(),(qHash(std::declval< const T & >()),...), size_t{}) QHashMultiReturnType
static jboolean copy(JNIEnv *, jobject)
#define Q_DECL_DEPRECATED_X(text)
#define Q_IMPLICIT
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_DECLARE_ASSOCIATIVE_ITERATOR(C)
Definition qiterator.h:94
#define Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(C)
Definition qiterator.h:130
QMultiMap< Key, T > operator+=(QMultiMap< Key, T > &lhs, const QMultiMap< Key, T > &rhs)
Definition qmap.h:1592
qsizetype erase_if(QMap< Key, T > &map, Predicate pred)
Definition qmap.h:812
QMultiMap< Key, T > operator+(const QMultiMap< Key, T > &lhs, const QMultiMap< Key, T > &rhs)
Definition qmap.h:1584
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLuint64 key
GLboolean r
[2]
GLuint GLuint end
GLsizei range
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLint first
GLsizei GLsizei GLchar * source
GLuint64EXT * result
[6]
GLfloat GLfloat p
[1]
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QT_DEPRECATED_VERSION_X_6_0(text)
ptrdiff_t qptrdiff
Definition qtypes.h:164
ptrdiff_t qsizetype
Definition qtypes.h:165
QList< int > list
[14]
QObject::connect nullptr
QSharedPointer< T > other(t)
[5]
QMapData * data
Definition qmap.h:144