Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-82916

qRegisterStreamOperators<T>() has no paired QMetaType::hasRegisteredStreamOperators(int type)

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P3: Somewhat important
    • 6.1.0
    • 5.15.0 Beta1
    • None
    • All
    • 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;
      }
      

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            laknoll Lars Knoll
            icpu Alex Frost
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes