[Interest] problem converting QVariant UserType to Int

glenn popelka gpp at popelka.org
Wed Aug 27 01:18:31 CEST 2014


Qt-5.3.1, Fedora 20, g++4.8.3. Also tested on Windows7 with Qt5.2.1 and 
5.3.1.

I’m trying to take advantage of the new functionality in Qt5.2 allowing 
conversion from a QVariant holding a UserType directly to Integer. I 
think this may be a bug, but I could be wrong...

Here's my code, it can all go into main.cpp and built in qtCreator. I 
hope it's readable:

#include <QCoreApplication>

#include <QString>
#include <QMetaType>
#include <QDebug>

class UserTypeClass
{
public:
UserTypeClass( int data = 0 );
UserTypeClass( const UserTypeClass& );

int toInt( bool *ok ) const;

private:
int m_data;
};

Q_DECLARE_METATYPE( UserTypeClass );

//---------------------------------------------------------------
UserTypeClass::UserTypeClass( int data ) : m_data( data & 0x03 )
{
qDebug() << "UserTypeClass ctor " << this << ' ' << data << " -> " << 
m_data;
}
//----------------------------------------------------------------
int UserTypeClass::toInt( bool* ok ) const
{
if (ok)
{
*ok = (m_data >= 0 && m_data < 4);
qDebug() << "UserTypeClass::toInt " << this << ' ' << *ok << ' ' << m_data;
}
else
{
qDebug() << "UserTypeClass::toInt " << this << " not set " << m_data;
}
return m_data;
}
//---------------------------------------------------------------
UserTypeClass::UserTypeClass( const UserTypeClass& other ) : m_data( 
other.m_data )
{
qDebug() << "UserTypeClass copy " << &other << " to " << this << ' ' << 
m_data;
}

//---------------------------------------------------------------
int main(int argc, char **argv)
{
Q_UNUSED(argc); Q_UNUSED(argv);

int (UserTypeClass::*f)(bool*) const = &UserTypeClass::toInt;
QMetaType::registerConverter< UserTypeClass, int > ( f );

QVariant value;
value.setValue(UserTypeClass(3));
bool b;
int i = value.toInt(&b);
qDebug() << "main(): value = " << i;
}


Output:
=====
UserTypeClass ctor 0x7fff6aa02710 3 -> 3
UserTypeClass copy 0x7fff6aa02710 to 0x194eb20 3 (UserType copied into 
QVariant)
UserTypeClass::toInt 0x7fff6aa026f0 false 26537440 (1st conversion 
failed, where did 26537440 come from?)
UserTypeClass::toInt 0x194eb20 true 3 (second attempt seems correct, I 
expect 3.)
main(): value = 3
=====

The call to value.toInt(&b) in main generates a call to 
QVariant::qNumVariantToHelper, which can do 2 attempts to make the 
conversion, both of which call back to UserTypeClass::toInt():

from QVariant.cpp:

template <typename T>
inline T qNumVariantToHelper(const QVariant::Private &d,
const HandlersManager &handlerManager, bool *ok, const T& val)
{
...some code omitted...

T ret = 0;
if ((d.type >= QMetaType::User || t >= QMetaType::User)
&& QMetaType::convert(&val, d.type, &ret, t)) {
return ret;
}

if (!handlerManager[d.type]->convert(&d, t, &ret, ok) && ok)
*ok = false;
return ret;
}


The first conversion attempt fails because UserTypeClass::toInt() finds 
m_Data > 3. I had to contrive that restriction to demonstrate the 
problem. Since I am able to return false, the second conversion is tried 
next and it turns out to be the correct one. Note that 'this' from the 
copy of UserTypeClass (line 2 of output) is the same as 'this' from the 
second attempt at conversion (line 4 of output).

Am I doing this correctly? What is the difference between the two 
conversion attempts in QVariant::qNumVariantToHelper?


Thanks,

glenn



More information about the Interest mailing list