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