c++qtqt5qt5.7

QVariants with QStringList comparison


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


Solution

  • 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