Home > front end >  How Could I Register Types With A Deleted Copy Constructor To QMetaType?
How Could I Register Types With A Deleted Copy Constructor To QMetaType?

Time:07-13

The Problem:

I want to create an object instance at runtime using QMetaType by the type name. But I couldn't register the type because it's a QObject and I don't have access to the implementation to change it.

Duplicate Question(s):

Reproducible Example Of The Problem:

The CMake: CMakeLists.txt

#include <QMetaType>
#include <QObject>

class MyObject : public QObject {
  Q_OBJECT
};

#include "main.moc"

int main()
{
  qRegisterMetaType<MyObject>("MyObject");
  int const type_id = QMetaType::type("MyObject");
}

It will fail:

/tmp/untitled1/main.cc:12:3: note: in instantiation of function template specialization 'qRegisterMetaType<MyObject>' requested here
  qRegisterMetaType<MyObject>("MyObject");
  ^
/tmp/untitled1/main.cc:4:18: note: copy constructor of 'MyObject' is implicitly deleted because base class 'QObject' has a deleted copy constructor
class MyObject : public QObject {
                 ^
/opt/Qt/5.15.2/gcc_64/include/QtCore/qobject.h:467:20: note: 'QObject' has been explicitly marked deleted here
    Q_DISABLE_COPY(QObject)
                   ^

CodePudding user response:

A Non-portable And Non-documented Solution:

Specialize the QtMetaTypePrivate::QMetaTypeFunctionHelper for your type:

namespace QtMetaTypePrivate
{
template <>
struct QMetaTypeFunctionHelper<MyObject, true> {
  static void Destruct(void *address)
  {
    static_cast<MyObject *>(address)->~MyObject();
  }

  static void *Construct(void *where, void const *address)
  {
    if (address != nullptr) {
      delete static_cast<MyObject const *>(address);
    }
    return where != nullptr ? new (where) MyObject : new MyObject;
  }
};
}  // namespace QtMetaTypePrivate

Using QMetaObject, But Requires A Q_INVOKABLE Constructor:

By not providing a Public Copy Constructor one solution is to register a pointer type:

qRegisterMetaType<MyObject*>();

And then retrieve the type ID using "MyObject*" string and the QMetaObject using QMetaType::metaObjectForType:

int const type_id = QMetaType::type("MyObject*");
QMetaObject const* metaObject = QMetaType::metaObjectForType(type_id);

And now we could create an instance of the class:

QObject* instance = metaObject->newInstance();

But still, we need to have an invokable public constructor:

class MyObject : public QObject {
  Q_OBJECT
public:
  Q_INVOKABLE MyObject()
  {}
};

https://interest.qt-project.narkive.com/zP6wxOZf/how-to-create-qobject-derived-class-instance-from-class-name#post7

  • Related