I've got a library, which registers a bunch of metatypes, illustrated by this code:
abstractfoobase.h
namespace foo {
enum FooState { OK, MAYBE };
class AbstractFooBase : public QObject {...};
}
Q_DECLARE_METATYPE(foo::FooState)
There is also a corresponding abstractfoobase.cpp, contents depending on what exactly is implemented in base class.
foousingclass.h:
namespace foo {
class FooUsingClass : public AbstractFooBase {...};
}
Again there is corresponding foousingclass.cpp, which has method implementations etc.
Now, that Q_DECLARE_METATYPE
enables the type for Qt template classes and QVariant
. To enable using the type in queued signals and such, there also needs to be a corresponding call:
qRegisterMetaType<foo::FooState>();
What is(are) the good place(s) to put the qRegisterMetaType
call? I obviously don't want any expllicit initialization call from application code. The registrations must have happened after doing a foo::FooUsingClass *f = new foo::FooUsingClass();
.
In Java I'd put this kind of code in a static initialization block. I can see several ways to do this in C++ too, but none of them seem particularily nice. For example, simply putting these to AbstractFooBase
constructor will cause the registrations being called every time a subclass instance is created, which may be undesired overhead. So those who have done this, where did you put the qRegisterMetaType
calls?
I've recently discovered a simple solution, which works with static libraries as well.
It exploits the fact that qMetaTypeId<>()
is used throughout Qt's meta type system. So, with an explicit template instantiation, we can enforce linkage to abstractfoobase.cpp (otherwise the linker might decide not to if there are no referenced symbols) and ensure that the type is registered statically at program startup:
abstractfoobase.h
#include <QMetaType>
namespace foo {
enum FooState { OK, MAYBE };
}
Q_DECLARE_METATYPE(foo::FooState)
extern template int qMetaTypeId<foo::FooState>();
abstractfoobase.cpp
static const int kFooStateMetaTypeId = qRegisterMetaType<foo::FooState>();
template int qMetaTypeId<foo::FooState>();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With