QtBase  v6.3.1
qmap.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
4 ** Copyright (C) 2021 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtCore module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #ifndef QMAP_H
42 #define QMAP_H
43 
44 #include <QtCore/qiterator.h>
45 #include <QtCore/qlist.h>
46 #include <QtCore/qrefcount.h>
47 #include <QtCore/qpair.h>
48 #include <QtCore/qshareddata.h>
49 #include <QtCore/qshareddata_impl.h>
50 
51 #include <functional>
52 #include <initializer_list>
53 #include <map>
54 #include <algorithm>
55 
57 
58 // common code shared between QMap and QMultimap
59 template <typename AMap>
60 class QMapData : public QSharedData
61 {
62 public:
63  using Map = AMap;
64  using Key = typename Map::key_type;
65  using T = typename Map::mapped_type;
66  using value_type = typename Map::value_type;
67  using size_type = typename Map::size_type;
68  using iterator = typename Map::iterator;
70 
71  static_assert(std::is_nothrow_destructible_v<Key>, "Types with throwing destructors are not supported in Qt containers.");
72  static_assert(std::is_nothrow_destructible_v<T>, "Types with throwing destructors are not supported in Qt containers.");
73 
74  Map m;
75 
76  QMapData() = default;
77  explicit QMapData(const Map &other)
78  : m(other)
79  {}
80 
81  explicit QMapData(Map &&other)
82  : m(std::move(other))
83  {}
84 
85  // used in remove(); copies from source all the values not matching key.
86  // returns how many were NOT copied (removed).
88  {
89  Q_ASSERT(m.empty());
90 
91  size_type result = 0;
92  const auto &keyCompare = source.key_comp();
93  const auto filter = [&result, &key, &keyCompare](const auto &v)
94  {
95  if (!keyCompare(key, v.first) && !keyCompare(v.first, key)) {
96  // keys are equivalent (neither a<b nor b<a) => found it
97  ++result;
98  return true;
99  }
100  return false;
101  };
102 
103  std::remove_copy_if(source.cbegin(), source.cend(),
104  std::inserter(m, m.end()),
105  filter);
106  return result;
107  }
108 
109  // used in key(T), count(Key, T), find(key, T), etc; returns a
110  // comparator object suitable for algorithms with std::(multi)map
111  // iterators.
112  static auto valueIsEqualTo(const T &value)
113  {
114  return [&value](const auto &v) { return v.second == value; };
115  }
116 
117  Key key(const T &value, const Key &defaultKey) const
118  {
119  auto i = std::find_if(m.cbegin(),
120  m.cend(),
122  if (i != m.cend())
123  return i->first;
124 
125  return defaultKey;
126  }
127 
128  QList<Key> keys() const
129  {
131  result.reserve(m.size());
132 
133  const auto extractKey = [](const auto &v) { return v.first; };
134 
135  std::transform(m.cbegin(),
136  m.cend(),
137  std::back_inserter(result),
138  extractKey);
139  return result;
140  }
141 
142  QList<Key> keys(const T &value) const
143  {
145  result.reserve(m.size());
146  // no std::transform_if...
147  for (const auto &v : m) {
148  if (v.second == value)
149  result.append(v.first);
150  }
151  result.shrink_to_fit();
152  return result;
153  }
154 
155  QList<T> values() const
156  {
158  result.reserve(m.size());
159 
160  const auto extractValue = [](const auto &v) { return v.second; };
161 
162  std::transform(m.cbegin(),
163  m.cend(),
164  std::back_inserter(result),
165  extractValue);
166  return result;
167  }
168 
169  size_type count(const Key &key) const
170  {
171  return m.count(key);
172  }
173 
174  // Used in erase. Allocates a new QMapData and copies, from this->m,
175  // the elements not in the [first, last) range. The return contains
176  // the new QMapData and an iterator in its map pointing at the first
177  // element after the erase.
178  struct EraseResult {
181  };
182 
184  {
186  result.data = new QMapData;
187  result.it = result.data->m.end();
188  const auto newDataEnd = result.it;
189 
190  auto i = m.begin();
191  const auto e = m.end();
192 
193  // copy over all the elements before first
194  while (i != first) {
195  result.it = result.data->m.insert(newDataEnd, *i);
196  ++i;
197  }
198 
199  // skip until last
200  while (i != last)
201  ++i;
202 
203  // copy from last to the end
204  while (i != e) {
205  result.data->m.insert(newDataEnd, *i);
206  ++i;
207  }
208 
209  if (result.it != newDataEnd)
210  ++result.it;
211 
212  return result;
213  }
214 };
215 
216 //
217 // QMap
218 //
219 
220 template <class Key, class T>
221 class QMap
222 {
223  using Map = std::map<Key, T>;
224  using MapData = QMapData<Map>;
226 
227  friend class QMultiMap<Key, T>;
228 
229 public:
230  using key_type = Key;
231  using mapped_type = T;
234 
235  QMap() = default;
236 
237  // implicitly generated special member functions are OK!
238 
239  void swap(QMap<Key, T> &other) noexcept
240  {
241  d.swap(other.d);
242  }
243 
244  QMap(std::initializer_list<std::pair<Key, T>> list)
245  {
246  for (auto &p : list)
247  insert(p.first, p.second);
248  }
249 
250  explicit QMap(const std::map<Key, T> &other)
251  : d(other.empty() ? nullptr : new MapData(other))
252  {
253  }
254 
255  explicit QMap(std::map<Key, T> &&other)
256  : d(other.empty() ? nullptr : new MapData(std::move(other)))
257  {
258  }
259 
260  std::map<Key, T> toStdMap() const &
261  {
262  if (d)
263  return d->m;
264  return {};
265  }
266 
267  std::map<Key, T> toStdMap() &&
268  {
269  if (d) {
270  if (d.isShared())
271  return d->m;
272  else
273  return std::move(d->m);
274  }
275 
276  return {};
277  }
278 
279 #ifndef Q_CLANG_QDOC
280  template <typename AKey = Key, typename AT = T> friend
282  {
283  if (lhs.d == rhs.d)
284  return true;
285  if (!lhs.d)
286  return rhs == lhs;
287  Q_ASSERT(lhs.d);
288  return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
289  }
290 
291  template <typename AKey = Key, typename AT = T> friend
293  {
294  return !(lhs == rhs);
295  }
296  // TODO: add the other comparison operators; std::map has them.
297 #else
298  friend bool operator==(const QMap &lhs, const QMap &rhs);
299  friend bool operator!=(const QMap &lhs, const QMap &rhs);
300 #endif // Q_CLANG_QDOC
301 
302  size_type size() const { return d ? size_type(d->m.size()) : size_type(0); }
303 
304  bool isEmpty() const { return d ? d->m.empty() : true; }
305 
306  void detach()
307  {
308  if (d)
309  d.detach();
310  else
311  d.reset(new MapData);
312  }
313 
314  bool isDetached() const noexcept
315  {
316  return d ? !d.isShared() : false; // false makes little sense, but that's shared_null's behavior...
317  }
318 
319  bool isSharedWith(const QMap<Key, T> &other) const noexcept
320  {
321  return d == other.d; // also this makes little sense?
322  }
323 
324  void clear()
325  {
326  if (!d)
327  return;
328 
329  if (!d.isShared())
330  d->m.clear();
331  else
332  d.reset();
333  }
334 
336  {
337  if (!d)
338  return 0;
339 
340  if (!d.isShared())
341  return size_type(d->m.erase(key));
342 
343  MapData *newData = new MapData;
344  size_type result = newData->copyIfNotEquivalentTo(d->m, key);
345 
346  d.reset(newData);
347 
348  return result;
349  }
350 
351  template <typename Predicate>
353  {
354  return QtPrivate::associative_erase_if(*this, pred);
355  }
356 
357  T take(const Key &key)
358  {
359  if (!d)
360  return T();
361 
362  const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
363  // TODO: improve. There is no need of copying all the
364  // elements (the one to be removed can be skipped).
365  detach();
366 
367  auto i = d->m.find(key);
368  if (i != d->m.end()) {
369  T result(std::move(i->second));
370  d->m.erase(i);
371  return result;
372  }
373  return T();
374  }
375 
376  bool contains(const Key &key) const
377  {
378  if (!d)
379  return false;
380  auto i = d->m.find(key);
381  return i != d->m.end();
382  }
383 
384  Key key(const T &value, const Key &defaultKey = Key()) const
385  {
386  if (!d)
387  return defaultKey;
388 
389  return d->key(value, defaultKey);
390  }
391 
392  T value(const Key &key, const T &defaultValue = T()) const
393  {
394  if (!d)
395  return defaultValue;
396  const auto i = d->m.find(key);
397  if (i != d->m.cend())
398  return i->second;
399  return defaultValue;
400  }
401 
402  T &operator[](const Key &key)
403  {
404  const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
405  detach();
406  auto i = d->m.find(key);
407  if (i == d->m.end())
408  i = d->m.insert({key, T()}).first;
409  return i->second;
410  }
411 
412  // CHANGE: return T, not const T!
413  T operator[](const Key &key) const
414  {
415  return value(key);
416  }
417 
418  QList<Key> keys() const
419  {
420  if (!d)
421  return {};
422  return d->keys();
423  }
424 
425  QList<Key> keys(const T &value) const
426  {
427  if (!d)
428  return {};
429  return d->keys(value);
430  }
431 
432  QList<T> values() const
433  {
434  if (!d)
435  return {};
436  return d->values();
437  }
438 
439  size_type count(const Key &key) const
440  {
441  if (!d)
442  return 0;
443  return d->count(key);
444  }
445 
446  size_type count() const
447  {
448  return size();
449  }
450 
451  inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
452  inline const Key &lastKey() const { Q_ASSERT(!isEmpty()); return (--constEnd()).key(); }
453 
454  inline T &first() { Q_ASSERT(!isEmpty()); return *begin(); }
455  inline const T &first() const { Q_ASSERT(!isEmpty()); return *constBegin(); }
456  inline T &last() { Q_ASSERT(!isEmpty()); return *(--end()); }
457  inline const T &last() const { Q_ASSERT(!isEmpty()); return *(--constEnd()); }
458 
459  class const_iterator;
460 
461  class iterator
462  {
463  friend class QMap<Key, T>;
464  friend class const_iterator;
465 
466  typename Map::iterator i;
467  explicit iterator(typename Map::iterator it) : i(it) {}
468  public:
469  using iterator_category = std::bidirectional_iterator_tag;
471  using value_type = T;
472  using pointer = T *;
473  using reference = T &;
474 
475  iterator() = default;
476 
477  const Key &key() const { return i->first; }
478  T &value() const { return i->second; }
479  T &operator*() const { return i->second; }
480  T *operator->() const { return &i->second; }
481  friend bool operator==(const iterator &lhs, const iterator &rhs) { return lhs.i == rhs.i; }
482  friend bool operator!=(const iterator &lhs, const iterator &rhs) { return lhs.i != rhs.i; }
483 
485  {
486  ++i;
487  return *this;
488  }
490  {
491  iterator r = *this;
492  ++i;
493  return r;
494  }
496  {
497  --i;
498  return *this;
499  }
501  {
502  iterator r = *this;
503  --i;
504  return r;
505  }
506 
507 #if QT_DEPRECATED_SINCE(6, 0)
508  QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
510  friend iterator operator+(iterator it, difference_type j) { return std::next(it, j); }
511 
512  QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
514  friend iterator operator-(iterator it, difference_type j) { return std::prev(it, j); }
515 
516  QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMap iterators are not random access")
517  iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
518 
519  QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMap iterators are not random access")
520  iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
521 
522  QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
524  friend iterator operator+(difference_type j, iterator it) { return std::next(it, j); }
525 
526  QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
528  friend iterator operator-(difference_type j, iterator it) { return std::prev(it, j); }
529 #endif
530  };
531 
533  {
534  friend class QMap<Key, T>;
535  typename Map::const_iterator i;
536  explicit const_iterator(typename Map::const_iterator it) : i(it) {}
537 
538  public:
539  using iterator_category = std::bidirectional_iterator_tag;
541  using value_type = T;
542  using pointer = const T *;
543  using reference = const T &;
544 
545  const_iterator() = default;
546  Q_IMPLICIT const_iterator(const iterator &o) : i(o.i) {}
547 
548  const Key &key() const { return i->first; }
549  const T &value() const { return i->second; }
550  const T &operator*() const { return i->second; }
551  const T *operator->() const { return &i->second; }
552  friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i == rhs.i; }
553  friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i != rhs.i; }
554 
556  {
557  ++i;
558  return *this;
559  }
561  {
562  const_iterator r = *this;
563  ++i;
564  return r;
565  }
567  {
568  --i;
569  return *this;
570  }
572  {
573  const_iterator r = *this;
574  --i;
575  return r;
576  }
577 
578 #if QT_DEPRECATED_SINCE(6, 0)
579  QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
581  friend const_iterator operator+(const_iterator it, difference_type j) { return std::next(it, j); }
582 
583  QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
585  friend const_iterator operator-(const_iterator it, difference_type j) { return std::prev(it, j); }
586 
587  QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMap iterators are not random access")
588  const_iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
589 
590  QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMap iterators are not random access")
591  const_iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
592 
593  QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMap iterators are not random access")
595  friend const_iterator operator+(difference_type j, const_iterator it) { return std::next(it, j); }
596 
597  QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMap iterators are not random access")
599  friend const_iterator operator-(difference_type j, const_iterator it) { return std::prev(it, j); }
600 #endif
601  };
602 
604  {
605  const_iterator i;
606 
607  public:
610  typedef Key value_type;
611  typedef const Key *pointer;
612  typedef const Key &reference;
613 
614  key_iterator() = default;
615  explicit key_iterator(const_iterator o) : i(o) { }
616 
617  const Key &operator*() const { return i.key(); }
618  const Key *operator->() const { return &i.key(); }
619  bool operator==(key_iterator o) const { return i == o.i; }
620  bool operator!=(key_iterator o) const { return i != o.i; }
621 
622  inline key_iterator &operator++() { ++i; return *this; }
623  inline key_iterator operator++(int) { return key_iterator(i++);}
624  inline key_iterator &operator--() { --i; return *this; }
625  inline key_iterator operator--(int) { return key_iterator(i--); }
626  const_iterator base() const { return i; }
627  };
628 
631 
632  // STL style
633  iterator begin() { detach(); return iterator(d->m.begin()); }
634  const_iterator begin() const { if (!d) return const_iterator(); return const_iterator(d->m.cbegin()); }
635  const_iterator constBegin() const { return begin(); }
636  const_iterator cbegin() const { return begin(); }
637  iterator end() { detach(); return iterator(d->m.end()); }
638  const_iterator end() const { if (!d) return const_iterator(); return const_iterator(d->m.end()); }
639  const_iterator constEnd() const { return end(); }
640  const_iterator cend() const { return end(); }
641  key_iterator keyBegin() const { return key_iterator(begin()); }
642  key_iterator keyEnd() const { return key_iterator(end()); }
649 
651  {
652  return erase(it, std::next(it));
653  }
654 
656  {
657  if (!d)
658  return iterator();
659 
660  if (!d.isShared())
661  return iterator(d->m.erase(afirst.i, alast.i));
662 
663  auto result = d->erase(afirst.i, alast.i);
664  d.reset(result.data);
665  return iterator(result.it);
666  }
667 
668  // more Qt
671 
673  {
674  const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
675  detach();
676  return iterator(d->m.find(key));
677  }
678 
679  const_iterator find(const Key &key) const
680  {
681  if (!d)
682  return const_iterator();
683  return const_iterator(d->m.find(key));
684  }
685 
687  {
688  return find(key);
689  }
690 
692  {
693  const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
694  detach();
695  return iterator(d->m.lower_bound(key));
696  }
697 
699  {
700  if (!d)
701  return const_iterator();
702  return const_iterator(d->m.lower_bound(key));
703  }
704 
706  {
707  const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
708  detach();
709  return iterator(d->m.upper_bound(key));
710  }
711 
713  {
714  if (!d)
715  return const_iterator();
716  return const_iterator(d->m.upper_bound(key));
717  }
718 
719  iterator insert(const Key &key, const T &value)
720  {
721  const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
722  // TODO: improve. In case of assignment, why copying first?
723  detach();
724  return iterator(d->m.insert_or_assign(key, value).first);
725  }
726 
728  {
729  // TODO: improve. In case of assignment, why copying first?
730  typename Map::const_iterator dpos;
731  const auto copy = d.isShared() ? *this : QMap(); // keep `key`/`value` alive across the detach
732  if (!d || d.isShared()) {
733  auto posDistance = d ? std::distance(d->m.cbegin(), pos.i) : 0;
734  detach();
735  dpos = std::next(d->m.cbegin(), posDistance);
736  } else {
737  dpos = pos.i;
738  }
739  return iterator(d->m.insert_or_assign(dpos, key, value));
740  }
741 
742  void insert(const QMap<Key, T> &map)
743  {
744  // TODO: improve. In case of assignment, why copying first?
745  if (map.isEmpty())
746  return;
747 
748  detach();
749 
750 #ifdef __cpp_lib_node_extract
751  auto copy = map.d->m;
752  copy.merge(std::move(d->m));
753  d->m = std::move(copy);
754 #else
755  // this is a std::copy, but we can't use std::inserter (need insert_or_assign...).
756  // copy in reverse order, trying to make effective use of insertionHint.
757  auto insertionHint = d->m.end();
758  auto mapIt = map.d->m.crbegin();
759  auto end = map.d->m.crend();
760  for (; mapIt != end; ++mapIt)
761  insertionHint = d->m.insert_or_assign(insertionHint, mapIt->first, mapIt->second);
762 #endif
763  }
764 
766  {
767  if (!map.d || map.d->m.empty())
768  return;
769 
770  if (map.d.isShared()) {
771  // fall back to a regular copy
772  insert(map);
773  return;
774  }
775 
776  detach();
777 
778 #ifdef __cpp_lib_node_extract
779  map.d->m.merge(std::move(d->m));
780  *this = std::move(map);
781 #else
782  // same as above
783  auto insertionHint = d->m.end();
784  auto mapIt = map.d->m.crbegin();
785  auto end = map.d->m.crend();
786  for (; mapIt != end; ++mapIt)
787  insertionHint = d->m.insert_or_assign(insertionHint, std::move(mapIt->first), std::move(mapIt->second));
788 #endif
789  }
790 
791  // STL compatibility
792  inline bool empty() const
793  {
794  return isEmpty();
795  }
796 
798  {
799  const auto copy = d.isShared() ? *this : QMap(); // keep `key` alive across the detach
800  detach();
801  auto result = d->m.equal_range(akey);
802  return {iterator(result.first), iterator(result.second)};
803  }
804 
806  {
807  if (!d)
808  return {};
809  auto result = d->m.equal_range(akey);
810  return {const_iterator(result.first), const_iterator(result.second)};
811  }
812 };
813 
816 
817 template <typename Key, typename T, typename Predicate>
819 {
820  return QtPrivate::associative_erase_if(map, pred);
821 }
822 
823 //
824 // QMultiMap
825 //
826 
827 template <class Key, class T>
829 {
830  using Map = std::multimap<Key, T>;
831  using MapData = QMapData<Map>;
833 
834 public:
835  using key_type = Key;
836  using mapped_type = T;
839 
840  QMultiMap() = default;
841 
842  // implicitly generated special member functions are OK!
843 
844  QMultiMap(std::initializer_list<std::pair<Key,T>> list)
845  {
846  for (auto &p : list)
847  insert(p.first, p.second);
848  }
849 
850  void swap(QMultiMap<Key, T> &other) noexcept
851  {
852  d.swap(other.d);
853  }
854 
855  explicit QMultiMap(const QMap<Key, T> &other)
856  : d(other.isEmpty() ? nullptr : new MapData)
857  {
858  if (d) {
859  Q_ASSERT(other.d);
860  d->m.insert(other.d->m.begin(),
861  other.d->m.end());
862  }
863  }
864 
866  : d(other.isEmpty() ? nullptr : new MapData)
867  {
868  if (d) {
869  Q_ASSERT(other.d);
870  if (other.d.isShared()) {
871  d->m.insert(other.d->m.begin(),
872  other.d->m.end());
873  } else {
874 #ifdef __cpp_lib_node_extract
875  d->m.merge(std::move(other.d->m));
876 #else
877  d->m.insert(std::make_move_iterator(other.d->m.begin()),
878  std::make_move_iterator(other.d->m.end()));
879 #endif
880  }
881  }
882  }
883 
884  explicit QMultiMap(const std::multimap<Key, T> &other)
885  : d(other.empty() ? nullptr : new MapData(other))
886  {
887  }
888 
889  explicit QMultiMap(std::multimap<Key, T> &&other)
890  : d(other.empty() ? nullptr : new MapData(std::move(other)))
891  {
892  }
893 
894  // CHANGE: return type
895  Q_DECL_DEPRECATED_X("Use toStdMultiMap instead")
896  std::multimap<Key, T> toStdMap() const
897  {
898  return toStdMultiMap();
899  }
900 
901  std::multimap<Key, T> toStdMultiMap() const &
902  {
903  if (d)
904  return d->m;
905  return {};
906  }
907 
908  std::multimap<Key, T> toStdMultiMap() &&
909  {
910  if (d) {
911  if (d.isShared())
912  return d->m;
913  else
914  return std::move(d->m);
915  }
916 
917  return {};
918  }
919 
920 #ifndef Q_CLANG_QDOC
921  template <typename AKey = Key, typename AT = T> friend
923  {
924  if (lhs.d == rhs.d)
925  return true;
926  if (!lhs.d)
927  return rhs == lhs;
928  Q_ASSERT(lhs.d);
929  return rhs.d ? (lhs.d->m == rhs.d->m) : lhs.d->m.empty();
930  }
931 
932  template <typename AKey = Key, typename AT = T> friend
934  {
935  return !(lhs == rhs);
936  }
937  // TODO: add the other comparison operators; std::multimap has them.
938 #else
939  friend bool operator==(const QMultiMap &lhs, const QMultiMap &rhs);
940  friend bool operator!=(const QMultiMap &lhs, const QMultiMap &rhs);
941 #endif // Q_CLANG_QDOC
942 
943  size_type size() const { return d ? size_type(d->m.size()) : size_type(0); }
944 
945  bool isEmpty() const { return d ? d->m.empty() : true; }
946 
947  void detach()
948  {
949  if (d)
950  d.detach();
951  else
952  d.reset(new MapData);
953  }
954 
955  bool isDetached() const noexcept
956  {
957  return d ? !d.isShared() : false; // false makes little sense, but that's shared_null's behavior...
958  }
959 
960  bool isSharedWith(const QMultiMap<Key, T> &other) const noexcept
961  {
962  return d == other.d; // also this makes little sense?
963  }
964 
965  void clear()
966  {
967  if (!d)
968  return;
969 
970  if (!d.isShared())
971  d->m.clear();
972  else
973  d.reset();
974  }
975 
977  {
978  if (!d)
979  return 0;
980 
981  if (!d.isShared())
982  return size_type(d->m.erase(key));
983 
984  MapData *newData = new MapData;
985  size_type result = newData->copyIfNotEquivalentTo(d->m, key);
986 
987  d.reset(newData);
988 
989  return result;
990  }
991 
992  size_type remove(const Key &key, const T &value)
993  {
994  if (!d)
995  return 0;
996 
997  // key and value may belong to this map. As such, we need to copy
998  // them to ensure they stay valid throughout the iteration below
999  // (which may destroy them)
1000  const Key keyCopy = key;
1001  const T valueCopy = value;
1002 
1003  // TODO: improve. Copy over only the elements not to be removed.
1004  detach();
1005 
1006  size_type result = 0;
1007  const auto &keyCompare = d->m.key_comp();
1008 
1009  auto i = d->m.find(keyCopy);
1010  const auto e = d->m.end();
1011 
1012  while (i != e && !keyCompare(keyCopy, i->first)) {
1013  if (i->second == valueCopy) {
1014  i = d->m.erase(i);
1015  ++result;
1016  } else {
1017  ++i;
1018  }
1019  }
1020 
1021  return result;
1022  }
1023 
1024  template <typename Predicate>
1026  {
1027  return QtPrivate::associative_erase_if(*this, pred);
1028  }
1029 
1030  T take(const Key &key)
1031  {
1032  if (!d)
1033  return T();
1034 
1035  const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
1036 
1037  // TODO: improve. There is no need of copying all the
1038  // elements (the one to be removed can be skipped).
1039  detach();
1040 
1041  auto i = d->m.find(key);
1042  if (i != d->m.end()) {
1043  T result(std::move(i->second));
1044  d->m.erase(i);
1045  return result;
1046  }
1047  return T();
1048  }
1049 
1050  bool contains(const Key &key) const
1051  {
1052  if (!d)
1053  return false;
1054  auto i = d->m.find(key);
1055  return i != d->m.end();
1056  }
1057 
1058  bool contains(const Key &key, const T &value) const
1059  {
1060  return find(key, value) != end();
1061  }
1062 
1063  Key key(const T &value, const Key &defaultKey = Key()) const
1064  {
1065  if (!d)
1066  return defaultKey;
1067 
1068  return d->key(value, defaultKey);
1069  }
1070 
1071  T value(const Key &key, const T &defaultValue = T()) const
1072  {
1073  if (!d)
1074  return defaultValue;
1075  const auto i = d->m.find(key);
1076  if (i != d->m.cend())
1077  return i->second;
1078  return defaultValue;
1079  }
1080 
1082  {
1083  if (!d)
1084  return {};
1085  return d->keys();
1086  }
1087 
1088  QList<Key> keys(const T &value) const
1089  {
1090  if (!d)
1091  return {};
1092  return d->keys(value);
1093  }
1094 
1096  {
1098  if (!d)
1099  return result;
1100 
1101  result.reserve(size());
1102 
1103  std::unique_copy(keyBegin(), keyEnd(),
1104  std::back_inserter(result));
1105 
1106  result.shrink_to_fit();
1107  return result;
1108  }
1109 
1111  {
1112  if (!d)
1113  return {};
1114  return d->values();
1115  }
1116 
1117  QList<T> values(const Key &key) const
1118  {
1119  QList<T> result;
1120  const auto range = equal_range(key);
1121  result.reserve(std::distance(range.first, range.second));
1122  std::copy(range.first, range.second, std::back_inserter(result));
1123  return result;
1124  }
1125 
1126  size_type count(const Key &key) const
1127  {
1128  if (!d)
1129  return 0;
1130  return d->count(key);
1131  }
1132 
1133  size_type count(const Key &key, const T &value) const
1134  {
1135  if (!d)
1136  return 0;
1137 
1138  // TODO: improve; no need of scanning the equal_range twice.
1139  auto range = d->m.equal_range(key);
1140 
1141  return size_type(std::count_if(range.first,
1142  range.second,
1144  }
1145 
1146  inline const Key &firstKey() const { Q_ASSERT(!isEmpty()); return constBegin().key(); }
1147  inline const Key &lastKey() const { Q_ASSERT(!isEmpty()); return std::next(constEnd(), -1).key(); }
1148 
1149  inline T &first() { Q_ASSERT(!isEmpty()); return *begin(); }
1150  inline const T &first() const { Q_ASSERT(!isEmpty()); return *constBegin(); }
1151  inline T &last() { Q_ASSERT(!isEmpty()); return *std::next(end(), -1); }
1152  inline const T &last() const { Q_ASSERT(!isEmpty()); return *std::next(constEnd(), -1); }
1153 
1154  class const_iterator;
1155 
1156  class iterator
1157  {
1158  friend class QMultiMap<Key, T>;
1159  friend class const_iterator;
1160 
1161  typename Map::iterator i;
1162  explicit iterator(typename Map::iterator it) : i(it) {}
1163  public:
1164  using iterator_category = std::bidirectional_iterator_tag;
1166  using value_type = T;
1167  using pointer = T *;
1168  using reference = T &;
1169 
1170  iterator() = default;
1171 
1172  const Key &key() const { return i->first; }
1173  T &value() const { return i->second; }
1174  T &operator*() const { return i->second; }
1175  T *operator->() const { return &i->second; }
1176  friend bool operator==(const iterator &lhs, const iterator &rhs) { return lhs.i == rhs.i; }
1177  friend bool operator!=(const iterator &lhs, const iterator &rhs) { return lhs.i != rhs.i; }
1178 
1180  {
1181  ++i;
1182  return *this;
1183  }
1185  {
1186  iterator r = *this;
1187  ++i;
1188  return r;
1189  }
1191  {
1192  --i;
1193  return *this;
1194  }
1196  {
1197  iterator r = *this;
1198  --i;
1199  return r;
1200  }
1201 
1202 #if QT_DEPRECATED_SINCE(6, 0)
1203  QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1205  friend iterator operator+(iterator it, difference_type j) { return std::next(it, j); }
1206 
1207  QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1209  friend iterator operator-(iterator it, difference_type j) { return std::prev(it, j); }
1210 
1211  QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMultiMap iterators are not random access")
1212  iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
1213 
1214  QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMultiMap iterators are not random access")
1215  iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
1216 
1217  QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1219  friend iterator operator+(difference_type j, iterator it) { return std::next(it, j); }
1220 
1221  QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1223  friend iterator operator-(difference_type j, iterator it) { return std::prev(it, j); }
1224 #endif
1225  };
1226 
1228  {
1229  friend class QMultiMap<Key, T>;
1230  typename Map::const_iterator i;
1231  explicit const_iterator(typename Map::const_iterator it) : i(it) {}
1232 
1233  public:
1234  using iterator_category = std::bidirectional_iterator_tag;
1236  using value_type = T;
1237  using pointer = const T *;
1238  using reference = const T &;
1239 
1240  const_iterator() = default;
1241  Q_IMPLICIT const_iterator(const iterator &o) : i(o.i) {}
1242 
1243  const Key &key() const { return i->first; }
1244  const T &value() const { return i->second; }
1245  const T &operator*() const { return i->second; }
1246  const T *operator->() const { return &i->second; }
1247  friend bool operator==(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i == rhs.i; }
1248  friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs) { return lhs.i != rhs.i; }
1249 
1251  {
1252  ++i;
1253  return *this;
1254  }
1256  {
1257  const_iterator r = *this;
1258  ++i;
1259  return r;
1260  }
1262  {
1263  --i;
1264  return *this;
1265  }
1267  {
1268  const_iterator r = *this;
1269  --i;
1270  return r;
1271  }
1272 
1273 #if QT_DEPRECATED_SINCE(6, 0)
1274  QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1276  friend const_iterator operator+(const_iterator it, difference_type j) { return std::next(it, j); }
1277 
1278  QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1280  friend const_iterator operator-(const_iterator it, difference_type j) { return std::prev(it, j); }
1281 
1282  QT_DEPRECATED_VERSION_X_6_0("Use std::next or std::advance; QMultiMap iterators are not random access")
1283  const_iterator &operator+=(difference_type j) { std::advance(*this, j); return *this; }
1284 
1285  QT_DEPRECATED_VERSION_X_6_0("Use std::prev or std::advance; QMultiMap iterators are not random access")
1286  const_iterator &operator-=(difference_type j) { std::advance(*this, -j); return *this; }
1287 
1288  QT_DEPRECATED_VERSION_X_6_0("Use std::next; QMultiMap iterators are not random access")
1290  friend const_iterator operator+(difference_type j, const_iterator it) { return std::next(it, j); }
1291 
1292  QT_DEPRECATED_VERSION_X_6_0("Use std::prev; QMultiMap iterators are not random access")
1294  friend const_iterator operator-(difference_type j, const_iterator it) { return std::prev(it, j); }
1295 #endif
1296  };
1297 
1299  {
1300  const_iterator i;
1301 
1302  public:
1305  typedef Key value_type;
1306  typedef const Key *pointer;
1307  typedef const Key &reference;
1308 
1309  key_iterator() = default;
1310  explicit key_iterator(const_iterator o) : i(o) { }
1311 
1312  const Key &operator*() const { return i.key(); }
1313  const Key *operator->() const { return &i.key(); }
1314  bool operator==(key_iterator o) const { return i == o.i; }
1315  bool operator!=(key_iterator o) const { return i != o.i; }
1316 
1317  inline key_iterator &operator++() { ++i; return *this; }
1318  inline key_iterator operator++(int) { return key_iterator(i++);}
1319  inline key_iterator &operator--() { --i; return *this; }
1320  inline key_iterator operator--(int) { return key_iterator(i--); }
1321  const_iterator base() const { return i; }
1322  };
1323 
1326 
1327  // STL style
1328  iterator begin() { detach(); return iterator(d->m.begin()); }
1329  const_iterator begin() const { if (!d) return const_iterator(); return const_iterator(d->m.cbegin()); }
1330  const_iterator constBegin() const { return begin(); }
1331  const_iterator cbegin() const { return begin(); }
1332  iterator end() { detach(); return iterator(d->m.end()); }
1333  const_iterator end() const { if (!d) return const_iterator(); return const_iterator(d->m.end()); }
1334  const_iterator constEnd() const { return end(); }
1335  const_iterator cend() const { return end(); }
1336  key_iterator keyBegin() const { return key_iterator(begin()); }
1337  key_iterator keyEnd() const { return key_iterator(end()); }
1344 
1346  {
1347  return erase(it, std::next(it));
1348  }
1349 
1351  {
1352  if (!d)
1353  return iterator();
1354 
1355  if (!d.isShared())
1356  return iterator(d->m.erase(afirst.i, alast.i));
1357 
1358  auto result = d->erase(afirst.i, alast.i);
1359  d.reset(result.data);
1360  return iterator(result.it);
1361  }
1362 
1363  // more Qt
1366 
1368  {
1369  return size();
1370  }
1371 
1373  {
1374  const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
1375  detach();
1376  return iterator(d->m.find(key));
1377  }
1378 
1379  const_iterator find(const Key &key) const
1380  {
1381  if (!d)
1382  return const_iterator();
1383  return const_iterator(d->m.find(key));
1384  }
1385 
1387  {
1388  return find(key);
1389  }
1390 
1391  iterator find(const Key &key, const T &value)
1392  {
1393  const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
1394 
1395  detach();
1396 
1397  auto range = d->m.equal_range(key);
1398  auto i = std::find_if(range.first, range.second,
1400 
1401  if (i != range.second)
1402  return iterator(i);
1403  return iterator(d->m.end());
1404  }
1405 
1406  const_iterator find(const Key &key, const T &value) const
1407  {
1408  if (!d)
1409  return const_iterator();
1410 
1411  auto range = d->m.equal_range(key);
1412  auto i = std::find_if(range.first, range.second,
1414 
1415  if (i != range.second)
1416  return const_iterator(i);
1417  return const_iterator(d->m.end());
1418  }
1419 
1420  const_iterator constFind(const Key &key, const T &value) const
1421  {
1422  return find(key, value);
1423  }
1424 
1426  {
1427  const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
1428  detach();
1429  return iterator(d->m.lower_bound(key));
1430  }
1431 
1433  {
1434  if (!d)
1435  return const_iterator();
1436  return const_iterator(d->m.lower_bound(key));
1437  }
1438 
1440  {
1441  const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
1442  detach();
1443  return iterator(d->m.upper_bound(key));
1444  }
1445 
1447  {
1448  if (!d)
1449  return const_iterator();
1450  return const_iterator(d->m.upper_bound(key));
1451  }
1452 
1453  iterator insert(const Key &key, const T &value)
1454  {
1455  const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
1456  detach();
1457  // note that std::multimap inserts at the end of an equal_range for a key,
1458  // QMultiMap at the beginning.
1459  auto i = d->m.lower_bound(key);
1460  return iterator(d->m.insert(i, {key, value}));
1461  }
1462 
1464  {
1465  const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
1466  typename Map::const_iterator dpos;
1467  if (!d || d.isShared()) {
1468  auto posDistance = d ? std::distance(d->m.cbegin(), pos.i) : 0;
1469  detach();
1470  dpos = std::next(d->m.cbegin(), posDistance);
1471  } else {
1472  dpos = pos.i;
1473  }
1474  return iterator(d->m.insert(dpos, {key, value}));
1475  }
1476 
1477 #if QT_DEPRECATED_SINCE(6, 0)
1478  QT_DEPRECATED_VERSION_X_6_0("Use insert() instead")
1479  iterator insertMulti(const Key &key, const T &value)
1480  {
1481  return insert(key, value);
1482  }
1483  QT_DEPRECATED_VERSION_X_6_0("Use insert() instead")
1484  iterator insertMulti(const_iterator pos, const Key &key, const T &value)
1485  {
1486  return insert(pos, key, value);
1487  }
1488 
1489  QT_DEPRECATED_VERSION_X_6_0("Use unite() instead")
1491  {
1492  unite(map);
1493  }
1494 
1495  QT_DEPRECATED_VERSION_X_6_0("Use unite() instead")
1496  void insert(QMultiMap<Key, T> &&map)
1497  {
1498  unite(std::move(map));
1499  }
1500 #endif
1501 
1502  iterator replace(const Key &key, const T &value)
1503  {
1504  const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key`/`value` alive across the detach
1505 
1506  // TODO: improve. No need of copying and then overwriting.
1507  detach();
1508 
1509  // Similarly, improve here (e.g. lower_bound and hinted insert);
1510  // there's no insert_or_assign on multimaps
1511  auto i = d->m.find(key);
1512  if (i != d->m.end())
1513  i->second = value;
1514  else
1515  i = d->m.insert({key, value});
1516 
1517  return iterator(i);
1518  }
1519 
1520  // STL compatibility
1521  inline bool empty() const { return isEmpty(); }
1522 
1524  {
1525  const auto copy = d.isShared() ? *this : QMultiMap(); // keep `key` alive across the detach
1526  detach();
1527  auto result = d->m.equal_range(akey);
1528  return {iterator(result.first), iterator(result.second)};
1529  }
1530 
1532  {
1533  if (!d)
1534  return {};
1535  auto result = d->m.equal_range(akey);
1536  return {const_iterator(result.first), const_iterator(result.second)};
1537  }
1538 
1540  {
1541  if (other.isEmpty())
1542  return *this;
1543 
1544  detach();
1545 
1546  auto copy = other.d->m;
1547 #ifdef __cpp_lib_node_extract
1548  copy.merge(std::move(d->m));
1549 #else
1550  copy.insert(std::make_move_iterator(d->m.begin()),
1551  std::make_move_iterator(d->m.end()));
1552 #endif
1553  d->m = std::move(copy);
1554  return *this;
1555  }
1556 
1558  {
1559  if (!other.d || other.d->m.empty())
1560  return *this;
1561 
1562  if (other.d.isShared()) {
1563  // fall back to a regular copy
1564  unite(other);
1565  return *this;
1566  }
1567 
1568  detach();
1569 
1570 #ifdef __cpp_lib_node_extract
1571  other.d->m.merge(std::move(d->m));
1572 #else
1573  other.d->m.insert(std::make_move_iterator(d->m.begin()),
1574  std::make_move_iterator(d->m.end()));
1575 #endif
1576  *this = std::move(other);
1577  return *this;
1578  }
1579 };
1580 
1583 
1584 template <typename Key, typename T>
1586 {
1587  auto result = lhs;
1588  result += rhs;
1589  return result;
1590 }
1591 
1592 template <typename Key, typename T>
1594 {
1595  return lhs.unite(rhs);
1596 }
1597 
1598 template <typename Key, typename T, typename Predicate>
1600 {
1601  return QtPrivate::associative_erase_if(map, pred);
1602 }
1603 
1605 
1606 #endif // QMAP_H
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
#define value
[5]
const QByteArray operator+(const QByteArray &a1, const QByteArray &a2)
Definition: qbytearray.h:575
template< typename Predicate > qsizetype erase_if(QByteArray &ba, Predicate pred)
Definition: qbytearray.h:676
Definition: qlist.h:108
QPair< QVariant, QVariant > value_type
Definition: qlist.h:121
const_iterator operator++(int)
Definition: qmap.h:560
friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs)
Definition: qmap.h:553
const T & value() const
Definition: qmap.h:549
const_iterator & operator--()
Definition: qmap.h:566
const T & operator*() const
Definition: qmap.h:550
const Key & key() const
Definition: qmap.h:548
const_iterator()=default
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs)
Definition: qmap.h:552
const T * operator->() const
Definition: qmap.h:551
Q_IMPLICIT const_iterator(const iterator &o)
Definition: qmap.h:546
qptrdiff difference_type
Definition: qmap.h:540
const_iterator operator--(int)
Definition: qmap.h:571
std::bidirectional_iterator_tag iterator_category
Definition: qmap.h:539
const_iterator & operator++()
Definition: qmap.h:555
T * operator->() const
Definition: qmap.h:480
T & operator*() const
Definition: qmap.h:479
qptrdiff difference_type
Definition: qmap.h:470
iterator operator++(int)
Definition: qmap.h:489
friend bool operator==(const iterator &lhs, const iterator &rhs)
Definition: qmap.h:481
iterator operator--(int)
Definition: qmap.h:500
const Key & key() const
Definition: qmap.h:477
iterator & operator--()
Definition: qmap.h:495
iterator()=default
iterator & operator++()
Definition: qmap.h:484
std::bidirectional_iterator_tag iterator_category
Definition: qmap.h:469
T & value() const
Definition: qmap.h:478
friend bool operator!=(const iterator &lhs, const iterator &rhs)
Definition: qmap.h:482
key_iterator(const_iterator o)
Definition: qmap.h:615
key_iterator()=default
key_iterator & operator++()
Definition: qmap.h:622
const_iterator::iterator_category iterator_category
Definition: qmap.h:608
key_iterator & operator--()
Definition: qmap.h:624
const Key * pointer
Definition: qmap.h:611
const_iterator base() const
Definition: qmap.h:626
const Key & reference
Definition: qmap.h:612
key_iterator operator--(int)
Definition: qmap.h:625
const Key * operator->() const
Definition: qmap.h:618
key_iterator operator++(int)
Definition: qmap.h:623
bool operator==(key_iterator o) const
Definition: qmap.h:619
const_iterator::difference_type difference_type
Definition: qmap.h:609
const Key & operator*() const
Definition: qmap.h:617
bool operator!=(key_iterator o) const
Definition: qmap.h:620
Definition: qmap.h:61
typename Map::iterator iterator
Definition: qmap.h:68
EraseResult erase(const_iterator first, const_iterator last) const
Definition: qmap.h:183
Key key(const T &value, const Key &defaultKey) const
Definition: qmap.h:117
QList< Key > keys() const
Definition: qmap.h:128
QMapData(Map &&other)
Definition: qmap.h:81
typename Map::size_type size_type
Definition: qmap.h:67
Map m
Definition: qmap.h:71
QMapData()=default
AMap Map
Definition: qmap.h:63
size_type count(const Key &key) const
Definition: qmap.h:169
QList< Key > keys(const T &value) const
Definition: qmap.h:142
typename Map::const_iterator const_iterator
Definition: qmap.h:69
typename Map::value_type value_type
Definition: qmap.h:66
size_type copyIfNotEquivalentTo(const Map &source, const Key &key)
Definition: qmap.h:87
QList< T > values() const
Definition: qmap.h:155
static auto valueIsEqualTo(const T &value)
Definition: qmap.h:112
typename Map::key_type Key
Definition: qmap.h:64
QMapData(const Map &other)
Definition: qmap.h:77
Definition: qmap.h:222
iterator insert(const Key &key, const T &value)
Definition: qmap.h:719
T value(const Key &key, const T &defaultValue=T()) const
Definition: qmap.h:392
QList< T > values() const
Definition: qmap.h:432
const_iterator end() const
Definition: qmap.h:638
iterator erase(const_iterator it)
Definition: qmap.h:650
key_value_iterator keyValueEnd()
Definition: qmap.h:644
QList< Key > keys() const
Definition: qmap.h:418
bool contains(const Key &key) const
Definition: qmap.h:376
size_type count(const Key &key) const
Definition: qmap.h:439
QList< Key > keys(const T &value) const
Definition: qmap.h:425
iterator insert(const_iterator pos, const Key &key, const T &value)
Definition: qmap.h:727
const_iterator cend() const
Definition: qmap.h:640
T & first()
Definition: qmap.h:454
QMap()=default
const T & last() const
Definition: qmap.h:457
const T & first() const
Definition: qmap.h:455
qptrdiff difference_type
Definition: qmap.h:232
QKeyValueIterator< const Key &, T &, iterator > key_value_iterator
Definition: qmap.h:630
size_type remove(const Key &key)
Definition: qmap.h:335
const Key & lastKey() const
Definition: qmap.h:452
const_key_value_iterator constKeyValueEnd() const
Definition: qmap.h:648
const_iterator cbegin() const
Definition: qmap.h:636
friend QTypeTraits::compare_eq_result_container< QMap, AKey, AT > operator!=(const QMap &lhs, const QMap &rhs)
Definition: qmap.h:292
const_iterator lowerBound(const Key &key) const
Definition: qmap.h:698
const_iterator constFind(const Key &key) const
Definition: qmap.h:686
void clear()
Definition: qmap.h:324
bool isSharedWith(const QMap< Key, T > &other) const noexcept
Definition: qmap.h:319
QPair< const_iterator, const_iterator > equal_range(const Key &akey) const
Definition: qmap.h:805
QMap(std::initializer_list< std::pair< Key, T >> list)
Definition: qmap.h:244
const_key_value_iterator constKeyValueBegin() const
Definition: qmap.h:646
iterator find(const Key &key)
Definition: qmap.h:672
void detach()
Definition: qmap.h:306
void insert(const QMap< Key, T > &map)
Definition: qmap.h:742
iterator lowerBound(const Key &key)
Definition: qmap.h:691
iterator Iterator
Definition: qmap.h:669
bool isEmpty() const
Definition: qmap.h:304
const_iterator ConstIterator
Definition: qmap.h:670
std::map< Key, T > toStdMap() const &
Definition: qmap.h:260
size_type count() const
Definition: qmap.h:446
qsizetype size_type
Definition: qmap.h:233
iterator begin()
Definition: qmap.h:633
T operator[](const Key &key) const
Definition: qmap.h:413
const_key_value_iterator keyValueEnd() const
Definition: qmap.h:647
QMap(std::map< Key, T > &&other)
Definition: qmap.h:255
iterator end()
Definition: qmap.h:637
QPair< iterator, iterator > equal_range(const Key &akey)
Definition: qmap.h:797
Key key_type
Definition: qmap.h:230
iterator upperBound(const Key &key)
Definition: qmap.h:705
iterator erase(const_iterator afirst, const_iterator alast)
Definition: qmap.h:655
std::map< Key, T > toStdMap() &&
Definition: qmap.h:267
const_iterator constBegin() const
Definition: qmap.h:635
const_iterator begin() const
Definition: qmap.h:634
friend QTypeTraits::compare_eq_result_container< QMap, AKey, AT > operator==(const QMap &lhs, const QMap &rhs)
Definition: qmap.h:281
size_type removeIf(Predicate pred)
Definition: qmap.h:352
size_type size() const
Definition: qmap.h:302
key_iterator keyBegin() const
Definition: qmap.h:641
bool empty() const
Definition: qmap.h:792
const Key & firstKey() const
Definition: qmap.h:451
T & last()
Definition: qmap.h:456
const_key_value_iterator keyValueBegin() const
Definition: qmap.h:645
key_value_iterator keyValueBegin()
Definition: qmap.h:643
void insert(QMap< Key, T > &&map)
Definition: qmap.h:765
bool isDetached() const noexcept
Definition: qmap.h:314
QMap(const std::map< Key, T > &other)
Definition: qmap.h:250
T & operator[](const Key &key)
Definition: qmap.h:402
Key key(const T &value, const Key &defaultKey=Key()) const
Definition: qmap.h:384
const_iterator constEnd() const
Definition: qmap.h:639
const_iterator upperBound(const Key &key) const
Definition: qmap.h:712
key_iterator keyEnd() const
Definition: qmap.h:642
QKeyValueIterator< const Key &, const T &, const_iterator > const_key_value_iterator
Definition: qmap.h:629
const_iterator find(const Key &key) const
Definition: qmap.h:679
T take(const Key &key)
Definition: qmap.h:357
void swap(QMap< Key, T > &other) noexcept
Definition: qmap.h:239
const T & operator*() const
Definition: qmap.h:1245
friend bool operator!=(const const_iterator &lhs, const const_iterator &rhs)
Definition: qmap.h:1248
const Key & key() const
Definition: qmap.h:1243
Q_IMPLICIT const_iterator(const iterator &o)
Definition: qmap.h:1241
const_iterator & operator++()
Definition: qmap.h:1250
qptrdiff difference_type
Definition: qmap.h:1235
friend bool operator==(const const_iterator &lhs, const const_iterator &rhs)
Definition: qmap.h:1247
const T & value() const
Definition: qmap.h:1244
const_iterator & operator--()
Definition: qmap.h:1261
const_iterator operator--(int)
Definition: qmap.h:1266
const_iterator operator++(int)
Definition: qmap.h:1255
const T * operator->() const
Definition: qmap.h:1246
std::bidirectional_iterator_tag iterator_category
Definition: qmap.h:1234
iterator & operator++()
Definition: qmap.h:1179
friend bool operator==(const iterator &lhs, const iterator &rhs)
Definition: qmap.h:1176
T & operator*() const
Definition: qmap.h:1174
T & value() const
Definition: qmap.h:1173
const Key & key() const
Definition: qmap.h:1172
T * operator->() const
Definition: qmap.h:1175
qptrdiff difference_type
Definition: qmap.h:1165
friend bool operator!=(const iterator &lhs, const iterator &rhs)
Definition: qmap.h:1177
std::bidirectional_iterator_tag iterator_category
Definition: qmap.h:1164
iterator & operator--()
Definition: qmap.h:1190
iterator operator++(int)
Definition: qmap.h:1184
iterator operator--(int)
Definition: qmap.h:1195
bool operator==(key_iterator o) const
Definition: qmap.h:1314
const_iterator::difference_type difference_type
Definition: qmap.h:1304
const_iterator base() const
Definition: qmap.h:1321
key_iterator(const_iterator o)
Definition: qmap.h:1310
key_iterator operator++(int)
Definition: qmap.h:1318
const_iterator::iterator_category iterator_category
Definition: qmap.h:1303
const Key * pointer
Definition: qmap.h:1306
const Key & operator*() const
Definition: qmap.h:1312
key_iterator & operator++()
Definition: qmap.h:1317
const Key & reference
Definition: qmap.h:1307
bool operator!=(key_iterator o) const
Definition: qmap.h:1315
key_iterator operator--(int)
Definition: qmap.h:1320
const Key * operator->() const
Definition: qmap.h:1313
key_iterator & operator--()
Definition: qmap.h:1319
const Key & lastKey() const
Definition: qmap.h:1147
size_type count(const Key &key) const
Definition: qmap.h:1126
const_iterator find(const Key &key, const T &value) const
Definition: qmap.h:1406
const Key & firstKey() const
Definition: qmap.h:1146
iterator lowerBound(const Key &key)
Definition: qmap.h:1425
size_type removeIf(Predicate pred)
Definition: qmap.h:1025
iterator replace(const Key &key, const T &value)
Definition: qmap.h:1502
const_key_value_iterator constKeyValueEnd() const
Definition: qmap.h:1343
QList< Key > uniqueKeys() const
Definition: qmap.h:1095
QMultiMap(std::multimap< Key, T > &&other)
Definition: qmap.h:889
QMultiMap & unite(const QMultiMap &other)
Definition: qmap.h:1539
QMultiMap(const QMap< Key, T > &other)
Definition: qmap.h:855
QPair< const_iterator, const_iterator > equal_range(const Key &akey) const
Definition: qmap.h:1531
const_iterator constFind(const Key &key) const
Definition: qmap.h:1386
const_key_value_iterator keyValueBegin() const
Definition: qmap.h:1340
QMultiMap(QMap< Key, T > &&other)
Definition: qmap.h:865
QList< Key > keys(const T &value) const
Definition: qmap.h:1088
const T & first() const
Definition: qmap.h:1150
const_iterator constEnd() const
Definition: qmap.h:1334
bool contains(const Key &key) const
Definition: qmap.h:1050
qptrdiff difference_type
Definition: qmap.h:837
key_value_iterator keyValueEnd()
Definition: qmap.h:1339
iterator end()
Definition: qmap.h:1332
bool isSharedWith(const QMultiMap< Key, T > &other) const noexcept
Definition: qmap.h:960
const_key_value_iterator constKeyValueBegin() const
Definition: qmap.h:1341
QList< Key > keys() const
Definition: qmap.h:1081
std::multimap< Key, T > toStdMultiMap() &&
Definition: qmap.h:908
const_iterator constFind(const Key &key, const T &value) const
Definition: qmap.h:1420
size_type count() const
Definition: qmap.h:1367
key_iterator keyBegin() const
Definition: qmap.h:1336
const_iterator find(const Key &key) const
Definition: qmap.h:1379
const T & last() const
Definition: qmap.h:1152
size_type count(const Key &key, const T &value) const
Definition: qmap.h:1133
bool contains(const Key &key, const T &value) const
Definition: qmap.h:1058
QKeyValueIterator< const Key &, const T &, const_iterator > const_key_value_iterator
Definition: qmap.h:1324
bool empty() const
Definition: qmap.h:1521
qsizetype size_type
Definition: qmap.h:838
Key key_type
Definition: qmap.h:835
const_iterator end() const
Definition: qmap.h:1333
friend QTypeTraits::compare_eq_result_container< QMultiMap, AKey, AT > operator!=(const QMultiMap &lhs, const QMultiMap &rhs)
Definition: qmap.h:933
const_iterator upperBound(const Key &key) const
Definition: qmap.h:1446
T & first()
Definition: qmap.h:1149
QMultiMap(std::initializer_list< std::pair< Key, T >> list)
Definition: qmap.h:844
QMultiMap(const std::multimap< Key, T > &other)
Definition: qmap.h:884
void detach()
Definition: qmap.h:947
const_iterator ConstIterator
Definition: qmap.h:1365
size_type remove(const Key &key, const T &value)
Definition: qmap.h:992
bool isEmpty() const
Definition: qmap.h:945
key_iterator keyEnd() const
Definition: qmap.h:1337
friend QTypeTraits::compare_eq_result_container< QMultiMap, AKey, AT > operator==(const QMultiMap &lhs, const QMultiMap &rhs)
Definition: qmap.h:922
iterator find(const Key &key)
Definition: qmap.h:1372
iterator insert(const Key &key, const T &value)
Definition: qmap.h:1453
iterator erase(const_iterator it)
Definition: qmap.h:1345
const_iterator begin() const
Definition: qmap.h:1329
size_type size() const
Definition: qmap.h:943
const_iterator constBegin() const
Definition: qmap.h:1330
QMultiMap()=default
size_type remove(const Key &key)
Definition: qmap.h:976
const_iterator cbegin() const
Definition: qmap.h:1331
iterator insert(const_iterator pos, const Key &key, const T &value)
Definition: qmap.h:1463
std::multimap< Key, T > toStdMultiMap() const &
Definition: qmap.h:901
QList< T > values() const
Definition: qmap.h:1110
std::multimap< Key, T > toStdMap() const
Definition: qmap.h:896
T value(const Key &key, const T &defaultValue=T()) const
Definition: qmap.h:1071
iterator upperBound(const Key &key)
Definition: qmap.h:1439
iterator Iterator
Definition: qmap.h:1364
void swap(QMultiMap< Key, T > &other) noexcept
Definition: qmap.h:850
QList< T > values(const Key &key) const
Definition: qmap.h:1117
QKeyValueIterator< const Key &, T &, iterator > key_value_iterator
Definition: qmap.h:1325
iterator erase(const_iterator afirst, const_iterator alast)
Definition: qmap.h:1350
void clear()
Definition: qmap.h:965
key_value_iterator keyValueBegin()
Definition: qmap.h:1338
iterator find(const Key &key, const T &value)
Definition: qmap.h:1391
const_key_value_iterator keyValueEnd() const
Definition: qmap.h:1342
bool isDetached() const noexcept
Definition: qmap.h:955
iterator begin()
Definition: qmap.h:1328
Key key(const T &value, const Key &defaultKey=Key()) const
Definition: qmap.h:1063
const_iterator lowerBound(const Key &key) const
Definition: qmap.h:1432
QPair< iterator, iterator > equal_range(const Key &akey)
Definition: qmap.h:1523
T take(const Key &key)
Definition: qmap.h:1030
T & last()
Definition: qmap.h:1151
const_iterator cend() const
Definition: qmap.h:1335
The QSharedData class is a base class for shared data objects. \reentrant.
Definition: qshareddata.h:55
#define T(x)
Definition: main.cpp:42
#define this
Definition: dialogs.cpp:56
QMap< QString, QString > map
[6]
double e
QMultiMap< int, QWidget * > multimap
[28]
auto it unsigned count const
Definition: hb-iter.hh:848
short next
Definition: keywords.cpp:454
Generic::PredicateMatcher< T > Predicate(std::function< bool(T const &)> const &predicate, std::string const &description="")
Definition: catch_p_p.h:3521
typename C::const_iterator const_iterator
typename C::key_type key_type
typename C::mapped_type mapped_type
typename C::iterator iterator
std::enable_if_t< std::conjunction_v< QTypeTraits::has_operator_equal_container< Container, T >... >, bool > compare_eq_result_container
Definition: qtypeinfo.h:347
auto associative_erase_if(Container &c, Predicate &pred)
Definition: qfloat16.h:381
int distance(TestIterator &a, TestIterator &b)
void
Definition: png.h:1080
#define Q_DECL_DEPRECATED_X(text)
std::pair< T1, T2 > QPair
Definition: qcontainerfwd.h:56
EGLOutputLayerEXT EGLint EGLAttrib value
ptrdiff_t qptrdiff
Definition: qglobal.h:307
ptrdiff_t qsizetype
Definition: qglobal.h:308
#define QT_DEPRECATED_VERSION_X_6_0(text)
Definition: qglobal.h:444
#define Q_DECLARE_ASSOCIATIVE_ITERATOR(C)
Definition: qiterator.h:114
#define Q_DECLARE_MUTABLE_ASSOCIATIVE_ITERATOR(C)
Definition: qiterator.h:146
QMultiMap< Key, T > operator+=(QMultiMap< Key, T > &lhs, const QMultiMap< Key, T > &rhs)
Definition: qmap.h:1593
GLsizei const GLfloat * v
[13]
const GLfloat * m
GLuint64 key
GLboolean r
[2]
GLuint GLuint end
GLsizei range
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLint first
GLsizei GLsizei GLchar * source
GLuint GLenum GLenum transform
Definition: qopenglext.h:11564
GLuint64EXT * result
[6]
Definition: qopenglext.h:10932
GLfloat GLfloat p
[1]
Definition: qopenglext.h:12698
#define Q_ASSERT(cond)
Definition: qrandom.cpp:84
QObject::connect nullptr
QSharedPointer< T > other(t)
[5]
QStringList::Iterator it
QStringList list
[0]
QMapData * data
Definition: qmap.h:179
Definition: main.cpp:38
#define rhs