QMap: add missing qHash() overload
Found in API review, but not deemed important enough to still get into 6.7. Not implementing it for QMultiMap, because there we need to mod out order of equivalent elements. The GHS compiler acted up and tried to compile the noexcept specification, hitting non-existing qHash(QVariant) for QVariantMap and producing a hard error instead of SFINAE'ing out. As a work-around, establish an artificial SFINAE-friendly context, but only for that compiler. [ChangeLog][QtCore][QMap/QHash] Added qHash() overload for QMap. Change-Id: Ia7dbf488e8e5490962118e40581b7c4cc8ed95e5 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
parent
3a2d8c5828
commit
e1f45ad818
@ -5,6 +5,7 @@
|
||||
#ifndef QMAP_H
|
||||
#define QMAP_H
|
||||
|
||||
#include <QtCore/qhashfunctions.h>
|
||||
#include <QtCore/qiterator.h>
|
||||
#include <QtCore/qlist.h>
|
||||
#include <QtCore/qrefcount.h>
|
||||
@ -777,6 +778,31 @@ public:
|
||||
auto result = d->m.equal_range(akey);
|
||||
return {const_iterator(result.first), const_iterator(result.second)};
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef Q_QDOC
|
||||
friend size_t qHash(const QMap &key, size_t seed = 0);
|
||||
#else
|
||||
# ifdef Q_CC_GHS
|
||||
// GHS tries to intantiate qHash() for the noexcept running into a
|
||||
// non-SFINAE'ed hard error... Create an artificial SFINAE context as a
|
||||
// work-around:
|
||||
template <typename M, std::enable_if_t<std::is_same_v<M, QMap>, bool> = true>
|
||||
friend QtPrivate::QHashMultiReturnType<typename M::key_type, typename M::mapped_type>
|
||||
# else
|
||||
using M = QMap;
|
||||
friend size_t
|
||||
# endif
|
||||
qHash(const M &key, size_t seed = 0)
|
||||
noexcept(QHashPrivate::noexceptPairHash<typename M::key_type, typename M::mapped_type>())
|
||||
{
|
||||
if (!key.d)
|
||||
return seed;
|
||||
// don't use qHashRange to avoid its compile-time overhead:
|
||||
return std::accumulate(key.d->m.begin(), key.d->m.end(), seed,
|
||||
QtPrivate::QHashCombine{});
|
||||
}
|
||||
#endif // !Q_QDOC
|
||||
};
|
||||
|
||||
Q_DECLARE_ASSOCIATIVE_ITERATOR(Map)
|
||||
@ -788,6 +814,7 @@ qsizetype erase_if(QMap<Key, T> &map, Predicate pred)
|
||||
return QtPrivate::associative_erase_if(map, pred);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// QMultiMap
|
||||
//
|
||||
|
@ -1389,3 +1389,12 @@
|
||||
|
||||
Returns the number of elements removed, if any.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn template <class Key, class T> QMap<Key, T>::qHash(const QMap &key, size_t seed)
|
||||
\since 6.8
|
||||
|
||||
Returns the hash value for \a key, using \a seed to seed the calculation.
|
||||
|
||||
Types \c Key and \c T must be supported by qHash().
|
||||
*/
|
||||
|
@ -640,16 +640,19 @@ void tst_QMap::operator_eq()
|
||||
QMap<int, int> b;
|
||||
|
||||
QVERIFY(a == b);
|
||||
QCOMPARE(qHash(a), qHash(b));
|
||||
QVERIFY(!(a != b));
|
||||
|
||||
a.insert(1,1);
|
||||
b.insert(1,1);
|
||||
QVERIFY(a == b);
|
||||
QCOMPARE(qHash(a), qHash(b));
|
||||
QVERIFY(!(a != b));
|
||||
|
||||
a.insert(0,1);
|
||||
b.insert(0,1);
|
||||
QVERIFY(a == b);
|
||||
QCOMPARE(qHash(a), qHash(b));
|
||||
QVERIFY(!(a != b));
|
||||
|
||||
// compare for inequality:
|
||||
@ -672,6 +675,7 @@ void tst_QMap::operator_eq()
|
||||
QMap<QString, QString> b;
|
||||
|
||||
QVERIFY(a == b);
|
||||
QCOMPARE(qHash(a), qHash(b));
|
||||
QVERIFY(!(a != b));
|
||||
|
||||
a.insert("Hello", "World");
|
||||
@ -680,6 +684,7 @@ void tst_QMap::operator_eq()
|
||||
|
||||
b.insert("Hello", "World");
|
||||
QVERIFY(a == b);
|
||||
QCOMPARE(qHash(a), qHash(b));
|
||||
QVERIFY(!(a != b));
|
||||
|
||||
a.insert("Goodbye", "cruel world");
|
||||
@ -696,6 +701,7 @@ void tst_QMap::operator_eq()
|
||||
// empty keys and null keys match:
|
||||
b.insert(QString(""), QString());
|
||||
QVERIFY(a == b);
|
||||
QCOMPARE(qHash(a), qHash(b));
|
||||
QVERIFY(!(a != b));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user