From 9c124b1b0a3730978699b8a6420308b5e5ab4e4e Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 26 Nov 2018 10:37:10 +0100 Subject: Qt 6: Deprecate QHash::insertMulti [ChangeLog][QtCore][QHash] insertMulti(), unite() and values(const Key &key) are now deprecated. Please use QMultiHash instead. Change-Id: Ic14907fd5fd38d585708e2dcf2c0200d221ebb25 Reviewed-by: Timur Pocheptsov --- .../doc/snippets/code/src_corelib_tools_qhash.cpp | 16 -- src/corelib/kernel/qvariant.cpp | 2 +- src/corelib/kernel/qvariant.h | 2 +- src/corelib/serialization/qdatastream.h | 3 + src/corelib/tools/qhash.cpp | 102 +++++---- src/corelib/tools/qhash.h | 250 +++++++++++++-------- src/dbus/qdbusargument.h | 2 +- 7 files changed, 217 insertions(+), 160 deletions(-) diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp index 9813cc98d5..a140175956 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qhash.cpp @@ -119,22 +119,6 @@ hash.insert("plenty", 2000); //! [9] -//! [10] -QList values = hash.values("plenty"); -for (int i = 0; i < values.size(); ++i) - cout << values.at(i) << Qt::endl; -//! [10] - - -//! [11] -QHash::iterator i = hash.find("plenty"); -while (i != hash.end() && i.key() == "plenty") { - cout << i.value() << Qt::endl; - ++i; -} -//! [11] - - //! [12] QHash hash; ... diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 40a401361d..5e27119729 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -972,7 +972,7 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) const QVariantMap *map = v_cast(d); const auto end = map->end(); for (auto it = map->begin(); it != end; ++it) - hash->insertMulti(it.key(), it.value()); + static_cast *>(hash)->insert(it.key(), it.value()); #ifndef QT_BOOTSTRAPPED } else if (d->type == QMetaType::QCborValue) { if (!v_cast(d)->isMap()) diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index f48419c934..6739643f89 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -825,7 +825,7 @@ namespace QtPrivate { QVariantHash l; l.reserve(iter.size()); for (QAssociativeIterable::const_iterator it = iter.begin(), end = iter.end(); it != end; ++it) - l.insertMulti(it.key().toString(), it.value()); + static_cast &>(l).insert(it.key().toString(), it.value()); return l; } return QVariantValueHelper::invoke(v); diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h index d9d4a4fcd3..4d827772c8 100644 --- a/src/corelib/serialization/qdatastream.h +++ b/src/corelib/serialization/qdatastream.h @@ -301,7 +301,10 @@ QDataStream &readAssociativeContainer(QDataStream &s, Container &c) c.clear(); break; } +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED c.insertMulti(k, t); +QT_WARNING_POP } return s; diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index dcac91778f..3ff8f886f1 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -1120,21 +1120,6 @@ uint qHash(long double key, uint seed) noexcept \snippet code/src_corelib_tools_qhash.cpp 9 - However, you can store multiple values per key by using - insertMulti() instead of insert() (or using the convenience - subclass QMultiHash). If you want to retrieve all - the values for a single key, you can use values(const Key &key), - which returns a QList: - - \snippet code/src_corelib_tools_qhash.cpp 10 - - The items that share the same key are available from most - recently to least recently inserted. A more efficient approach is - to call find() to get the iterator for the first item with a key - and iterate from there: - - \snippet code/src_corelib_tools_qhash.cpp 11 - If you only need to extract the values from a hash (not the keys), you can also use \l{foreach}: @@ -1435,9 +1420,8 @@ uint qHash(long double key, uint seed) noexcept /*! \fn template int QHash::remove(const Key &key) Removes all the items that have the \a key from the hash. - Returns the number of items removed which is usually 1 but will - be 0 if the key isn't in the hash, or greater than 1 if - insertMulti() has been used with the \a key. + Returns the number of items removed which is 1 if the key exists in the hash, + and 0 otherwise. \sa clear(), take(), QMultiHash::remove() */ @@ -1507,27 +1491,25 @@ uint qHash(long double key, uint seed) noexcept /*! \fn template QList QHash::uniqueKeys() const \since 4.2 + \obsolete Returns a list containing all the keys in the map. Keys that occur multiple times in the map (because items were inserted with insertMulti(), or unite() was used) occur only once in the returned list. - \sa keys(), values() + \sa QMultiHash::uniqueKeys() */ /*! \fn template QList QHash::keys() const Returns a list containing all the keys in the hash, in an arbitrary order. Keys that occur multiple times in the hash - (because items were inserted with insertMulti(), or unite() was - used) also occur multiple times in the list. - - To obtain a list of unique keys, where each key from the map only - occurs once, use uniqueKeys(). + (because the method is operating on a QMultiHash) also occur + multiple times in the list. The order is guaranteed to be the same as that used by values(). - \sa uniqueKeys(), values(), key() + \sa QMultiMap::uniqueKeys(), values(), key() */ /*! \fn template QList QHash::keys(const T &value) const @@ -1555,7 +1537,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QList QHash::values(const Key &key) const - + \obsolete \overload Returns a list of all the values associated with the \a key, @@ -1592,6 +1574,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template int QHash::count(const Key &key) const + \obsolete Returns the number of items associated with the \a key. @@ -1803,8 +1786,6 @@ uint qHash(long double key, uint seed) noexcept If there are multiple items with the \a key, the most recently inserted item's value is replaced with \a value. - - \sa insertMulti() */ /*! \fn template void QHash::insert(const QHash &other) @@ -1820,6 +1801,7 @@ uint qHash(long double key, uint seed) noexcept */ /*! \fn template QHash::iterator QHash::insertMulti(const Key &key, const T &value) + \obsolete Inserts a new item with the \a key and a value of \a value. @@ -1828,16 +1810,17 @@ uint qHash(long double key, uint seed) noexcept different from insert(), which overwrites the value of an existing item.) + This function is obsolete. Use QMultiHash or QMultiMap instead. + \sa insert(), values() */ /*! \fn template QHash &QHash::unite(const QHash &other) + \obsolete Inserts all the items in the \a other hash into this hash. If a key is common to both hashes, the resulting hash will contain the key multiple times. - - \sa insertMulti() */ /*! \fn template bool QHash::empty() const @@ -1978,10 +1961,7 @@ uint qHash(long double key, uint seed) noexcept \snippet code/src_corelib_tools_qhash.cpp 17 Unlike QMap, which orders its items by key, QHash stores its - items in an arbitrary order. The only guarantee is that items that - share the same key (because they were inserted using - QHash::insertMulti()) will appear consecutively, from the most - recently to the least recently inserted value. + items in an arbitrary order. Let's see a few examples of things we can do with a QHash::iterator that we cannot do with a QHash::const_iterator. @@ -2048,7 +2028,7 @@ uint qHash(long double key, uint seed) noexcept There is no direct way of changing an item's key through an iterator, although it can be done by calling QHash::erase() - followed by QHash::insert() or QHash::insertMulti(). + followed by QHash::insert(). \sa value() */ @@ -2210,7 +2190,7 @@ uint qHash(long double key, uint seed) noexcept Unlike QMap, which orders its items by key, QHash stores its items in an arbitrary order. The only guarantee is that items that share the same key (because they were inserted using - QHash::insertMulti()) will appear consecutively, from the most + a QMultiHash) will appear consecutively, from the most recently to the least recently inserted value. Multiple iterators can be used on the same hash. However, be aware @@ -2543,18 +2523,22 @@ uint qHash(long double key, uint seed) noexcept It inherits QHash and extends it with a few convenience functions that make it more suitable than QHash for storing multi-valued hashes. A multi-valued hash is a hash that allows multiple values - with the same key; QHash normally doesn't allow that, unless you - call QHash::insertMulti(). + with the same key. Because QMultiHash inherits QHash, all of QHash's functionality also applies to QMultiHash. For example, you can use isEmpty() to test whether the hash is empty, and you can traverse a QMultiHash using - QHash's iterator classes (for example, QHashIterator). But in - addition, it provides an insert() function that corresponds to - QHash::insertMulti(), and a replace() function that corresponds to + QHash's iterator classes (for example, QHashIterator). But opposed to + QHash, it provides an insert() function will allow the insertion of + multiple items with the same key. The replace() function corresponds to QHash::insert(). It also provides convenient operator+() and operator+=(). + Unlike QMultiMap, QMultiHash does not provide and ordering of the + inserted items. The only guarantee is that items that + share the same key will appear consecutively, from the most + recently to the least recently inserted value. + Example: \snippet code/src_corelib_tools_qhash.cpp 24 @@ -2645,7 +2629,8 @@ uint qHash(long double key, uint seed) noexcept \sa replace() */ -/*! \fn template QMultiHash &QMultiHash::operator+=(const QMultiHash &other) +/*! \fn template QMultiHash &QMultiHash::unite(const QMultiHash &other) + \since 5.13 Inserts all the items in the \a other hash into this hash and returns a reference to this hash. @@ -2653,6 +2638,32 @@ uint qHash(long double key, uint seed) noexcept \sa insert() */ +/*! \fn template QList QHash::uniqueKeys() const + \since 5.13 + + Returns a list containing all the keys in the map. Keys that occur multiple + times in the map occur only once in the returned list. + + \sa keys(), values() +*/ + +/*! \fn template QList QMultiHash::values(const Key &key) const + \overload + + Returns a list of all the values associated with the \a key, + from the most recently inserted to the least recently inserted. + + \sa count(), insert() +*/ + +/*! \fn template QMultiHash &QMultiHash::operator+=(const QMultiHash &other) + + Inserts all the items in the \a other hash into this hash + and returns a reference to this hash. + + \sa unit(), insert() +*/ + /*! \fn template QMultiHash QMultiHash::operator+(const QMultiHash &other) const Returns a hash that contains all the items in this hash in @@ -2682,6 +2693,13 @@ uint qHash(long double key, uint seed) noexcept \sa QHash::remove() */ +/*! \fn template int QMultiHash::count(const Key &key) const + + Returns the number of items associated with the \a key. + + \sa contains(), insert() +*/ + /*! \fn template int QMultiHash::count(const Key &key, const T &value) const \since 4.3 diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h index 89697b1fd1..0b8a0b283d 100644 --- a/src/corelib/tools/qhash.h +++ b/src/corelib/tools/qhash.h @@ -308,12 +308,14 @@ public: T &operator[](const Key &key); const T operator[](const Key &key) const; - QList uniqueKeys() const; QList keys() const; QList keys(const T &value) const; QList values() const; - QList values(const Key &key) const; - int count(const Key &key) const; +#if QT_DEPRECATED_SINCE(5, 15) + QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QList uniqueKeys() const; + QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QList values(const Key &key) const; + QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") int count(const Key &key) const; +#endif class const_iterator; @@ -388,6 +390,7 @@ public: { friend class iterator; friend class QHash; + friend class QMultiHash; friend class QSet; QHashData::Node *i; @@ -527,8 +530,10 @@ public: const_iterator constFind(const Key &key) const; iterator insert(const Key &key, const T &value); void insert(const QHash &hash); - iterator insertMulti(const Key &key, const T &value); - QHash &unite(const QHash &other); +#if QT_DEPRECATED_SINCE(5, 15) + QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") iterator insertMulti(const Key &key, const T &value); + QT_DEPRECATED_X("Use QMultiHash for hashes storing multiple values with the same key.") QHash &unite(const QHash &other); +#endif // STL compatibility typedef T mapped_type; @@ -570,6 +575,7 @@ private: #endif } friend class QSet; + friend class QMultiHash; }; @@ -607,38 +613,6 @@ QHash::createNode(uint ah, const Key &akey, const T &avalue, Node **anex return node; } -template -Q_INLINE_TEMPLATE QHash &QHash::unite(const QHash &other) -{ - if (d == &QHashData::shared_null) { - *this = other; - } else { -#if QT_DEPRECATED_SINCE(5, 15) - QHash copy(other); - const_iterator it = copy.constEnd(); - while (it != copy.constBegin()) { - it.i = QHashData::previousNode(it.i); - insertMulti(it.key(), it.value()); - } -#else - QHash copy(other); - const_iterator it = copy.cbegin(); - const const_iterator end = copy.cend(); - while (it != end) { - const auto rangeStart = it++; - while (it != end && rangeStart.key() == it.key()) - ++it; - const qint64 last = std::distance(rangeStart, it) - 1; - for (qint64 i = last; i >= 0; --i) { - auto next = std::next(rangeStart, i); - insertMulti(next.key(), next.value()); - } - } -#endif - } - return *this; -} - template Q_OUTOFLINE_TEMPLATE void QHash::freeData(QHashData *x) { @@ -697,26 +671,6 @@ Q_INLINE_TEMPLATE const T QHash::value(const Key &akey, const T &adefaul } } -template -Q_OUTOFLINE_TEMPLATE QList QHash::uniqueKeys() const -{ - QList res; - res.reserve(size()); // May be too much, but assume short lifetime - const_iterator i = begin(); - if (i != end()) { - for (;;) { - const Key &aKey = i.key(); - res.append(aKey); - do { - if (++i == end()) - goto break_out_of_outer_loop; - } while (aKey == i.key()); - } - } -break_out_of_outer_loop: - return res; -} - template Q_OUTOFLINE_TEMPLATE QList QHash::keys() const { @@ -775,32 +729,6 @@ Q_OUTOFLINE_TEMPLATE QList QHash::values() const return res; } -template -Q_OUTOFLINE_TEMPLATE QList QHash::values(const Key &akey) const -{ - QList res; - Node *node = *findNode(akey); - if (node != e) { - do { - res.append(node->value); - } while ((node = node->next) != e && node->key == akey); - } - return res; -} - -template -Q_OUTOFLINE_TEMPLATE int QHash::count(const Key &akey) const -{ - int cnt = 0; - Node *node = *findNode(akey); - if (node != e) { - do { - ++cnt; - } while ((node = node->next) != e && node->key == akey); - } - return cnt; -} - template Q_INLINE_TEMPLATE const T QHash::operator[](const Key &akey) const { @@ -866,18 +794,6 @@ Q_INLINE_TEMPLATE void QHash::insert(const QHash &hash) } } -template -Q_INLINE_TEMPLATE typename QHash::iterator QHash::insertMulti(const Key &akey, - const T &avalue) -{ - detach(); - d->willGrow(); - - uint h; - Node **nextNode = findNode(akey, &h); - return iterator(createNode(h, akey, avalue, nextNode)); -} - template Q_OUTOFLINE_TEMPLATE int QHash::remove(const Key &akey) { @@ -1128,11 +1044,12 @@ public: inline typename QHash::iterator replace(const Key &key, const T &value) { return QHash::insert(key, value); } - inline typename QHash::iterator insert(const Key &key, const T &value) - { return QHash::insertMulti(key, value); } + typename QHash::iterator insert(const Key &key, const T &value); + + inline QMultiHash &unite(const QMultiHash &other); inline QMultiHash &operator+=(const QMultiHash &other) - { this->unite(other); return *this; } + { return unite(other); } inline QMultiHash operator+(const QMultiHash &other) const { QMultiHash result = *this; result += other; return result; } @@ -1141,13 +1058,27 @@ public: using QHash::count; using QHash::find; using QHash::constFind; + using QHash::values; + using QHash::findNode; + using QHash::createNode; + using QHash::concrete; + using QHash::detach; + + using typename QHash::Node; + using typename QHash::iterator; + using typename QHash::const_iterator; bool contains(const Key &key, const T &value) const; int remove(const Key &key, const T &value); + int count(const Key &key) const; int count(const Key &key, const T &value) const; + QList uniqueKeys() const; + + QList values(const Key &akey) const; + typename QHash::iterator find(const Key &key, const T &value) { typename QHash::iterator i(find(key)); typename QHash::iterator end(this->end()); @@ -1175,6 +1106,50 @@ private: const T operator[](const Key &key) const; }; +template +Q_INLINE_TEMPLATE typename QHash::iterator QMultiHash::insert(const Key &akey, const T &avalue) +{ + detach(); + this->d->willGrow(); + + uint h; + Node **nextNode = findNode(akey, &h); + return iterator(createNode(h, akey, avalue, nextNode)); +} + +template +Q_INLINE_TEMPLATE QMultiHash &QMultiHash::unite(const QMultiHash &other) +{ + if (this->d == &QHashData::shared_null) { + *this = other; + } else { +#if QT_DEPRECATED_SINCE(5, 15) + QMultiHash copy(other); + const_iterator it = copy.constEnd(); + while (it != copy.constBegin()) { + it.i = QHashData::previousNode(it.i); + insert(it.key(), it.value()); + } +#else + const QMultiHash copy(other); + const_iterator it = copy.cbegin(); + const const_iterator end = copy.cend(); + while (it != end) { + const auto rangeStart = it++; + while (it != end && rangeStart.key() == it.key()) + ++it; + const qint64 last = std::distance(rangeStart, it) - 1; + for (qint64 i = last; i >= 0; --i) { + auto next = std::next(rangeStart, i); + insert(next.key(), next.value()); + } + } +#endif + } + return *this; +} + + template Q_INLINE_TEMPLATE bool QMultiHash::contains(const Key &key, const T &value) const { @@ -1212,7 +1187,84 @@ Q_INLINE_TEMPLATE int QMultiHash::count(const Key &key, const T &value) return n; } -template +template +Q_OUTOFLINE_TEMPLATE QList QMultiHash::uniqueKeys() const +{ + QList res; + res.reserve(QHash::size()); // May be too much, but assume short lifetime + typename QHash::const_iterator i = QHash::begin(); + if (i != QHash::end()) { + for (;;) { + const Key &aKey = i.key(); + res.append(aKey); + do { + if (++i == QHash::end()) + goto break_out_of_outer_loop; + } while (aKey == i.key()); + } + } +break_out_of_outer_loop: + return res; +} + +#if QT_DEPRECATED_SINCE(5, 15) + +template +Q_OUTOFLINE_TEMPLATE typename QHash::iterator QHash::insertMulti(const Key &key, const T &value) { + return static_cast *>(this)->insert(key, value); +} + +template +Q_OUTOFLINE_TEMPLATE QHash &QHash::unite(const QHash &other) { + return static_cast *>(this)->unite(other); +} + +template +Q_OUTOFLINE_TEMPLATE QList QHash::values(const Key &akey) const +{ + return static_cast *>(this)->values(akey); +} + +template +Q_OUTOFLINE_TEMPLATE int QHash::count(const Key &akey) const +{ + return static_cast *>(this)->count(akey); +} + +template +Q_OUTOFLINE_TEMPLATE QList QHash::uniqueKeys() const +{ + return static_cast *>(this)->uniqueKeys(); +} +#endif + +template +Q_OUTOFLINE_TEMPLATE QList QMultiHash::values(const Key &akey) const +{ + QList res; + Node *node = *findNode(akey); + if (node != this->e) { + do { + res.append(node->value); + } while ((node = node->next) != this->e && node->key == akey); + } + return res; +} + +template +Q_OUTOFLINE_TEMPLATE int QMultiHash::count(const Key &akey) const +{ + int cnt = 0; + Node *node = *findNode(akey); + if (node != this->e) { + do { + ++cnt; + } while ((node = node->next) != this->e && node->key == akey); + } + return cnt; +} + +template class QHashIterator { typedef typename QHash::const_iterator const_iterator; diff --git a/src/dbus/qdbusargument.h b/src/dbus/qdbusargument.h index b7cd4c8989..340f11bf5d 100644 --- a/src/dbus/qdbusargument.h +++ b/src/dbus/qdbusargument.h @@ -370,7 +370,7 @@ inline const QDBusArgument &operator>>(const QDBusArgument &arg, QHash & T value; arg.beginMapEntry(); arg >> key >> value; - map.insertMulti(key, value); + static_cast &>(map).insert(key, value); arg.endMapEntry(); } arg.endMap(); -- cgit v1.2.3