summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSérgio Martins <sergio.martins@kdab.com>2015-07-24 20:30:01 +0100
committerSérgio Martins <sergio.martins@kdab.com>2015-07-28 19:11:12 +0000
commit07f27fcf6d4f046bbea6c3155efa78128e164da4 (patch)
tree177ed098a3924965ef9b1028ae97918e834de7c5 /src
parent75244bf985e248bd3fccac532fc4a9cd1bf7722f (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.cpp19
-rw-r--r--src/corelib/tools/qmap.cpp154
-rw-r--r--src/corelib/tools/qmap.h28
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