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.
qMetaTypeConstructHelper
.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)
^
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
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()
{}
};