File indexing completed on 2026-08-02 09:27:15
0001
0002
0003
0004
0005
0006 #ifndef QMAP_H
0007 #define QMAP_H
0008
0009 #include <QtCore/qcompare.h>
0010 #include <QtCore/qhashfunctions.h>
0011 #include <QtCore/qiterator.h>
0012 #include <QtCore/qlist.h>
0013 #include <QtCore/qrefcount.h>
0014 #include <QtCore/qpair.h>
0015 #include <QtCore/qscopeguard.h>
0016 #include <QtCore/qshareddata.h>
0017 #include <QtCore/qshareddata_impl.h>
0018 #include <QtCore/qttypetraits.h>
0019
0020 #include <functional>
0021 #include <initializer_list>
0022 #include <map>
0023 #include <algorithm>
0024
0025 QT_BEGIN_NAMESPACE
0026
0027
0028 template <typename AMap>
0029 class QMapData : public QSharedData
0030 {
0031 public:
0032 using Map = AMap;
0033 using Key = typename Map::key_type;
0034 using T = typename Map::mapped_type;
0035 using value_type = typename Map::value_type;
0036 using size_type = typename Map::size_type;
0037 using iterator = typename Map::iterator;
0038 using const_iterator = typename Map::const_iterator;
0039
0040 static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
0041 static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
0042
0043 Map m;
0044
0045 QMapData() = default;
0046 explicit QMapData(const Map &other)
0047 : m(other)
0048 {}
0049
0050 explicit QMapData(Map &&other)
0051 : m(std::move(other))
0052 {}
0053
0054
0055
0056 size_type copyIfNotEquivalentTo(const Map &source, const Key &key)
0057 {
0058 Q_ASSERT(m.empty());
0059
0060 size_type result = 0;
0061
0062 const auto keep = [this](auto it) { m.insert(m.cend(), *it); };
0063
0064 auto it = source.cbegin();
0065 const auto end = source.cend();
0066 const auto &cmp = m.key_comp();
0067
0068 for (; it != end && cmp(it->first, key); ++it)
0069 keep(it);
0070
0071 for (; it != end && !cmp(key, it->first); ++it)
0072 ++result;
0073
0074 for (; it != end; ++it)
0075 keep(it);
0076
0077 return result;
0078 }
0079
0080 void copyExceptFor(const Map &source, const iterator &skipit)
0081 {
0082 Q_ASSERT(m.empty());
0083
0084 auto it = source.cend();
0085 const auto end = source.cbegin();
0086 auto hint = m.end();
0087 if (it == end)
0088 return;
0089 do {
0090 --it;
0091 if (it == skipit)
0092 continue;
0093 hint = m.emplace_hint(hint, it->first, it->second);
0094 } while (it != end);
0095 }
0096
0097
0098 void fillWithMergeOf(const Map &source1, const Map &source2)
0099 {
0100 Q_ASSERT(m.empty());
0101
0102 auto insertionHint = m.end();
0103 auto src1It = source1.crbegin();
0104 const auto src1End = source1.crend();
0105 auto src2It = source2.crbegin();
0106 const auto src2End = source2.crend();
0107 const auto &keyCompare = m.key_comp();
0108 while (src1It != src1End && src2It != src2End) {
0109 if (keyCompare(src2It->first, src1It->first)) {
0110 insertionHint = m.emplace_hint(insertionHint, src1It->first, src1It->second);
0111 ++src1It;
0112 } else if (keyCompare(src1It->first, src2It->first)) {
0113 insertionHint = m.emplace_hint(insertionHint, src2It->first, src2It->second);
0114 ++src2It;
0115 } else {
0116
0117 insertionHint = m.emplace_hint(insertionHint, src2It->first, src2It->second);
0118 ++src1It;
0119 ++src2It;
0120 }
0121 }
0122 for (; src1It != src1End; ++src1It)
0123 insertionHint = m.emplace_hint(insertionHint, src1It->first, src1It->second);
0124 for (; src2It != src2End; ++src2It)
0125 insertionHint = m.emplace_hint(insertionHint, src2It->first, src2It->second);
0126 }
0127
0128
0129 void insertMap(const Map &source)
0130 {
0131 Q_ASSERT(!m.empty());
0132
0133 auto insertionHint = m.end();
0134 auto it = source.crbegin();
0135 const auto end = source.crend();
0136 for (; it != end; ++it)
0137 insertionHint = m.emplace_hint(insertionHint, it->first, it->second);
0138 }
0139
0140
0141
0142
0143 static auto valueIsEqualTo(const T &value)
0144 {
0145 return [&value](const auto &v) { return v.second == value; };
0146 }
0147
0148 Key key(const T &value, const Key &defaultKey) const
0149 {
0150 auto i = std::find_if(m.cbegin(),
0151 m.cend(),
0152 valueIsEqualTo(value));
0153 if (i != m.cend())
0154 return i->first;
0155
0156 return defaultKey;
0157 }
0158
0159 QList<Key> keys() const
0160 {
0161 QList<Key> result;
0162 result.reserve(m.size());
0163
0164 const auto extractKey = [](const auto &v) { return v.first; };
0165
0166 std::transform(m.cbegin(),
0167 m.cend(),
0168 std::back_inserter(result),
0169 extractKey);
0170 return result;
0171 }
0172
0173 QList<Key> keys(const T &value) const
0174 {
0175 QList<Key> result;
0176 result.reserve(m.size());
0177
0178 for (const auto &v : m) {
0179 if (v.second == value)
0180 result.append(v.first);
0181 }
0182 result.shrink_to_fit();
0183 return result;
0184 }
0185
0186 QList<T> values() const
0187 {
0188 QList<T> result;
0189 result.reserve(m.size());
0190
0191 const auto extractValue = [](const auto &v) { return v.second; };
0192
0193 std::transform(m.cbegin(),
0194 m.cend(),
0195 std::back_inserter(result),
0196 extractValue);
0197 return result;
0198 }
0199
0200 size_type count(const Key &key) const
0201 {
0202 return m.count(key);
0203 }
0204
0205
0206
0207
0208
0209 struct EraseResult {
0210 QMapData *data;
0211 iterator it;
0212 };
0213
0214 EraseResult erase(const_iterator first, const_iterator last) const
0215 {
0216 EraseResult result;
0217 result.data = new QMapData;
0218 result.it = result.data->m.end();
0219 const auto newDataEnd = result.it;
0220
0221 auto i = m.begin();
0222 const auto e = m.end();
0223
0224
0225 while (i != first) {
0226 result.it = result.data->m.insert(newDataEnd, *i);
0227 ++i;
0228 }
0229
0230
0231 while (i != last)
0232 ++i;
0233
0234
0235 while (i != e) {
0236 result.data->m.insert(newDataEnd, *i);
0237 ++i;
0238 }
0239
0240 if (result.it != newDataEnd)
0241 ++result.it;
0242
0243 return result;
0244 }
0245 };
0246
0247
0248
0249
0250
0251 template <class Key, class T>
0252 class QMap
0253 {
0254 using Map = std::map<Key, T>;
0255 using MapData = QMapData<Map>;
0256 QtPrivate::QExplicitlySharedDataPointerV2<MapData> d;
0257
0258 friend class QMultiMap<Key, T>;
0259
0260 public:
0261 using key_type = Key;
0262 using mapped_type = T;
0263 using difference_type = qptrdiff;
0264 using size_type = qsizetype;
0265
0266 QMap() = default;
0267
0268
0269
0270 void swap(QMap<Key, T> &other) noexcept
0271 {
0272 d.swap(other.d);
0273 }
0274
0275 QMap(std::initializer_list<std::pair<Key, T>> list)
0276 {
0277 for (auto &p : list)
0278 insert(p.first, p.second);
0279 }
0280
0281 explicit QMap(const std::map<Key, T> &other)
0282 : d(other.empty() ? nullptr : new MapData(other))
0283 {
0284 }
0285
0286 explicit QMap(std::map<Key, T> &&other)
0287 : d(other.empty() ? nullptr : new MapData(std::move(other)))
0288 {
0289 }
0290
0291 std::map<Key, T> toStdMap() const &
0292 {
0293 if (d)
0294 return d->m;
0295 return {};
0296 }
0297
0298 std::map<Key, T> toStdMap() &&
0299 {
0300 if (d) {
0301 if (d.isShared())
0302 return d->m;
0303 else
0304 return std::move(d->m);
0305 }
0306
0307 return {};
0308 }
0309
0310 #ifndef Q_QDOC
0311 private:
0312 template <typename AKey = Key, typename AT = T,
0313 QTypeTraits::compare_eq_result_container<QMap, AKey, AT> = true>
0314 friend bool comparesEqual(const QMap &lhs, const QMap &rhs)
0315 {
0316 if (lhs.d == rhs.d)
0317 return true;
0318 if (!lhs.d)
0319 return rhs == lhs;
0320 Q_ASSERT(lhs.d);
0321 return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
0322 }
0323 QT_DECLARE_EQUALITY_OPERATORS_HELPER(QMap, QMap, , noexcept(false),
0324 template <typename AKey = Key, typename AT = T,
0325 QTypeTraits::compare_eq_result_container<QMap, AKey, AT> = true>)
0326
0327 public:
0328 #else
0329 friend bool operator==(const QMap &lhs, const QMap &rhs);
0330 friend bool operator!=(const QMap &lhs, const QMap &rhs);
0331 #endif
0332
0333 size_type size() const { return d ? size_type(d->m.size()) : size_type(0); }
0334
0335 [[nodiscard]]
0336 bool isEmpty() const { return d ? d->m.empty() : true; }
0337
0338 void detach()
0339 {
0340 if (d)
0341 d.detach();
0342 else
0343 d.reset(new MapData);
0344 }
0345
0346
0347
0348 QMap referenceHoldingDetach()
0349 {
0350 if (!d) {
0351 d.reset(new MapData);
0352 } else if (d.isShared()) {
0353 auto hold = *this;
0354 d.detach();
0355 return hold;
0356 }
0357 return {};
0358 }
0359
0360
0361 QMap referenceHoldingDetachExcept(const Key &key)
0362 {
0363 if (!d) {
0364 d.reset(new MapData);
0365 } else if (d.isShared()) {
0366 auto hold = *this;
0367 QtPrivate::QExplicitlySharedDataPointerV2<MapData> newData(new MapData);
0368 newData->copyIfNotEquivalentTo(d->m, key);
0369 d.swap(newData);
0370 return hold;
0371 }
0372 return {};
0373 }
0374
0375 bool isDetached() const noexcept
0376 {
0377 return d ? !d.isShared() : false;
0378 }
0379
0380 bool isSharedWith(const QMap<Key, T> &other) const noexcept
0381 {
0382 return d == other.d;
0383 }
0384
0385 void clear()
0386 {
0387 if (!d)
0388 return;
0389
0390 if (!d.isShared())
0391 d->m.clear();
0392 else
0393 d.reset();
0394 }
0395
0396 size_type remove(const Key &key)
0397 {
0398 if (!d)
0399 return 0;
0400
0401 if (!d.isShared())
0402 return size_type(d->m.erase(key));
0403
0404 MapData *newData = new MapData;
0405 size_type result = newData->copyIfNotEquivalentTo(d->m, key);
0406
0407 d.reset(newData);
0408
0409 return result;
0410 }
0411
0412 template <typename Predicate>
0413 size_type removeIf(Predicate pred)
0414 {
0415 return QtPrivate::associative_erase_if(*this, pred);
0416 }
0417
0418 T take(const Key &key)
0419 {
0420 if (!d)
0421 return T();
0422
0423 if (d.isShared()) {
0424 Map m;
0425
0426
0427 const auto commit = qScopeGuard([&] { QMap{std::move(m)}.swap(*this); });
0428
0429
0430
0431
0432
0433 const auto keep = [&m] (auto it) { m.insert(m.cend(), *it); };
0434
0435 auto it = d->m.cbegin();
0436 const auto end = d->m.cend();
0437 const auto cmp = d->m.key_comp();
0438 while (it != end) {
0439 if (cmp(it->first, key)) {
0440 keep(it);
0441 ++it;
0442 } else if (cmp(key, it->first)) {
0443
0444
0445 while (it != end) {
0446 keep(it);
0447 ++it;
0448 }
0449 break;
0450 } else {
0451 return [&] {
0452 T r = it->second;
0453 while (++it != end)
0454 keep(it);
0455 return r;
0456 }();
0457 }
0458 }
0459
0460 return T();
0461 }
0462
0463 #ifdef __cpp_lib_node_extract
0464 if (const auto node = d->m.extract(key))
0465 return std::move(node.mapped());
0466 #else
0467 auto i = d->m.find(key);
0468 if (i != d->m.end()) {
0469
0470 T result(std::move(i->second));
0471 d->m.erase(i);
0472 return result;
0473 }
0474 #endif
0475 return T();
0476 }
0477
0478 bool contains(const Key &key) const
0479 {
0480 if (!d)
0481 return false;
0482 auto i = d->m.find(key);
0483 return i != d->m.end();
0484 }
0485
0486 Key key(const T &value, const Key &defaultKey = Key()) const
0487 {
0488 if (!d)
0489 return defaultKey;
0490
0491 return d->key(value, defaultKey);
0492 }
0493
0494 T value(const Key &key, const T &defaultValue = T()) const
0495 {
0496 if (!d)
0497 return defaultValue;
0498 const auto i = d->m.find(key);
0499 if (i != d->m.cend())
0500 return i->second;
0501 return defaultValue;
0502 }
0503
0504 T &operator[](const Key &key)
0505 {
0506 const auto hold = referenceHoldingDetach();
0507 auto i = d->m.find(key);
0508 if (i == d->m.end())
0509 i = d->m.insert({key, T()}).first;
0510 return i->second;
0511 }
0512
0513
0514 T operator[](const Key &key) const
0515 {
0516 return value(key);
0517 }
0518
0519 QList<Key> keys() const
0520 {
0521 if (!d)
0522 return {};
0523 return d->keys();
0524 }
0525
0526 QList<Key> keys(const T &value) const
0527 {
0528 if (!d)
0529 return {};
0530 return d->keys(value);
0531 }
0532
0533 QList<T> values() const
0534 {
0535 if (!d)
0536 return {};
0537 return d->values();
0538 }
0539
0540 size_type count(const Key &key) const
0541 {
0542 if (!d)
0543 return 0;
0544 return d->count(key);
0545 }
0546
0547 size_type count() const
0548 {
0549 return size();
0550 }
0551
0552 inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
0553 inline const Key &lastKey() const { Q_ASSERT(!isEmpty()); return (--constEnd()).key(); }
0554
0555 inline T &first() { Q_ASSERT(!isEmpty()); return *begin(); }
0556 inline const T &first() const { Q_ASSERT(!isEmpty()); return *constBegin(); }
0557 inline T &last() { Q_ASSERT(!isEmpty()); return *(--end()); }
0558 inline const T &last() const { Q_ASSERT(!isEmpty()); return *(--constEnd()); }
0559
0560 class const_iterator;
0561
0562 class iterator
0563 {
0564 friend class QMap<Key, T>;
0565 friend class const_iterator;
0566
0567 typename Map::iterator i;
0568 explicit iterator(typename Map::iterator it) : i(it) {}
0569 public:
0570 using iterator_category = std::bidirectional_iterator_tag;
0571 using difference_type = qptrdiff;
0572 using value_type = T;
0573 using pointer = T *;
0574 using reference = T &;
0575
0576 iterator() = default;
0577
0578 const Key &key() const { return i->first; }
0579 T &value() const { return i->second; }
0580 T &operator*() const { return i->second; }
0581 T *operator->() const { return &i->second; }
0582 friend bool operator==(const iterator &lhs, const iterator &rhs) { return lhs.i == rhs.i; }
0583 friend bool operator!=(const iterator &lhs, const iterator &rhs) { return lhs.i != rhs.i; }
0584
0585 iterator &operator++()
0586 {
0587 ++i;
0588 return *this;
0589 }
0590 iterator operator++(int)
0591 {
0592 iterator r = *this;
0593 ++i;
0594 return r;
0595 }
0596 iterator &operator--()
0597 {
0598 --i;
0599 return *this;
0600 }
0601 iterator operator--(int)
0602 {
0603 iterator r = *this;
0604 --i;
0605 return r;
0606 }
0607
0608 #if QT_DEPRECATED_SINCE(6, 0)
0609 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
0610
0611 friend iterator operator+(iterator it, difference_type j) { return std::next(it, j); }
0612
0613 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
0614
0615 friend iterator operator-(iterator it, difference_type j) { return std::prev(it, j); }
0616
0617 QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMap iterators are not random access")
0618 iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
0619
0620 QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMap iterators are not random access")
0621 iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
0622
0623 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
0624
0625 friend iterator operator+(difference_type j, iterator it) { return std::next(it, j); }
0626
0627 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
0628
0629 friend iterator operator-(difference_type j, iterator it) { return std::prev(it, j); }
0630 #endif
0631 };
0632
0633 class const_iterator
0634 {
0635 friend class QMap<Key, T>;
0636 typename Map::const_iterator i;
0637 explicit const_iterator(typename Map::const_iterator it) : i(it) {}
0638
0639 public:
0640 using iterator_category = std::bidirectional_iterator_tag;
0641 using difference_type = qptrdiff;
0642 using value_type = T;
0643 using pointer = const T *;
0644 using reference = const T &;
0645
0646 const_iterator() = default;
0647 Q_IMPLICIT const_iterator(const iterator &o) : i(o.i) {}
0648
0649 const Key &key() const { return i->first; }
0650 const T &value() const { return i->second; }
0651 const T &operator*() const { return i->second; }
0652 const T *operator->() const { return &i->second; }
0653 friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i == rhs.i; }
0654 friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i != rhs.i; }
0655
0656 const_iterator &operator++()
0657 {
0658 ++i;
0659 return *this;
0660 }
0661 const_iterator operator++(int)
0662 {
0663 const_iterator r = *this;
0664 ++i;
0665 return r;
0666 }
0667 const_iterator &operator--()
0668 {
0669 --i;
0670 return *this;
0671 }
0672 const_iterator operator--(int)
0673 {
0674 const_iterator r = *this;
0675 --i;
0676 return r;
0677 }
0678
0679 #if QT_DEPRECATED_SINCE(6, 0)
0680 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
0681
0682 friend const_iterator operator+(const_iterator it, difference_type j) { return std::next(it, j); }
0683
0684 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
0685
0686 friend const_iterator operator-(const_iterator it, difference_type j) { return std::prev(it, j); }
0687
0688 QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMap iterators are not random access")
0689 const_iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
0690
0691 QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMap iterators are not random access")
0692 const_iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
0693
0694 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
0695
0696 friend const_iterator operator+(difference_type j, const_iterator it) { return std::next(it, j); }
0697
0698 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
0699
0700 friend const_iterator operator-(difference_type j, const_iterator it) { return std::prev(it, j); }
0701 #endif
0702 };
0703
0704 class key_iterator
0705 {
0706 const_iterator i;
0707
0708 public:
0709 typedef typename const_iterator::iterator_category iterator_category;
0710 typedef typename const_iterator::difference_type difference_type;
0711 typedef Key value_type;
0712 typedef const Key *pointer;
0713 typedef const Key &reference;
0714
0715 key_iterator() = default;
0716 explicit key_iterator(const_iterator o) : i(o) { }
0717
0718 const Key &operator*() const { return i.key(); }
0719 const Key *operator->() const { return &i.key(); }
0720 bool operator==(key_iterator o) const { return i == o.i; }
0721 bool operator!=(key_iterator o) const { return i != o.i; }
0722
0723 inline key_iterator &operator++() { ++i; return *this; }
0724 inline key_iterator operator++(int) { return key_iterator(i++);}
0725 inline key_iterator &operator--() { --i; return *this; }
0726 inline key_iterator operator--(int) { return key_iterator(i--); }
0727 const_iterator base() const { return i; }
0728 };
0729
0730 typedef QKeyValueIterator<const Key&, const T&, const_iterator> const_key_value_iterator;
0731 typedef QKeyValueIterator<const Key&, T&, iterator> key_value_iterator;
0732
0733
0734 iterator begin() { detach(); return iterator(d->m.begin()); }
0735 const_iterator begin() const { if (!d) return const_iterator(); return const_iterator(d->m.cbegin()); }
0736 const_iterator constBegin() const { return begin(); }
0737 const_iterator cbegin() const { return begin(); }
0738 iterator end() { detach(); return iterator(d->m.end()); }
0739 const_iterator end() const { if (!d) return const_iterator(); return const_iterator(d->m.end()); }
0740 const_iterator constEnd() const { return end(); }
0741 const_iterator cend() const { return end(); }
0742 key_iterator keyBegin() const { return key_iterator(begin()); }
0743 key_iterator keyEnd() const { return key_iterator(end()); }
0744 key_value_iterator keyValueBegin() { return key_value_iterator(begin()); }
0745 key_value_iterator keyValueEnd() { return key_value_iterator(end()); }
0746 const_key_value_iterator keyValueBegin() const { return const_key_value_iterator(begin()); }
0747 const_key_value_iterator constKeyValueBegin() const { return const_key_value_iterator(begin()); }
0748 const_key_value_iterator keyValueEnd() const { return const_key_value_iterator(end()); }
0749 const_key_value_iterator constKeyValueEnd() const { return const_key_value_iterator(end()); }
0750 auto asKeyValueRange() & { return QtPrivate::QKeyValueRange<QMap &>(*this); }
0751 auto asKeyValueRange() const & { return QtPrivate::QKeyValueRange<const QMap &>(*this); }
0752 auto asKeyValueRange() && { return QtPrivate::QKeyValueRange<QMap>(std::move(*this)); }
0753 auto asKeyValueRange() const && { return QtPrivate::QKeyValueRange<QMap>(std::move(*this)); }
0754
0755 iterator erase(const_iterator it)
0756 {
0757 return erase(it, std::next(it));
0758 }
0759
0760 iterator erase(const_iterator afirst, const_iterator alast)
0761 {
0762 if (!d)
0763 return iterator();
0764
0765 if (!d.isShared())
0766 return iterator(d->m.erase(afirst.i, alast.i));
0767
0768 auto result = d->erase(afirst.i, alast.i);
0769 d.reset(result.data);
0770 return iterator(result.it);
0771 }
0772
0773
0774 typedef iterator Iterator;
0775 typedef const_iterator ConstIterator;
0776
0777 iterator find(const Key &key)
0778 {
0779 const auto hold = referenceHoldingDetach();
0780 return iterator(d->m.find(key));
0781 }
0782
0783 const_iterator find(const Key &key) const
0784 {
0785 if (!d)
0786 return const_iterator();
0787 return const_iterator(d->m.find(key));
0788 }
0789
0790 const_iterator constFind(const Key &key) const
0791 {
0792 return find(key);
0793 }
0794
0795 iterator lowerBound(const Key &key)
0796 {
0797 const auto hold = referenceHoldingDetach();
0798 return iterator(d->m.lower_bound(key));
0799 }
0800
0801 const_iterator lowerBound(const Key &key) const
0802 {
0803 if (!d)
0804 return const_iterator();
0805 return const_iterator(d->m.lower_bound(key));
0806 }
0807
0808 iterator upperBound(const Key &key)
0809 {
0810 const auto hold = referenceHoldingDetach();
0811 return iterator(d->m.upper_bound(key));
0812 }
0813
0814 const_iterator upperBound(const Key &key) const
0815 {
0816 if (!d)
0817 return const_iterator();
0818 return const_iterator(d->m.upper_bound(key));
0819 }
0820
0821 iterator insert(const Key &key, const T &value)
0822 {
0823 const auto hold = referenceHoldingDetachExcept(key);
0824 return iterator(d->m.insert_or_assign(key, value).first);
0825 }
0826
0827 iterator insert(const_iterator pos, const Key &key, const T &value)
0828 {
0829 if (!d) {
0830 detach();
0831 return iterator(d->m.emplace(key, value).first);
0832 } else if (d.isShared()) {
0833 auto posDistance = std::distance(d->m.cbegin(), pos.i);
0834 const auto hold = referenceHoldingDetachExcept(key);
0835 auto dpos = std::next(d->m.cbegin(), posDistance);
0836 return iterator(d->m.insert_or_assign(dpos, key, value));
0837 }
0838 return iterator(d->m.insert_or_assign(pos.i, key, value));
0839 }
0840
0841 void insert(const QMap<Key, T> &map)
0842 {
0843 if (map.isEmpty())
0844 return;
0845
0846 if (isEmpty()) {
0847 *this = map;
0848 return;
0849 }
0850
0851 if (d.isShared()) {
0852 QtPrivate::QExplicitlySharedDataPointerV2<MapData> newD(new MapData);
0853 const auto commit = qScopeGuard([&] { newD.swap(d); });
0854 newD->fillWithMergeOf(d->m, map.d->m);
0855 return;
0856 }
0857
0858 #ifdef __cpp_lib_node_extract
0859
0860 auto copy = map.d->m;
0861 copy.merge(d->m);
0862 d->m = std::move(copy);
0863 #else
0864 QtPrivate::QExplicitlySharedDataPointerV2<MapData> newD(new MapData);
0865 const auto commit = qScopeGuard([&] { newD.swap(d); });
0866 newD->fillWithMergeOf(d->m, map.d->m);
0867
0868 #endif
0869 }
0870
0871 void insert(QMap<Key, T> &&map)
0872 {
0873 if (map.isEmpty() || map.d.isShared()) {
0874
0875 insert(map);
0876 return;
0877 }
0878
0879
0880 const auto commit = qScopeGuard([&] { map.swap(*this); });
0881 if (isEmpty())
0882 return;
0883
0884 if (d.isShared()) {
0885 map.d->insertMap(d->m);
0886 return;
0887 }
0888
0889 #ifdef __cpp_lib_node_extract
0890 map.d->m.merge(std::move(d->m));
0891 #else
0892
0893 map.d->insertMap(d->m);
0894 #endif
0895 }
0896
0897
0898 [[nodiscard]]
0899 inline bool empty() const
0900 {
0901 return isEmpty();
0902 }
0903
0904 std::pair<iterator, iterator> equal_range(const Key &akey)
0905 {
0906 const auto hold = referenceHoldingDetach();
0907 auto result = d->m.equal_range(akey);
0908 return {iterator(result.first), iterator(result.second)};
0909 }
0910
0911 std::pair<const_iterator, const_iterator> equal_range(const Key &akey) const
0912 {
0913 if (!d)
0914 return {};
0915 auto result = d->m.equal_range(akey);
0916 return {const_iterator(result.first), const_iterator(result.second)};
0917 }
0918
0919 private:
0920 #ifdef Q_QDOC
0921 friend size_t qHash(const QMap &key, size_t seed = 0);
0922 #else
0923 # if defined(Q_CC_GHS) || defined (Q_CC_MSVC)
0924
0925
0926
0927 template <typename M, std::enable_if_t<std::is_same_v<M, QMap>, bool> = true>
0928 friend QtPrivate::QHashMultiReturnType<typename M::key_type, typename M::mapped_type>
0929 # else
0930 using M = QMap;
0931 friend size_t
0932 # endif
0933 qHash(const M &key, size_t seed = 0)
0934 noexcept(QHashPrivate::noexceptPairHash<typename M::key_type, typename M::mapped_type>())
0935 {
0936 if (!key.d)
0937 return seed;
0938
0939 return std::accumulate(key.d->m.begin(), key.d->m.end(), seed,
0940 QtPrivate::QHashCombine{seed});
0941 }
0942 #endif
0943 };
0944
0945 Q_DECLARE_ASSOCIATIVE_ITERATOR(Map)
0946 Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(Map)
0947
0948 template <typename Key, typename T, typename Predicate>
0949 qsizetype erase_if(QMap<Key, T> &map, Predicate pred)
0950 {
0951 return QtPrivate::associative_erase_if(map, pred);
0952 }
0953
0954
0955
0956
0957
0958
0959 template <class Key, class T>
0960 class QMultiMap
0961 {
0962 using Map = std::multimap<Key, T>;
0963 using MapData = QMapData<Map>;
0964 QtPrivate::QExplicitlySharedDataPointerV2<MapData> d;
0965
0966 public:
0967 using key_type = Key;
0968 using mapped_type = T;
0969 using difference_type = qptrdiff;
0970 using size_type = qsizetype;
0971
0972 QMultiMap() = default;
0973
0974
0975
0976 QMultiMap(std::initializer_list<std::pair<Key,T>> list)
0977 {
0978 for (auto &p : list)
0979 insert(p.first, p.second);
0980 }
0981
0982 void swap(QMultiMap<Key, T> &other) noexcept
0983 {
0984 d.swap(other.d);
0985 }
0986
0987 explicit QMultiMap(const QMap<Key, T> &other)
0988 : d(other.isEmpty() ? nullptr : new MapData)
0989 {
0990 if (d) {
0991 Q_ASSERT(other.d);
0992 d->m.insert(other.d->m.begin(),
0993 other.d->m.end());
0994 }
0995 }
0996
0997 explicit QMultiMap(QMap<Key, T> &&other)
0998 : d(other.isEmpty() ? nullptr : new MapData)
0999 {
1000 if (d) {
1001 Q_ASSERT(other.d);
1002 if (other.d.isShared()) {
1003 d->m.insert(other.d->m.begin(),
1004 other.d->m.end());
1005 } else {
1006 #ifdef __cpp_lib_node_extract
1007 d->m.merge(std::move(other.d->m));
1008 #else
1009 d->m.insert(std::make_move_iterator(other.d->m.begin()),
1010 std::make_move_iterator(other.d->m.end()));
1011 #endif
1012 }
1013 }
1014 }
1015
1016 explicit QMultiMap(const std::multimap<Key, T> &other)
1017 : d(other.empty() ? nullptr : new MapData(other))
1018 {
1019 }
1020
1021 explicit QMultiMap(std::multimap<Key, T> &&other)
1022 : d(other.empty() ? nullptr : new MapData(std::move(other)))
1023 {
1024 }
1025
1026
1027 Q_DECL_DEPRECATED_X("Use toStdMultiMap instead")
1028 std::multimap<Key, T> toStdMap() const
1029 {
1030 return toStdMultiMap();
1031 }
1032
1033 std::multimap<Key, T> toStdMultiMap() const &
1034 {
1035 if (d)
1036 return d->m;
1037 return {};
1038 }
1039
1040 std::multimap<Key, T> toStdMultiMap() &&
1041 {
1042 if (d) {
1043 if (d.isShared())
1044 return d->m;
1045 else
1046 return std::move(d->m);
1047 }
1048
1049 return {};
1050 }
1051
1052 #ifndef Q_QDOC
1053 private:
1054 template <typename AKey = Key, typename AT = T,
1055 QTypeTraits::compare_eq_result_container<QMultiMap, AKey, AT> = true>
1056 friend bool comparesEqual(const QMultiMap &lhs, const QMultiMap &rhs)
1057 {
1058 if (lhs.d == rhs.d)
1059 return true;
1060 if (!lhs.d)
1061 return rhs == lhs;
1062 Q_ASSERT(lhs.d);
1063 return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
1064 }
1065 QT_DECLARE_EQUALITY_OPERATORS_HELPER(QMultiMap, QMultiMap, , noexcept(false),
1066 template <typename AKey = Key, typename AT = T,
1067 QTypeTraits::compare_eq_result_container<QMultiMap, AKey, AT> = true>)
1068
1069 public:
1070 #else
1071 friend bool operator==(const QMultiMap &lhs, const QMultiMap &rhs);
1072 friend bool operator!=(const QMultiMap &lhs, const QMultiMap &rhs);
1073 #endif
1074
1075 size_type size() const { return d ? size_type(d->m.size()) : size_type(0); }
1076
1077 [[nodiscard]]
1078 bool isEmpty() const { return d ? d->m.empty() : true; }
1079
1080 void detach()
1081 {
1082 if (d)
1083 d.detach();
1084 else
1085 d.reset(new MapData);
1086 }
1087
1088
1089
1090 [[nodiscard]] QMultiMap referenceHoldingDetach()
1091 {
1092 if (!d) {
1093 d.reset(new MapData);
1094 } else if (d.isShared()) {
1095 auto hold = *this;
1096 d.detach();
1097 return hold;
1098 }
1099 return {};
1100 }
1101
1102
1103 [[nodiscard]] QMultiMap referenceHoldingDetachExceptFor(const typename Map::iterator &skipit)
1104 {
1105 Q_ASSERT(d.isShared());
1106 auto hold = *this;
1107 QtPrivate::QExplicitlySharedDataPointerV2<MapData> newData(new MapData);
1108 newData->copyExceptFor(d->m, skipit);
1109 d.swap(newData);
1110 return hold;
1111 }
1112
1113 bool isDetached() const noexcept
1114 {
1115 return d ? !d.isShared() : false;
1116 }
1117
1118 bool isSharedWith(const QMultiMap<Key, T> &other) const noexcept
1119 {
1120 return d == other.d;
1121 }
1122
1123 void clear()
1124 {
1125 if (!d)
1126 return;
1127
1128 if (!d.isShared())
1129 d->m.clear();
1130 else
1131 d.reset();
1132 }
1133
1134 size_type remove(const Key &key)
1135 {
1136 if (!d)
1137 return 0;
1138
1139 if (!d.isShared())
1140 return size_type(d->m.erase(key));
1141
1142 MapData *newData = new MapData;
1143 size_type result = newData->copyIfNotEquivalentTo(d->m, key);
1144
1145 d.reset(newData);
1146
1147 return result;
1148 }
1149
1150 size_type remove(const Key &key, const T &value)
1151 {
1152 if (!d)
1153 return 0;
1154
1155 size_type result = 0;
1156 const auto &keyCompare = d->m.key_comp();
1157
1158 if (d.isShared()) {
1159 QtPrivate::QExplicitlySharedDataPointerV2<MapData> newData(new MapData);
1160 const auto keep = [&newData](auto it) { newData->m.insert(newData->m.cend(), *it); };
1161
1162 auto it = d->m.cbegin();
1163 const auto end = d->m.cend();
1164 for (; it != end && keyCompare(it->first, key); ++it)
1165 keep(it);
1166
1167 for (; it != end && !keyCompare(key, it->first); ++it) {
1168 if (!(it->second == value))
1169 keep(it);
1170 else
1171 ++result;
1172 }
1173 for (; it != end; ++it)
1174 keep(it);
1175
1176 d.swap(newData);
1177 return result;
1178 }
1179
1180
1181
1182 auto [i, e] = d->m.equal_range(key);
1183 if (i == e)
1184 return result;
1185
1186
1187
1188 const T valueCopy = value;
1189 while (i != e) {
1190 if (i->second == valueCopy) {
1191 i = d->m.erase(i);
1192 ++result;
1193 } else {
1194 ++i;
1195 }
1196 }
1197
1198 return result;
1199 }
1200
1201 template <typename Predicate>
1202 size_type removeIf(Predicate pred)
1203 {
1204 return QtPrivate::associative_erase_if(*this, pred);
1205 }
1206
1207 T take(const Key &key)
1208 {
1209 if (!d)
1210 return T();
1211
1212 if (d.isShared()) {
1213 auto i = d->m.find(key);
1214 const auto hold = referenceHoldingDetachExceptFor(i);
1215 return i->second;
1216 }
1217
1218 #ifdef __cpp_lib_node_extract
1219 if (const auto node = d->m.extract(key))
1220 return std::move(node.mapped());
1221 #else
1222 auto i = d->m.find(key);
1223 if (i != d->m.end()) {
1224
1225 T result(std::move(i->second));
1226 d->m.erase(i);
1227 return result;
1228 }
1229 #endif
1230 return T();
1231 }
1232
1233 bool contains(const Key &key) const
1234 {
1235 if (!d)
1236 return false;
1237 auto i = d->m.find(key);
1238 return i != d->m.end();
1239 }
1240
1241 bool contains(const Key &key, const T &value) const
1242 {
1243 return find(key, value) != end();
1244 }
1245
1246 Key key(const T &value, const Key &defaultKey = Key()) const
1247 {
1248 if (!d)
1249 return defaultKey;
1250
1251 return d->key(value, defaultKey);
1252 }
1253
1254 T value(const Key &key, const T &defaultValue = T()) const
1255 {
1256 if (!d)
1257 return defaultValue;
1258 const auto i = d->m.find(key);
1259 if (i != d->m.cend())
1260 return i->second;
1261 return defaultValue;
1262 }
1263
1264 QList<Key> keys() const
1265 {
1266 if (!d)
1267 return {};
1268 return d->keys();
1269 }
1270
1271 QList<Key> keys(const T &value) const
1272 {
1273 if (!d)
1274 return {};
1275 return d->keys(value);
1276 }
1277
1278 QList<Key> uniqueKeys() const
1279 {
1280 QList<Key> result;
1281 if (!d)
1282 return result;
1283
1284 result.reserve(size());
1285
1286 std::unique_copy(keyBegin(), keyEnd(),
1287 std::back_inserter(result));
1288
1289 result.shrink_to_fit();
1290 return result;
1291 }
1292
1293 QList<T> values() const
1294 {
1295 if (!d)
1296 return {};
1297 return d->values();
1298 }
1299
1300 QList<T> values(const Key &key) const
1301 {
1302 QList<T> result;
1303 const auto range = equal_range(key);
1304 result.reserve(std::distance(range.first, range.second));
1305 std::copy(range.first, range.second, std::back_inserter(result));
1306 return result;
1307 }
1308
1309 size_type count(const Key &key) const
1310 {
1311 if (!d)
1312 return 0;
1313 return d->count(key);
1314 }
1315
1316 size_type count(const Key &key, const T &value) const
1317 {
1318 if (!d)
1319 return 0;
1320
1321
1322 auto range = d->m.equal_range(key);
1323
1324 return size_type(std::count_if(range.first,
1325 range.second,
1326 MapData::valueIsEqualTo(value)));
1327 }
1328
1329 inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
1330 inline const Key &lastKey() const { Q_ASSERT(!isEmpty()); return std::next(constEnd(), -1).key(); }
1331
1332 inline T &first() { Q_ASSERT(!isEmpty()); return *begin(); }
1333 inline const T &first() const { Q_ASSERT(!isEmpty()); return *constBegin(); }
1334 inline T &last() { Q_ASSERT(!isEmpty()); return *std::next(end(), -1); }
1335 inline const T &last() const { Q_ASSERT(!isEmpty()); return *std::next(constEnd(), -1); }
1336
1337 class const_iterator;
1338
1339 class iterator
1340 {
1341 friend class QMultiMap<Key, T>;
1342 friend class const_iterator;
1343
1344 typename Map::iterator i;
1345 explicit iterator(typename Map::iterator it) : i(it) {}
1346 public:
1347 using iterator_category = std::bidirectional_iterator_tag;
1348 using difference_type = qptrdiff;
1349 using value_type = T;
1350 using pointer = T *;
1351 using reference = T &;
1352
1353 iterator() = default;
1354
1355 const Key &key() const { return i->first; }
1356 T &value() const { return i->second; }
1357 T &operator*() const { return i->second; }
1358 T *operator->() const { return &i->second; }
1359 friend bool operator==(const iterator &lhs, const iterator &rhs) { return lhs.i == rhs.i; }
1360 friend bool operator!=(const iterator &lhs, const iterator &rhs) { return lhs.i != rhs.i; }
1361
1362 iterator &operator++()
1363 {
1364 ++i;
1365 return *this;
1366 }
1367 iterator operator++(int)
1368 {
1369 iterator r = *this;
1370 ++i;
1371 return r;
1372 }
1373 iterator &operator--()
1374 {
1375 --i;
1376 return *this;
1377 }
1378 iterator operator--(int)
1379 {
1380 iterator r = *this;
1381 --i;
1382 return r;
1383 }
1384
1385 #if QT_DEPRECATED_SINCE(6, 0)
1386 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1387
1388 friend iterator operator+(iterator it, difference_type j) { return std::next(it, j); }
1389
1390 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1391
1392 friend iterator operator-(iterator it, difference_type j) { return std::prev(it, j); }
1393
1394 QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMultiMap iterators are not random access")
1395 iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
1396
1397 QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMultiMap iterators are not random access")
1398 iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
1399
1400 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1401
1402 friend iterator operator+(difference_type j, iterator it) { return std::next(it, j); }
1403
1404 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1405
1406 friend iterator operator-(difference_type j, iterator it) { return std::prev(it, j); }
1407 #endif
1408 };
1409
1410 class const_iterator
1411 {
1412 friend class QMultiMap<Key, T>;
1413 typename Map::const_iterator i;
1414 explicit const_iterator(typename Map::const_iterator it) : i(it) {}
1415
1416 public:
1417 using iterator_category = std::bidirectional_iterator_tag;
1418 using difference_type = qptrdiff;
1419 using value_type = T;
1420 using pointer = const T *;
1421 using reference = const T &;
1422
1423 const_iterator() = default;
1424 Q_IMPLICIT const_iterator(const iterator &o) : i(o.i) {}
1425
1426 const Key &key() const { return i->first; }
1427 const T &value() const { return i->second; }
1428 const T &operator*() const { return i->second; }
1429 const T *operator->() const { return &i->second; }
1430 friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i == rhs.i; }
1431 friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i != rhs.i; }
1432
1433 const_iterator &operator++()
1434 {
1435 ++i;
1436 return *this;
1437 }
1438 const_iterator operator++(int)
1439 {
1440 const_iterator r = *this;
1441 ++i;
1442 return r;
1443 }
1444 const_iterator &operator--()
1445 {
1446 --i;
1447 return *this;
1448 }
1449 const_iterator operator--(int)
1450 {
1451 const_iterator r = *this;
1452 --i;
1453 return r;
1454 }
1455
1456 #if QT_DEPRECATED_SINCE(6, 0)
1457 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1458
1459 friend const_iterator operator+(const_iterator it, difference_type j) { return std::next(it, j); }
1460
1461 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1462
1463 friend const_iterator operator-(const_iterator it, difference_type j) { return std::prev(it, j); }
1464
1465 QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMultiMap iterators are not random access")
1466 const_iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
1467
1468 QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMultiMap iterators are not random access")
1469 const_iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
1470
1471 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1472
1473 friend const_iterator operator+(difference_type j, const_iterator it) { return std::next(it, j); }
1474
1475 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1476
1477 friend const_iterator operator-(difference_type j, const_iterator it) { return std::prev(it, j); }
1478 #endif
1479 };
1480
1481 class key_iterator
1482 {
1483 const_iterator i;
1484
1485 public:
1486 typedef typename const_iterator::iterator_category iterator_category;
1487 typedef typename const_iterator::difference_type difference_type;
1488 typedef Key value_type;
1489 typedef const Key *pointer;
1490 typedef const Key &reference;
1491
1492 key_iterator() = default;
1493 explicit key_iterator(const_iterator o) : i(o) { }
1494
1495 const Key &operator*() const { return i.key(); }
1496 const Key *operator->() const { return &i.key(); }
1497 bool operator==(key_iterator o) const { return i == o.i; }
1498 bool operator!=(key_iterator o) const { return i != o.i; }
1499
1500 inline key_iterator &operator++() { ++i; return *this; }
1501 inline key_iterator operator++(int) { return key_iterator(i++);}
1502 inline key_iterator &operator--() { --i; return *this; }
1503 inline key_iterator operator--(int) { return key_iterator(i--); }
1504 const_iterator base() const { return i; }
1505 };
1506
1507 typedef QKeyValueIterator<const Key&, const T&, const_iterator> const_key_value_iterator;
1508 typedef QKeyValueIterator<const Key&, T&, iterator> key_value_iterator;
1509
1510
1511 iterator begin() { detach(); return iterator(d->m.begin()); }
1512 const_iterator begin() const { if (!d) return const_iterator(); return const_iterator(d->m.cbegin()); }
1513 const_iterator constBegin() const { return begin(); }
1514 const_iterator cbegin() const { return begin(); }
1515 iterator end() { detach(); return iterator(d->m.end()); }
1516 const_iterator end() const { if (!d) return const_iterator(); return const_iterator(d->m.end()); }
1517 const_iterator constEnd() const { return end(); }
1518 const_iterator cend() const { return end(); }
1519 key_iterator keyBegin() const { return key_iterator(begin()); }
1520 key_iterator keyEnd() const { return key_iterator(end()); }
1521 key_value_iterator keyValueBegin() { return key_value_iterator(begin()); }
1522 key_value_iterator keyValueEnd() { return key_value_iterator(end()); }
1523 const_key_value_iterator keyValueBegin() const { return const_key_value_iterator(begin()); }
1524 const_key_value_iterator constKeyValueBegin() const { return const_key_value_iterator(begin()); }
1525 const_key_value_iterator keyValueEnd() const { return const_key_value_iterator(end()); }
1526 const_key_value_iterator constKeyValueEnd() const { return const_key_value_iterator(end()); }
1527 auto asKeyValueRange() & { return QtPrivate::QKeyValueRange<QMultiMap &>(*this); }
1528 auto asKeyValueRange() const & { return QtPrivate::QKeyValueRange<const QMultiMap &>(*this); }
1529 auto asKeyValueRange() && { return QtPrivate::QKeyValueRange<QMultiMap>(std::move(*this)); }
1530 auto asKeyValueRange() const && { return QtPrivate::QKeyValueRange<QMultiMap>(std::move(*this)); }
1531
1532 iterator erase(const_iterator it)
1533 {
1534 return erase(it, std::next(it));
1535 }
1536
1537 iterator erase(const_iterator afirst, const_iterator alast)
1538 {
1539 if (!d)
1540 return iterator();
1541
1542 if (!d.isShared())
1543 return iterator(d->m.erase(afirst.i, alast.i));
1544
1545 auto result = d->erase(afirst.i, alast.i);
1546 d.reset(result.data);
1547 return iterator(result.it);
1548 }
1549
1550
1551 typedef iterator Iterator;
1552 typedef const_iterator ConstIterator;
1553
1554 size_type count() const
1555 {
1556 return size();
1557 }
1558
1559 iterator find(const Key &key)
1560 {
1561 const auto hold = referenceHoldingDetach();
1562 return iterator(d->m.find(key));
1563 }
1564
1565 const_iterator find(const Key &key) const
1566 {
1567 if (!d)
1568 return const_iterator();
1569 return const_iterator(d->m.find(key));
1570 }
1571
1572 const_iterator constFind(const Key &key) const
1573 {
1574 return find(key);
1575 }
1576
1577 iterator find(const Key &key, const T &value)
1578 {
1579 const auto hold = referenceHoldingDetach();
1580
1581 auto range = d->m.equal_range(key);
1582 auto i = std::find_if(range.first, range.second,
1583 MapData::valueIsEqualTo(value));
1584
1585 if (i != range.second)
1586 return iterator(i);
1587 return iterator(d->m.end());
1588 }
1589
1590 const_iterator find(const Key &key, const T &value) const
1591 {
1592 if (!d)
1593 return const_iterator();
1594
1595 auto range = d->m.equal_range(key);
1596 auto i = std::find_if(range.first, range.second,
1597 MapData::valueIsEqualTo(value));
1598
1599 if (i != range.second)
1600 return const_iterator(i);
1601 return const_iterator(d->m.end());
1602 }
1603
1604 const_iterator constFind(const Key &key, const T &value) const
1605 {
1606 return find(key, value);
1607 }
1608
1609 iterator lowerBound(const Key &key)
1610 {
1611 const auto hold = referenceHoldingDetach();
1612 return iterator(d->m.lower_bound(key));
1613 }
1614
1615 const_iterator lowerBound(const Key &key) const
1616 {
1617 if (!d)
1618 return const_iterator();
1619 return const_iterator(d->m.lower_bound(key));
1620 }
1621
1622 iterator upperBound(const Key &key)
1623 {
1624 const auto hold = referenceHoldingDetach();
1625 return iterator(d->m.upper_bound(key));
1626 }
1627
1628 const_iterator upperBound(const Key &key) const
1629 {
1630 if (!d)
1631 return const_iterator();
1632 return const_iterator(d->m.upper_bound(key));
1633 }
1634
1635 iterator insert(const Key &key, const T &value)
1636 {
1637 const auto hold = referenceHoldingDetach();
1638
1639
1640 auto i = d->m.lower_bound(key);
1641 return iterator(d->m.insert(i, {key, value}));
1642 }
1643
1644 iterator insert(const_iterator pos, const Key &key, const T &value)
1645 {
1646 if (!d) {
1647 d.reset(new MapData);
1648 return iterator(d->m.insert({ key, value }));
1649 } else if (d.isShared()) {
1650 auto posDistance = std::distance(d->m.cbegin(), pos.i);
1651 auto hold = referenceHoldingDetach();
1652 auto dpos = std::next(d->m.cbegin(), posDistance);
1653 return iterator(d->m.insert(dpos, {key, value}));
1654 }
1655
1656 return iterator(d->m.insert(pos.i, {key, value}));
1657 }
1658
1659 #if QT_DEPRECATED_SINCE(6, 0)
1660 QT_DEPRECATED_VERSION_X_6_0("Use insert() instead")
1661 iterator insertMulti(const Key &key, const T &value)
1662 {
1663 return insert(key, value);
1664 }
1665 QT_DEPRECATED_VERSION_X_6_0("Use insert() instead")
1666 iterator insertMulti(const_iterator pos, const Key &key, const T &value)
1667 {
1668 return insert(pos, key, value);
1669 }
1670
1671 QT_DEPRECATED_VERSION_X_6_0("Use unite() instead")
1672 void insert(const QMultiMap<Key, T> &map)
1673 {
1674 unite(map);
1675 }
1676
1677 QT_DEPRECATED_VERSION_X_6_0("Use unite() instead")
1678 void insert(QMultiMap<Key, T> &&map)
1679 {
1680 unite(std::move(map));
1681 }
1682 #endif
1683
1684 iterator replace(const Key &key, const T &value)
1685 {
1686 if (!d) {
1687 d.reset(new MapData);
1688 return iterator(d->m.insert({ key, value }));
1689 }
1690 auto i = d->m.find(key);
1691 if (d.isShared()) {
1692 const auto hold = referenceHoldingDetachExceptFor(i);
1693 return iterator(d->m.insert({ key, value }));
1694 }
1695
1696
1697
1698 if (i != d->m.end())
1699 i->second = value;
1700 else
1701 i = d->m.insert({key, value});
1702
1703 return iterator(i);
1704 }
1705
1706
1707 [[nodiscard]]
1708 inline bool empty() const { return isEmpty(); }
1709
1710 std::pair<iterator, iterator> equal_range(const Key &akey)
1711 {
1712 const auto hold = referenceHoldingDetach();
1713 auto result = d->m.equal_range(akey);
1714 return {iterator(result.first), iterator(result.second)};
1715 }
1716
1717 std::pair<const_iterator, const_iterator> equal_range(const Key &akey) const
1718 {
1719 if (!d)
1720 return {};
1721 auto result = d->m.equal_range(akey);
1722 return {const_iterator(result.first), const_iterator(result.second)};
1723 }
1724
1725 QMultiMap &unite(const QMultiMap &other)
1726 {
1727 if (other.isEmpty())
1728 return *this;
1729
1730 detach();
1731
1732 auto copy = other.d->m;
1733 #ifdef __cpp_lib_node_extract
1734 copy.merge(std::move(d->m));
1735 #else
1736 copy.insert(std::make_move_iterator(d->m.begin()),
1737 std::make_move_iterator(d->m.end()));
1738 #endif
1739 d->m = std::move(copy);
1740 return *this;
1741 }
1742
1743 QMultiMap &unite(QMultiMap<Key, T> &&other)
1744 {
1745 if (!other.d || other.d->m.empty())
1746 return *this;
1747
1748 if (other.d.isShared()) {
1749
1750 unite(other);
1751 return *this;
1752 }
1753
1754 detach();
1755
1756 #ifdef __cpp_lib_node_extract
1757 other.d->m.merge(std::move(d->m));
1758 #else
1759 other.d->m.insert(std::make_move_iterator(d->m.begin()),
1760 std::make_move_iterator(d->m.end()));
1761 #endif
1762 *this = std::move(other);
1763 return *this;
1764 }
1765 };
1766
1767 Q_DECLARE_ASSOCIATIVE_ITERATOR(MultiMap)
1768 Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(MultiMap)
1769
1770 template <typename Key, typename T>
1771 QMultiMap<Key, T> operator+(const QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
1772 {
1773 auto result = lhs;
1774 result += rhs;
1775 return result;
1776 }
1777
1778 template <typename Key, typename T>
1779 QMultiMap<Key, T> operator+=(QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
1780 {
1781 return lhs.unite(rhs);
1782 }
1783
1784 template <typename Key, typename T, typename Predicate>
1785 qsizetype erase_if(QMultiMap<Key, T> &map, Predicate pred)
1786 {
1787 return QtPrivate::associative_erase_if(map, pred);
1788 }
1789
1790 QT_END_NAMESPACE
1791
1792 #endif