I have a multimap with QVariant as key, but it's not working with QByteArray.
The funcion map.values("\xc2\x39\xc7\xe1") is returning all the values of the map.
This is a small example:
#include <QCoreApplication>
#include <QMultiMap>
#include <QVariant>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QMultiMap<QVariant, QString> map;
QByteArray b1("\xc1\x39\xc7\xe1");
QByteArray b2("\xc1\x39\xc7\xe2");
map.insert(QVariant(b1), "TEST1");
map.insert(QVariant(b2), "TEST2");
QStringList values = map.values(QByteArray("\xc1\x39\xc7\xe1"));
return a.exec();
}
I tried also using a QMap to see what happens and it adds only an element to the map.
Can someone explain me this behavior?
What am I doing wrong?
CodePudding user response:
The problem is the unavailability of a suitable operator<. You can use this hack to show the desired behaviour:
bool operator<(const QVariant& lhs, const QVariant& rhs)
{
if (lhs.userType() == QMetaType::QByteArray && rhs.userType() == QMetaType::QByteArray)
{
return lhs.toByteArray() < rhs.toByteArray();
}
// The rest is up to you.
return true;
}
CodePudding user response:
Use QMultiHash
instead of QMultiMap
. QMultiHash
does not require <
operator for the key type. Hashed container should be preferred over map whenever you do not need sorted keys. And I bet you do not not need them sorted because sorting variants (i.e. values of different underlying types) does not make any sense.
CodePudding user response:
It appears to be a bug in Qt, because the operator QVariant::operator<()
does not provide a total ordering, even though QByteArray::operator<()
does. And QMap relies on that (see QMap documentation).
QByteArray b1("\xc1\x39\xc7\xe1");
QByteArray b2("\xc1\x39\xc7\xe2");
QVariant v1(b1);
QVariant v2(b2);
assert(b1 < b2 != b2 < b1); // works as expected for QByteArray
assert(v1 != v2); // make sure the values are actually not equal
assert(v1 < v2 != v2 < v1); // fails for QVariant(QByteArray)
So a QByteArray
works as a key to a QMap, but a QVariant(QByteArray)
does not.