diff options
author | Sérgio Martins <sergio.martins@kdab.com> | 2015-07-24 20:30:01 +0100 |
---|---|---|
committer | Sérgio Martins <sergio.martins@kdab.com> | 2015-07-28 19:11:12 +0000 |
commit | 07f27fcf6d4f046bbea6c3155efa78128e164da4 (patch) | |
tree | 177ed098a3924965ef9b1028ae97918e834de7c5 /src | |
parent | 75244bf985e248bd3fccac532fc4a9cd1bf7722f (diff) |
Introduce QMap key iterators
So we can have interoperability with algorithms.
Motivated by inefficient code like qDeleteAll(map.keys())
[ChangeLog][QtCore][QMap] Added key iterators, accessible through
keyBegin() and keyEnd().
Change-Id: Ieee2f9ad031e9d1e845a71447746699bbe95b96c
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp | 19 | ||||
-rw-r--r-- | src/corelib/tools/qmap.cpp | 154 | ||||
-rw-r--r-- | src/corelib/tools/qmap.h | 28 |
3 files changed, 197 insertions, 4 deletions
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp index 7580b6bbaf..29e53fc700 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qmap.cpp @@ -311,3 +311,22 @@ while (i != map.end() && i.key() == "plenty") { ++i; } //! [27] + +//! [keyiterator1] +for (QMap<int, QString>::const_iterator it = map.cbegin(), end = map.cend(); it != end; ++it) { + cout << "The key: " << it.key() << endl + cout << "The value: " << it.value() << endl; + cout << "Also the value: " << (*it) << endl; +} +//! [keyiterator1] + +//! [keyiterator2] +// Inefficient, keys() is expensive +QList<int> keys = map.keys(); +int numPrimes = std::count_if(map.cbegin(), map.cend(), isPrimeNumber); +qDeleteAll(map2.keys()); + +// Efficient, no memory allocation needed +int numPrimes = std::count_if(map.keyBegin(), map.keyEnd(), isPrimeNumber); +qDeleteAll(map2.keyBegin(), map2.keyEnd()); +//! [keyiterator2] diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp index 61e19252b3..f7aa7332dd 100644 --- a/src/corelib/tools/qmap.cpp +++ b/src/corelib/tools/qmap.cpp @@ -858,6 +858,15 @@ void QMapDataBase::freeData(QMapDataBase *d) \sa begin(), constEnd() */ +/*! \fn QMap::key_iterator QMap::keyBegin() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first key + in the map. + + \sa keyEnd(), firstKey() +*/ + /*! \fn QMap::iterator QMap::end() Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item @@ -888,6 +897,15 @@ void QMapDataBase::freeData(QMapDataBase *d) \sa constBegin(), end() */ +/*! \fn QMap::key_iterator QMap::keyEnd() const + \since 5.6 + + Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary + item after the last key in the map. + + \sa keyBegin(), lastKey() +*/ + /*! \fn const Key &QMap::firstKey() const \since 5.2 @@ -896,7 +914,7 @@ void QMapDataBase::freeData(QMapDataBase *d) This executes in \l{constant time}. - \sa lastKey(), first(), isEmpty() + \sa lastKey(), first(), keyBegin(), isEmpty() */ /*! \fn const Key &QMap::lastKey() const @@ -907,7 +925,7 @@ void QMapDataBase::freeData(QMapDataBase *d) This executes in \l{logarithmic time}. - \sa firstKey(), last(), isEmpty() + \sa firstKey(), last(), keyEnd(), isEmpty() */ /*! \fn T &QMap::first() @@ -1235,7 +1253,7 @@ void QMapDataBase::freeData(QMapDataBase *d) while iterators are active on that container. For more information, read \l{Implicit sharing iterator problem}. - \sa QMap::const_iterator, QMutableMapIterator + \sa QMap::const_iterator, QMap::key_iterator, QMutableMapIterator */ /*! \typedef QMap::iterator::difference_type @@ -1458,7 +1476,7 @@ void QMapDataBase::freeData(QMapDataBase *d) while iterators are active on that container. For more information, read \l{Implicit sharing iterator problem}. - \sa QMap::iterator, QMapIterator + \sa QMap::iterator, QMap::key_iterator, QMapIterator */ /*! \typedef QMap::const_iterator::difference_type @@ -1634,6 +1652,134 @@ void QMapDataBase::freeData(QMapDataBase *d) \sa operator+=(), operator-() */ +/*! \class QMap::key_iterator + \inmodule QtCore + \since 5.6 + \brief The QMap::key_iterator class provides an STL-style const iterator for QMap and QMultiMap keys. + + QMap::key_iterator is essentially the same as QMap::const_iterator + with the difference that operator*() and operator->() return a key + instead of a value. + + For most uses QMap::iterator and QMap::const_iterator should be used, + you can easily access the key by calling QMap::iterator::key(): + + \snippet code/src_corelib_tools_qmap.cpp keyiterator1 + + However, to have interoperability between QMap's keys and STL-style + algorithms we need an iterator that dereferences to a key instead + of a value. With QMap::key_iterator we can apply an algorithm to a + range of keys without having to call QMap::keys(), which is inefficient + as it costs one QMap iteration and memory allocation to create a temporary + QList. + + \snippet code/src_corelib_tools_qmap.cpp keyiterator2 + + QMap::key_iterator is const, it's not possible to modify the key. + + The default QMap::key_iterator constructor creates an uninitialized + iterator. You must initialize it using a QMap function like + QMap::keyBegin() or QMap::keyEnd(). + + \warning Iterators on implicitly shared containers do not work + exactly like STL-iterators. You should avoid copying a container + while iterators are active on that container. For more information, + read \l{Implicit sharing iterator problem}. + + \sa QMap::const_iterator, QMap::iterator +*/ + +/*! \typedef QMap::key_iterator::difference_type + \internal +*/ + +/*! \typedef QMap::key_iterator::iterator_category + \internal +*/ + +/*! \typedef QMap::key_iterator::pointer + \internal +*/ + +/*! \typedef QMap::key_iterator::reference + \internal +*/ + +/*! \typedef QMap::key_iterator::value_type + \internal +*/ + +/*! \fn const T &QMap::key_iterator::operator*() const + + Returns the current item's key. +*/ + +/*! \fn const T *QMap::key_iterator::operator->() const + + Returns a pointer to the current item's key. +*/ + +/*! \fn bool QMap::key_iterator::operator==(key_iterator other) + + Returns \c true if \a other points to the same item as this + iterator; otherwise returns \c false. + + \sa operator!=() +*/ + +/*! \fn bool QMap::key_iterator::operator!=(key_iterator other) + + Returns \c true if \a other points to a different item than this + iterator; otherwise returns \c false. + + \sa operator==() +*/ + +/*! + \fn QMap::key_iterator &QMap::key_iterator::operator++() + + The prefix ++ operator (\c{++i}) advances the iterator to the + next item in the hash and returns an iterator to the new current + item. + + Calling this function on QMap::keyEnd() leads to undefined results. + + \sa operator--() +*/ + +/*! \fn QMap::key_iterator QMap::key_iterator::operator++(int) + + \overload + + The postfix ++ operator (\c{i++}) advances the iterator to the + next item in the hash and returns an iterator to the previous + item. +*/ + +/*! \fn QMap::key_iterator &QMap::key_iterator::operator--() + + The prefix -- operator (\c{--i}) makes the preceding item + current and returns an iterator pointing to the new current item. + + Calling this function on QMap::keyBegin() leads to undefined + results. + + \sa operator++() +*/ + +/*! \fn QMap::key_iterator QMap::key_iterator::operator--(int) + + \overload + + The postfix -- operator (\c{i--}) makes the preceding item + current and returns an iterator pointing to the previous + item. +*/ + +/*! \fn const_iterator QMap::key_iterator::base() const + Returns the underlying const_iterator this key_iterator is based on. +*/ + /*! \fn QDataStream &operator<<(QDataStream &out, const QMap<Key, T> &map) \relates QMap diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h index f3d921c968..b7bd268bda 100644 --- a/src/corelib/tools/qmap.h +++ b/src/corelib/tools/qmap.h @@ -518,6 +518,32 @@ public: }; friend class const_iterator; + class key_iterator + { + const_iterator i; + + public: + typedef typename const_iterator::iterator_category iterator_category; + typedef typename const_iterator::difference_type difference_type; + typedef Key value_type; + typedef const Key *pointer; + typedef const Key &reference; + + explicit key_iterator(const_iterator o) : i(o) { } + + const Key &operator*() const { return i.key(); } + const Key *operator->() const { return &i.key(); } + bool operator==(key_iterator o) const { return i == o.i; } + bool operator!=(key_iterator o) const { return i != o.i; } + + inline key_iterator &operator++() { ++i; return *this; } + inline key_iterator operator++(int) { return key_iterator(i++);} + inline key_iterator &operator--() { --i; return *this; } + inline key_iterator operator--(int) { return key_iterator(i--); } + const_iterator base() const { return i; } + }; + + // STL style inline iterator begin() { detach(); return iterator(d->begin()); } inline const_iterator begin() const { return const_iterator(d->begin()); } @@ -527,6 +553,8 @@ public: inline const_iterator end() const { return const_iterator(d->end()); } inline const_iterator constEnd() const { return const_iterator(d->end()); } inline const_iterator cend() const { return const_iterator(d->end()); } + inline key_iterator keyBegin() const { return key_iterator(begin()); } + inline key_iterator keyEnd() const { return key_iterator(end()); } iterator erase(iterator it); // more Qt |