Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/QtCore/qmap.h was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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