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
0002
0003
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
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
0050
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
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
0074
0075
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
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
0139
0140
0141
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
0158 while (i != first) {
0159 result.it = result.data->m.insert(newDataEnd, *i);
0160 ++i;
0161 }
0162
0163
0164 while (i != last)
0165 ++i;
0166
0167
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
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
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
0261 #else
0262 friend bool operator==(const QMap &lhs, const QMap &rhs);
0263 friend bool operator!=(const QMap &lhs, const QMap &rhs);
0264 #endif
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;
0281 }
0282
0283 bool isSharedWith(const QMap<Key, T> &other) const noexcept
0284 {
0285 return d == other.d;
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();
0327
0328
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();
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
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
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
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
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
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
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
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
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
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
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
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();
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();
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();
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();
0690
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
0698 typename Map::const_iterator dpos;
0699 const auto copy = d.isShared() ? *this : QMap();
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
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
0724
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
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
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
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();
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
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
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
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
0906 #else
0907 friend bool operator==(const QMultiMap &lhs, const QMultiMap &rhs);
0908 friend bool operator!=(const QMultiMap &lhs, const QMultiMap &rhs);
0909 #endif
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;
0926 }
0927
0928 bool isSharedWith(const QMultiMap<Key, T> &other) const noexcept
0929 {
0930 return d == other.d;
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
0966
0967
0968 const Key keyCopy = key;
0969 const T valueCopy = value;
0970
0971
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();
1004
1005
1006
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
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
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
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
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
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
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
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
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
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
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
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();
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();
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();
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();
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();
1428 detach();
1429
1430
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();
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();
1477
1478
1479 detach();
1480
1481
1482
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
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();
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
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