c++qtqvariant

Inconsistent conversion of QVariant to double


I'm having trouble understanding the behaviour of QVariant::canConvert and QVariant::toDouble. I'd expect that both of these would return false if the underlying variant data is, say, a QString, but I'm getting different results as shown:

#include <QString>
#include <QVariant>
#include <QDebug>

int main(int argc, char *argv[])
{

    QString not_a_number("foo");
    QVariant variant(not_a_number);

    auto can_convert_1 = variant.canConvert<double>();
    auto can_convert_2 = false;
    variant.toDouble(&can_convert_2);

    qDebug() << can_convert_1 << can_convert_2; //prints: true false
}

The method canConvert returns true whereas the toDouble return false. Can someone explain this behaviour please?

I'm using Qt 5.15.7 on Windows with Visual Studio 2019.


Solution

  • double QVariant::toDouble(bool *ok = nullptr) const
    

    and

    template <typename T> bool QVariant::canConvert() const
    

    have two very different meanings. bool* ok will return true if the conversion has actually succeded, while canConvert() tell if the source type could be converted to the destination type.

    QString can be converted to double? Maybe.

    QString is one of the type allowed to be converted to double? Yes, so canConvert() will always return true, but toDouble() of course will fail.

    Indeed if you try

    auto convert = [](auto&& string){
       QString not_a_number(string);
       QVariant variant(not_a_number);
    
       auto can_convert_1 = variant.canConvert<double>();
       auto can_convert_2 = false;
       variant.toDouble(&can_convert_2);
    
       qDebug() << can_convert_1 << can_convert_2;
    };
    
    convert("foo");
    convert("5");
    

    will print

    true false
    true true
    

    Both are QString, so canConvert succed, toDouble only succed for "5" can actually be converted to double.