Details
-
Bug
-
Resolution: Done
-
P3: Somewhat important
-
5.15.0 Beta1
-
None
-
-
60ea10e70b408b87243b5f0511b91c4848a7ab6f (qt/qtbase/dev)
Description
qRegisterStreamOperators<T>() saves function pointers into private class QMetaTypeInterface (qmetatype_p.h).
However, there is no way to find out if type can be serialized. Well, there is one - serialize QVariant::fromValue(T()) once and see what would happen (qvariant.cpp: void QVariant::save(QDataStream &s) const)
if (!QMetaType::save(s, d.type, constData())) { qWarning("QVariant::save: unable to save type '%s' (type id: %d).\n", QMetaType::typeName(d.type), d.type); Q_ASSERT_X(false, "QVariant::save", "Invalid type to save"); }
It might be OK if type is small and cheap. Yet sometimes it become troublesome, especially if one tries to wrap QObject::connect to add additional conditions on parameters.
bool SignalSerializer::listen(QObject *sender, int sigIndex) { QMetaMethod method = sender->metaObject()->method(sigIndex); for (int i = 0; i < method.parameterCount(); ++i) { // if (!QMetaType::hasRegisteredStreamOperators(method.parameterType(i))) { // qWarning("Parameter %s can not be serialized: type %s", i, QMetaType::typename((method.parameterType(i))); // return false; // } } const bool connected = QMetaObject::connect( sender, sigIndex, this, memberOffset2, Qt::DirectConnection, nullptr); if (!connected) { qWarning("SignalSerializer::connect returned false. Unable to connect."); } return connected; }
The solution is much simple
bool QMetaType::hasRegisteredStreamOperators(int idx) { if (idx < User) { switch(idx) { /* ... */ } } QVector<QCustomTypeInfo> *ct = customTypes(); if (!ct) return false; QReadLocker locker(customTypesLock()); QCustomTypeInfo &inf = (*ct)[idx - User]; return inf.saveOp !=nullptr && inf.loadOp != nullptr; }