1

I'm having weird observations when comparing QVariants with QStringLists inside.

Code:

QStringList l1, l2;

l1 << "";
l2 << "33" << "434";

const bool le = l1 < l2;
const bool ge = l1 > l2;
const bool eq = l1 == l2;

QVariant v1(l1), v2(l2);

const bool vle = v1 < v2;
const bool vge = v1 > v2;
const bool veq = v1 == v2;

When I modify l1 my comparison results (le, ge and eq) have expected values. But it doesn't affect results for variants at all. I always get vge == true, vle and veq are always false.

Docs say it should work. Am I wrong somewhere or is it Qt bug? I'm using Qt5.7.

EDIT

I've filled a bug report for this issue: https://bugreports.qt.io/browse/QTBUG-54893

Michał Walenciak
  • 4,257
  • 4
  • 33
  • 61
  • I would say you should not expect sensible comparison between QVariants, but anyhow I strongly suspect it's a bug, cf the implementation: https://code.woboq.org/qt5/qtbase/src/corelib/kernel/qvariant.cpp.html#_ZNK8QVariant7compareERKS_ – peppe Jul 20 '16 at 23:20

1 Answers1

2

Nice one.

Here is the exact line in the Qt source code that produces this behaviour: https://github.com/qt/qtbase/blob/4e41babd0337473a1078d3a5f3367cc1fc5f2935/src/corelib/kernel/qvariant.cpp#L3564

There is no special case for QStringList, therefore QVariant::toString() is called, which returns an empty string if there are no, or more than one entries in the QStringList, or the first entry if there is just the one.

Comparing two empty strings returns 0. Comparing two QVariant with one entry each results in the comparison on both strings and comparing two QVariant with more than one entry causes the type to be compared, yielding a return value of 1 in all cases, which results in < always returning false and > always true.

Looks like a bug to me.

Examples:

// expected behaviour when both have a single entry
QStringList l, m;
l << "0";
m << "1";
QVariant less(l);
QVariant more(m);
less < more; // true
less > more; // false

QStringList l, m;
l << "1";
m << "0";
QVariant less(l);
QVariant more(m);
less < more; // false
less > more; // true

// ... or both have no entry
QStringList l, m;
QVariant less(l);
QVariant more(m);
less < more; // false
more < less; // false
more == less; // true

// otherwise, things get weird
QStringList l, m;
l << "0" << "1";
m << "2" << "3";
QVariant less(l);
QVariant more(m);
less < more; // false
more < less; // false
less > more; // true
more > less; // true
less == more; // false

QStringList l, m;
m << "2" << "3";
QVariant less(l);
QVariant more(m);
less < more; // false
more < less; // false
less > more; // true
more > less; // true
less == more; // false

etc.


Edit: pushed a fix explicitly comparing QStringLists in QVariants: https://codereview.qt-project.org/#/c/165886/1

Clemens Sielaff
  • 708
  • 10
  • 15