File indexing completed on 2026-10-31 09:40:53
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
0967
0968
0969
0970
0971
0972 auto findIteratorByKey(const Key &key) const
0973 {
0974 auto i = d->m.lower_bound(key);
0975 const auto &cmp = d->m.key_comp();
0976 if (i != d->m.end() && !cmp(key, i->first))
0977 return i;
0978 return d->m.end();
0979 }
0980 auto findIteratorByKey(const Key &key)
0981 {
0982 auto i = d->m.lower_bound(key);
0983 const auto &cmp = d->m.key_comp();
0984 if (i != d->m.end() && !cmp(key, i->first))
0985 return i;
0986 return d->m.end();
0987 }
0988
0989 public:
0990 using key_type = Key;
0991 using mapped_type = T;
0992 using difference_type = qptrdiff;
0993 using size_type = qsizetype;
0994
0995 QMultiMap() = default;
0996
0997
0998
0999 QMultiMap(std::initializer_list<std::pair<Key,T>> list)
1000 {
1001 for (auto &p : list)
1002 insert(p.first, p.second);
1003 }
1004
1005 void swap(QMultiMap<Key, T> &other) noexcept
1006 {
1007 d.swap(other.d);
1008 }
1009
1010 explicit QMultiMap(const QMap<Key, T> &other)
1011 : d(other.isEmpty() ? nullptr : new MapData)
1012 {
1013 if (d) {
1014 Q_ASSERT(other.d);
1015 d->m.insert(other.d->m.begin(),
1016 other.d->m.end());
1017 }
1018 }
1019
1020 explicit QMultiMap(QMap<Key, T> &&other)
1021 : d(other.isEmpty() ? nullptr : new MapData)
1022 {
1023 if (d) {
1024 Q_ASSERT(other.d);
1025 if (other.d.isShared()) {
1026 d->m.insert(other.d->m.begin(),
1027 other.d->m.end());
1028 } else {
1029 #ifdef __cpp_lib_node_extract
1030 d->m.merge(std::move(other.d->m));
1031 #else
1032 d->m.insert(std::make_move_iterator(other.d->m.begin()),
1033 std::make_move_iterator(other.d->m.end()));
1034 #endif
1035 }
1036 }
1037 }
1038
1039 explicit QMultiMap(const std::multimap<Key, T> &other)
1040 : d(other.empty() ? nullptr : new MapData(other))
1041 {
1042 }
1043
1044 explicit QMultiMap(std::multimap<Key, T> &&other)
1045 : d(other.empty() ? nullptr : new MapData(std::move(other)))
1046 {
1047 }
1048
1049
1050 Q_DECL_DEPRECATED_X("Use toStdMultiMap instead")
1051 std::multimap<Key, T> toStdMap() const
1052 {
1053 return toStdMultiMap();
1054 }
1055
1056 std::multimap<Key, T> toStdMultiMap() const &
1057 {
1058 if (d)
1059 return d->m;
1060 return {};
1061 }
1062
1063 std::multimap<Key, T> toStdMultiMap() &&
1064 {
1065 if (d) {
1066 if (d.isShared())
1067 return d->m;
1068 else
1069 return std::move(d->m);
1070 }
1071
1072 return {};
1073 }
1074
1075 #ifndef Q_QDOC
1076 private:
1077 template <typename AKey = Key, typename AT = T,
1078 QTypeTraits::compare_eq_result_container<QMultiMap, AKey, AT> = true>
1079 friend bool comparesEqual(const QMultiMap &lhs, const QMultiMap &rhs)
1080 {
1081 if (lhs.d == rhs.d)
1082 return true;
1083 if (!lhs.d)
1084 return rhs == lhs;
1085 Q_ASSERT(lhs.d);
1086 return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
1087 }
1088 QT_DECLARE_EQUALITY_OPERATORS_HELPER(QMultiMap, QMultiMap, , noexcept(false),
1089 template <typename AKey = Key, typename AT = T,
1090 QTypeTraits::compare_eq_result_container<QMultiMap, AKey, AT> = true>)
1091
1092 public:
1093 #else
1094 friend bool operator==(const QMultiMap &lhs, const QMultiMap &rhs);
1095 friend bool operator!=(const QMultiMap &lhs, const QMultiMap &rhs);
1096 #endif
1097
1098 size_type size() const { return d ? size_type(d->m.size()) : size_type(0); }
1099
1100 [[nodiscard]]
1101 bool isEmpty() const { return d ? d->m.empty() : true; }
1102
1103 void detach()
1104 {
1105 if (d)
1106 d.detach();
1107 else
1108 d.reset(new MapData);
1109 }
1110
1111
1112
1113 [[nodiscard]] QMultiMap referenceHoldingDetach()
1114 {
1115 if (!d) {
1116 d.reset(new MapData);
1117 } else if (d.isShared()) {
1118 auto hold = *this;
1119 d.detach();
1120 return hold;
1121 }
1122 return {};
1123 }
1124
1125
1126 [[nodiscard]] QMultiMap referenceHoldingDetachExceptFor(const typename Map::iterator &skipit)
1127 {
1128 Q_ASSERT(d.isShared());
1129 auto hold = *this;
1130 QtPrivate::QExplicitlySharedDataPointerV2<MapData> newData(new MapData);
1131 newData->copyExceptFor(d->m, skipit);
1132 d.swap(newData);
1133 return hold;
1134 }
1135
1136 bool isDetached() const noexcept
1137 {
1138 return d ? !d.isShared() : false;
1139 }
1140
1141 bool isSharedWith(const QMultiMap<Key, T> &other) const noexcept
1142 {
1143 return d == other.d;
1144 }
1145
1146 void clear()
1147 {
1148 if (!d)
1149 return;
1150
1151 if (!d.isShared())
1152 d->m.clear();
1153 else
1154 d.reset();
1155 }
1156
1157 size_type remove(const Key &key)
1158 {
1159 if (!d)
1160 return 0;
1161
1162 if (!d.isShared())
1163 return size_type(d->m.erase(key));
1164
1165 MapData *newData = new MapData;
1166 size_type result = newData->copyIfNotEquivalentTo(d->m, key);
1167
1168 d.reset(newData);
1169
1170 return result;
1171 }
1172
1173 size_type remove(const Key &key, const T &value)
1174 {
1175 if (!d)
1176 return 0;
1177
1178 size_type result = 0;
1179 const auto &keyCompare = d->m.key_comp();
1180
1181 if (d.isShared()) {
1182 QtPrivate::QExplicitlySharedDataPointerV2<MapData> newData(new MapData);
1183 const auto keep = [&newData](auto it) { newData->m.insert(newData->m.cend(), *it); };
1184
1185 auto it = d->m.cbegin();
1186 const auto end = d->m.cend();
1187 for (; it != end && keyCompare(it->first, key); ++it)
1188 keep(it);
1189
1190 for (; it != end && !keyCompare(key, it->first); ++it) {
1191 if (!(it->second == value))
1192 keep(it);
1193 else
1194 ++result;
1195 }
1196 for (; it != end; ++it)
1197 keep(it);
1198
1199 d.swap(newData);
1200 return result;
1201 }
1202
1203
1204
1205 auto [i, e] = d->m.equal_range(key);
1206 if (i == e)
1207 return result;
1208
1209
1210
1211 const T valueCopy = value;
1212 while (i != e) {
1213 if (i->second == valueCopy) {
1214 i = d->m.erase(i);
1215 ++result;
1216 } else {
1217 ++i;
1218 }
1219 }
1220
1221 return result;
1222 }
1223
1224 template <typename Predicate>
1225 size_type removeIf(Predicate pred)
1226 {
1227 return QtPrivate::associative_erase_if(*this, pred);
1228 }
1229
1230 T take(const Key &key)
1231 {
1232 if (!d)
1233 return T();
1234
1235 auto i = findIteratorByKey(key);
1236 if (d.isShared()) {
1237 if (i == d->m.end()) {
1238
1239 detach();
1240 return T();
1241 }
1242 const auto hold = referenceHoldingDetachExceptFor(i);
1243 return i->second;
1244 }
1245
1246 if (i == d->m.end())
1247 return T();
1248
1249 #ifdef __cpp_lib_node_extract
1250 return d->m.extract(i).mapped();
1251 #else
1252
1253 T result(std::move(i->second));
1254 d->m.erase(i);
1255 return result;
1256 #endif
1257 }
1258
1259 bool contains(const Key &key) const
1260 {
1261 if (!d)
1262 return false;
1263 auto i = d->m.find(key);
1264 return i != d->m.end();
1265 }
1266
1267 bool contains(const Key &key, const T &value) const
1268 {
1269 return find(key, value) != end();
1270 }
1271
1272 Key key(const T &value, const Key &defaultKey = Key()) const
1273 {
1274 if (!d)
1275 return defaultKey;
1276
1277 return d->key(value, defaultKey);
1278 }
1279
1280 T value(const Key &key, const T &defaultValue = T()) const
1281 {
1282 if (!d)
1283 return defaultValue;
1284 auto i = findIteratorByKey(key);
1285 if (i != d->m.cend())
1286 return i->second;
1287 return defaultValue;
1288 }
1289
1290 QList<Key> keys() const
1291 {
1292 if (!d)
1293 return {};
1294 return d->keys();
1295 }
1296
1297 QList<Key> keys(const T &value) const
1298 {
1299 if (!d)
1300 return {};
1301 return d->keys(value);
1302 }
1303
1304 QList<Key> uniqueKeys() const
1305 {
1306 QList<Key> result;
1307 if (!d)
1308 return result;
1309
1310 result.reserve(size());
1311
1312 std::unique_copy(keyBegin(), keyEnd(),
1313 std::back_inserter(result));
1314
1315 result.shrink_to_fit();
1316 return result;
1317 }
1318
1319 QList<T> values() const
1320 {
1321 if (!d)
1322 return {};
1323 return d->values();
1324 }
1325
1326 QList<T> values(const Key &key) const
1327 {
1328 QList<T> result;
1329 const auto range = equal_range(key);
1330 result.reserve(std::distance(range.first, range.second));
1331 std::copy(range.first, range.second, std::back_inserter(result));
1332 return result;
1333 }
1334
1335 size_type count(const Key &key) const
1336 {
1337 if (!d)
1338 return 0;
1339 return d->count(key);
1340 }
1341
1342 size_type count(const Key &key, const T &value) const
1343 {
1344 if (!d)
1345 return 0;
1346
1347
1348 auto range = d->m.equal_range(key);
1349
1350 return size_type(std::count_if(range.first,
1351 range.second,
1352 MapData::valueIsEqualTo(value)));
1353 }
1354
1355 inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
1356 inline const Key &lastKey() const { Q_ASSERT(!isEmpty()); return std::next(constEnd(), -1).key(); }
1357
1358 inline T &first() { Q_ASSERT(!isEmpty()); return *begin(); }
1359 inline const T &first() const { Q_ASSERT(!isEmpty()); return *constBegin(); }
1360 inline T &last() { Q_ASSERT(!isEmpty()); return *std::next(end(), -1); }
1361 inline const T &last() const { Q_ASSERT(!isEmpty()); return *std::next(constEnd(), -1); }
1362
1363 class const_iterator;
1364
1365 class iterator
1366 {
1367 friend class QMultiMap<Key, T>;
1368 friend class const_iterator;
1369
1370 typename Map::iterator i;
1371 explicit iterator(typename Map::iterator it) : i(it) {}
1372 public:
1373 using iterator_category = std::bidirectional_iterator_tag;
1374 using difference_type = qptrdiff;
1375 using value_type = T;
1376 using pointer = T *;
1377 using reference = T &;
1378
1379 iterator() = default;
1380
1381 const Key &key() const { return i->first; }
1382 T &value() const { return i->second; }
1383 T &operator*() const { return i->second; }
1384 T *operator->() const { return &i->second; }
1385 friend bool operator==(const iterator &lhs, const iterator &rhs) { return lhs.i == rhs.i; }
1386 friend bool operator!=(const iterator &lhs, const iterator &rhs) { return lhs.i != rhs.i; }
1387
1388 iterator &operator++()
1389 {
1390 ++i;
1391 return *this;
1392 }
1393 iterator operator++(int)
1394 {
1395 iterator r = *this;
1396 ++i;
1397 return r;
1398 }
1399 iterator &operator--()
1400 {
1401 --i;
1402 return *this;
1403 }
1404 iterator operator--(int)
1405 {
1406 iterator r = *this;
1407 --i;
1408 return r;
1409 }
1410
1411 #if QT_DEPRECATED_SINCE(6, 0)
1412 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1413
1414 friend iterator operator+(iterator it, difference_type j) { return std::next(it, j); }
1415
1416 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1417
1418 friend iterator operator-(iterator it, difference_type j) { return std::prev(it, j); }
1419
1420 QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMultiMap iterators are not random access")
1421 iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
1422
1423 QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMultiMap iterators are not random access")
1424 iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
1425
1426 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1427
1428 friend iterator operator+(difference_type j, iterator it) { return std::next(it, j); }
1429
1430 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1431
1432 friend iterator operator-(difference_type j, iterator it) { return std::prev(it, j); }
1433 #endif
1434 };
1435
1436 class const_iterator
1437 {
1438 friend class QMultiMap<Key, T>;
1439 typename Map::const_iterator i;
1440 explicit const_iterator(typename Map::const_iterator it) : i(it) {}
1441
1442 public:
1443 using iterator_category = std::bidirectional_iterator_tag;
1444 using difference_type = qptrdiff;
1445 using value_type = T;
1446 using pointer = const T *;
1447 using reference = const T &;
1448
1449 const_iterator() = default;
1450 Q_IMPLICIT const_iterator(const iterator &o) : i(o.i) {}
1451
1452 const Key &key() const { return i->first; }
1453 const T &value() const { return i->second; }
1454 const T &operator*() const { return i->second; }
1455 const T *operator->() const { return &i->second; }
1456 friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i == rhs.i; }
1457 friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i != rhs.i; }
1458
1459 const_iterator &operator++()
1460 {
1461 ++i;
1462 return *this;
1463 }
1464 const_iterator operator++(int)
1465 {
1466 const_iterator r = *this;
1467 ++i;
1468 return r;
1469 }
1470 const_iterator &operator--()
1471 {
1472 --i;
1473 return *this;
1474 }
1475 const_iterator operator--(int)
1476 {
1477 const_iterator r = *this;
1478 --i;
1479 return r;
1480 }
1481
1482 #if QT_DEPRECATED_SINCE(6, 0)
1483 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1484
1485 friend const_iterator operator+(const_iterator it, difference_type j) { return std::next(it, j); }
1486
1487 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1488
1489 friend const_iterator operator-(const_iterator it, difference_type j) { return std::prev(it, j); }
1490
1491 QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMultiMap iterators are not random access")
1492 const_iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
1493
1494 QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMultiMap iterators are not random access")
1495 const_iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
1496
1497 QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1498
1499 friend const_iterator operator+(difference_type j, const_iterator it) { return std::next(it, j); }
1500
1501 QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1502
1503 friend const_iterator operator-(difference_type j, const_iterator it) { return std::prev(it, j); }
1504 #endif
1505 };
1506
1507 class key_iterator
1508 {
1509 const_iterator i;
1510
1511 public:
1512 typedef typename const_iterator::iterator_category iterator_category;
1513 typedef typename const_iterator::difference_type difference_type;
1514 typedef Key value_type;
1515 typedef const Key *pointer;
1516 typedef const Key &reference;
1517
1518 key_iterator() = default;
1519 explicit key_iterator(const_iterator o) : i(o) { }
1520
1521 const Key &operator*() const { return i.key(); }
1522 const Key *operator->() const { return &i.key(); }
1523 bool operator==(key_iterator o) const { return i == o.i; }
1524 bool operator!=(key_iterator o) const { return i != o.i; }
1525
1526 inline key_iterator &operator++() { ++i; return *this; }
1527 inline key_iterator operator++(int) { return key_iterator(i++);}
1528 inline key_iterator &operator--() { --i; return *this; }
1529 inline key_iterator operator--(int) { return key_iterator(i--); }
1530 const_iterator base() const { return i; }
1531 };
1532
1533 typedef QKeyValueIterator<const Key&, const T&, const_iterator> const_key_value_iterator;
1534 typedef QKeyValueIterator<const Key&, T&, iterator> key_value_iterator;
1535
1536
1537 iterator begin() { detach(); return iterator(d->m.begin()); }
1538 const_iterator begin() const { if (!d) return const_iterator(); return const_iterator(d->m.cbegin()); }
1539 const_iterator constBegin() const { return begin(); }
1540 const_iterator cbegin() const { return begin(); }
1541 iterator end() { detach(); return iterator(d->m.end()); }
1542 const_iterator end() const { if (!d) return const_iterator(); return const_iterator(d->m.end()); }
1543 const_iterator constEnd() const { return end(); }
1544 const_iterator cend() const { return end(); }
1545 key_iterator keyBegin() const { return key_iterator(begin()); }
1546 key_iterator keyEnd() const { return key_iterator(end()); }
1547 key_value_iterator keyValueBegin() { return key_value_iterator(begin()); }
1548 key_value_iterator keyValueEnd() { return key_value_iterator(end()); }
1549 const_key_value_iterator keyValueBegin() const { return const_key_value_iterator(begin()); }
1550 const_key_value_iterator constKeyValueBegin() const { return const_key_value_iterator(begin()); }
1551 const_key_value_iterator keyValueEnd() const { return const_key_value_iterator(end()); }
1552 const_key_value_iterator constKeyValueEnd() const { return const_key_value_iterator(end()); }
1553 auto asKeyValueRange() & { return QtPrivate::QKeyValueRange<QMultiMap &>(*this); }
1554 auto asKeyValueRange() const & { return QtPrivate::QKeyValueRange<const QMultiMap &>(*this); }
1555 auto asKeyValueRange() && { return QtPrivate::QKeyValueRange<QMultiMap>(std::move(*this)); }
1556 auto asKeyValueRange() const && { return QtPrivate::QKeyValueRange<QMultiMap>(std::move(*this)); }
1557
1558 iterator erase(const_iterator it)
1559 {
1560 return erase(it, std::next(it));
1561 }
1562
1563 iterator erase(const_iterator afirst, const_iterator alast)
1564 {
1565 if (!d)
1566 return iterator();
1567
1568 if (!d.isShared())
1569 return iterator(d->m.erase(afirst.i, alast.i));
1570
1571 auto result = d->erase(afirst.i, alast.i);
1572 d.reset(result.data);
1573 return iterator(result.it);
1574 }
1575
1576
1577 typedef iterator Iterator;
1578 typedef const_iterator ConstIterator;
1579
1580 size_type count() const
1581 {
1582 return size();
1583 }
1584
1585 iterator find(const Key &key)
1586 {
1587 const auto hold = referenceHoldingDetach();
1588 return iterator(findIteratorByKey(key));
1589 }
1590
1591 const_iterator find(const Key &key) const
1592 {
1593 if (!d)
1594 return const_iterator();
1595 return const_iterator(findIteratorByKey(key));
1596 }
1597
1598 const_iterator constFind(const Key &key) const
1599 {
1600 return find(key);
1601 }
1602
1603 iterator find(const Key &key, const T &value)
1604 {
1605 const auto hold = referenceHoldingDetach();
1606
1607 auto range = d->m.equal_range(key);
1608 auto i = std::find_if(range.first, range.second,
1609 MapData::valueIsEqualTo(value));
1610
1611 if (i != range.second)
1612 return iterator(i);
1613 return iterator(d->m.end());
1614 }
1615
1616 const_iterator find(const Key &key, const T &value) const
1617 {
1618 if (!d)
1619 return const_iterator();
1620
1621 auto range = d->m.equal_range(key);
1622 auto i = std::find_if(range.first, range.second,
1623 MapData::valueIsEqualTo(value));
1624
1625 if (i != range.second)
1626 return const_iterator(i);
1627 return const_iterator(d->m.end());
1628 }
1629
1630 const_iterator constFind(const Key &key, const T &value) const
1631 {
1632 return find(key, value);
1633 }
1634
1635 iterator lowerBound(const Key &key)
1636 {
1637 const auto hold = referenceHoldingDetach();
1638 return iterator(d->m.lower_bound(key));
1639 }
1640
1641 const_iterator lowerBound(const Key &key) const
1642 {
1643 if (!d)
1644 return const_iterator();
1645 return const_iterator(d->m.lower_bound(key));
1646 }
1647
1648 iterator upperBound(const Key &key)
1649 {
1650 const auto hold = referenceHoldingDetach();
1651 return iterator(d->m.upper_bound(key));
1652 }
1653
1654 const_iterator upperBound(const Key &key) const
1655 {
1656 if (!d)
1657 return const_iterator();
1658 return const_iterator(d->m.upper_bound(key));
1659 }
1660
1661 iterator insert(const Key &key, const T &value)
1662 {
1663 const auto hold = referenceHoldingDetach();
1664
1665
1666 auto i = d->m.lower_bound(key);
1667 return iterator(d->m.insert(i, {key, value}));
1668 }
1669
1670 iterator insert(const_iterator pos, const Key &key, const T &value)
1671 {
1672 if (!d) {
1673 d.reset(new MapData);
1674 return iterator(d->m.insert({ key, value }));
1675 } else if (d.isShared()) {
1676 auto posDistance = std::distance(d->m.cbegin(), pos.i);
1677 auto hold = referenceHoldingDetach();
1678 auto dpos = std::next(d->m.cbegin(), posDistance);
1679 return iterator(d->m.insert(dpos, {key, value}));
1680 }
1681
1682 return iterator(d->m.insert(pos.i, {key, value}));
1683 }
1684
1685 #if QT_DEPRECATED_SINCE(6, 0)
1686 QT_DEPRECATED_VERSION_X_6_0("Use insert() instead")
1687 iterator insertMulti(const Key &key, const T &value)
1688 {
1689 return insert(key, value);
1690 }
1691 QT_DEPRECATED_VERSION_X_6_0("Use insert() instead")
1692 iterator insertMulti(const_iterator pos, const Key &key, const T &value)
1693 {
1694 return insert(pos, key, value);
1695 }
1696
1697 QT_DEPRECATED_VERSION_X_6_0("Use unite() instead")
1698 void insert(const QMultiMap<Key, T> &map)
1699 {
1700 unite(map);
1701 }
1702
1703 QT_DEPRECATED_VERSION_X_6_0("Use unite() instead")
1704 void insert(QMultiMap<Key, T> &&map)
1705 {
1706 unite(std::move(map));
1707 }
1708 #endif
1709
1710 iterator replace(const Key &key, const T &value)
1711 {
1712 if (!d) {
1713 d.reset(new MapData);
1714 return iterator(d->m.insert({ key, value }));
1715 }
1716 auto i = findIteratorByKey(key);
1717 if (d.isShared()) {
1718 const auto hold = referenceHoldingDetachExceptFor(i);
1719 return iterator(d->m.insert({ key, value }));
1720 }
1721
1722
1723
1724 if (i != d->m.end())
1725 i->second = value;
1726 else
1727 i = d->m.insert({key, value});
1728
1729 return iterator(i);
1730 }
1731
1732
1733 [[nodiscard]]
1734 inline bool empty() const { return isEmpty(); }
1735
1736 std::pair<iterator, iterator> equal_range(const Key &akey)
1737 {
1738 const auto hold = referenceHoldingDetach();
1739 auto result = d->m.equal_range(akey);
1740 return {iterator(result.first), iterator(result.second)};
1741 }
1742
1743 std::pair<const_iterator, const_iterator> equal_range(const Key &akey) const
1744 {
1745 if (!d)
1746 return {};
1747 auto result = d->m.equal_range(akey);
1748 return {const_iterator(result.first), const_iterator(result.second)};
1749 }
1750
1751 QMultiMap &unite(const QMultiMap &other)
1752 {
1753 if (other.isEmpty())
1754 return *this;
1755
1756 detach();
1757
1758 auto copy = other.d->m;
1759 #ifdef __cpp_lib_node_extract
1760 copy.merge(std::move(d->m));
1761 #else
1762 copy.insert(std::make_move_iterator(d->m.begin()),
1763 std::make_move_iterator(d->m.end()));
1764 #endif
1765 d->m = std::move(copy);
1766 return *this;
1767 }
1768
1769 QMultiMap &unite(QMultiMap<Key, T> &&other)
1770 {
1771 if (!other.d || other.d->m.empty())
1772 return *this;
1773
1774 if (other.d.isShared()) {
1775
1776 unite(other);
1777 return *this;
1778 }
1779
1780 detach();
1781
1782 #ifdef __cpp_lib_node_extract
1783 other.d->m.merge(std::move(d->m));
1784 #else
1785 other.d->m.insert(std::make_move_iterator(d->m.begin()),
1786 std::make_move_iterator(d->m.end()));
1787 #endif
1788 *this = std::move(other);
1789 return *this;
1790 }
1791 };
1792
1793 Q_DECLARE_ASSOCIATIVE_ITERATOR(MultiMap)
1794 Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(MultiMap)
1795
1796 template <typename Key, typename T>
1797 QMultiMap<Key, T> operator+(const QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
1798 {
1799 auto result = lhs;
1800 result += rhs;
1801 return result;
1802 }
1803
1804 template <typename Key, typename T>
1805 QMultiMap<Key, T> operator+=(QMultiMap<Key, T> &lhs, const QMultiMap<Key, T> &rhs)
1806 {
1807 return lhs.unite(rhs);
1808 }
1809
1810 template <typename Key, typename T, typename Predicate>
1811 qsizetype erase_if(QMultiMap<Key, T> &map, Predicate pred)
1812 {
1813 return QtPrivate::associative_erase_if(map, pred);
1814 }
1815
1816 QT_END_NAMESPACE
1817
1818 #endif