Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How and when to use Q_DECLARE_METATYPE

Tags:

c++

qt

qmetatype

I need to cast a QSqlRecord to QVariant and back throughout my project. In order to do so I added

Q_DECLARE_METATYPE(QSqlRecord);

in the .h files of the classes which require the casting. I also have a base class from which several children inherit, in this case I assume it is sufficient to include the Q_DECLARE_METATYPE only once in the base class. I therefore have for example:

  • widgetBaseClass: declares metatype
  • widgetChildClass1: inherits widgetBaseClass does not declare metatype
  • widgetChildClass2: inherits widgetBaseClass does not declare metatype
  • myTableModel: declares metatype

When I try to run the program like this I get

Redefinition of 'QMetaTypeId<QSqlRecord>

from widgetBaseClass, pointing to the previous declaration in myTableModel. If on the other hand I remove the declaration I get:

static_assert failed "Type is not registered, please use the Q_DECLARE_METATYPE macro to make it known to Qt's meta-object system");

From how I understand the workings of Q_DECLARE_METATYPE this means that if i declare it, it result in an error because it was already declared somewhere else, but if I don't declare it I cannot cast from QVariant, because it does not recognise the object as a valid QVariant, what am I missing?

like image 600
Nicolo Castro Avatar asked Mar 16 '17 09:03

Nicolo Castro


People also ask

What is this qmetatype macro for?

This macro makes the type Type known to QMetaType as long as it provides a public default constructor, a public copy constructor and a public destructor. It is needed to use the type Type as a custom type in QVariant. This macro requires that Type is a fully defined type at the point where it is used.

What is QQ_declare_metatype macro?

Q_DECLARE_METATYPE (Type) This macro makes the type Type known to QMetaType as long as it provides a public default constructor, a public copy constructor and a public destructor. It is needed to use the type Type as a custom type in QVariant. This macro requires that Type is a fully defined type at the point where it is used.

How to specialise the template class qmetatypeid with type?

But if we want to use the type in queued signal and slot connections or in QObject's property system, you have to call qRegisterMetaType () since the names are resolved at runtime. This macro is used to specialise the template class QMetaTypeId with typename TYPE, in which, a static member function qt_metatype_id () is defined.

What is qmetatype in qvariant?

The QMetaType class manages named types in the meta-object system. The class is used as a helper to marshall types in QVariant and in queued signals and slots connections.


2 Answers

You should place Q_DECLARE_METATYPE(QSqlRecord) in only one header and then just include it everewhere it needed. Q_DECLARE_METATYPE(QSqlRecord) have to be outside any classes and namespaces. From Qt documentation:

Ideally, this macro should be placed below the declaration of the class or struct. If that is not possible, it can be put in a private header file which has to be included every time that type is used in a QVariant

like image 162
em2er Avatar answered Sep 28 '22 03:09

em2er


You use Q_DECLARE_METATYPE on classes with public constructor, destructor, copy-constructor, so QSqlRecord fits. Just make sure that this macro is used only once per class declaration. Possibly you missed some #pragma once?

Use it on your own classes, after declaration of the class, outside namespace braces:

//mystruct.h
namespace MyNamespace
{
struct MyStruct
{
    int i;
    ...
};
}

Q_DECLARE_METATYPE(MyNamespace::MyStruct)

See documentation here: http://doc.qt.io/qt-5/qmetatype.html#Q_DECLARE_METATYPE

like image 31
MateuszL Avatar answered Sep 28 '22 01:09

MateuszL