Preamble
In the process of software development, I had to define enum enumerators in a centralized header file, whereas their use could be in many source files. This is very convenient from the point of view of source organization and dependencies. However, my tasks also required enumeration registration in the Qt metatypes system. About how I did such a registration and will be discussed.
Qt Interview
- I need you to understand my
enum .
- To declare enum as a meta type for QVariant, Q_DECLARE_METATYPE () is suitable. Macros should be called immediately after the enum declaration.
- Well! And if I want to throw my
enum from signals to slots, but shove properties?
- To register enum in the meta-type system, qRegisterMetaType <T> () is required. Please note this is a feature. It must be called somewhere. Preferably, before any flinging and shoving. In main () , for example. And, yes, without Q_DECLARE_METATYPE () nothing happens.
- Hmm ... This is not convenient. I want the whole registration to be limited to one place in the source ...
- What didn't you say right away ?! Use Q_ENUM () ! This wonderful macro will do everything for you! And even more! He will register the conversion from your enum to a QString for QVariant ! You just need to call the macro immediately after the enum declaration inside the class definition inherited from QObject ...
- Wait, what? Need to do this in the classroom? .. And I wanted it globally and for everyone ...
Opportunities
- If it's enough for us to simply store instances of our enum in QVariant , then we need the Q_DECLARE_METATYPE () macro. You can transfer the value through signal slots, you can store it in properties in int , and, if necessary, you can bring it explicitly to our enum .
')
- If it is very important for us to distinguish just int from our enum , or we want to have a pack of invokable methods with the same name, but a difference in the type of the argument, then we can’t do without additional registration in the system of meta-types. You can do this by calling qRegisterMetaType <T> () somewhere before actual use.
- Well, if enum is part of some QObject class, then everything is decided by Q_ENUM () , then you can do anything with it. Even use properties or parameters of a slot in another class as a full type name ( ClassName :: EnumName ).
Decision
My target task, formulated earlier, required full registration in the meta-type system. The last two possibilities suited me. At opportunity number 2, there is a drawback in having to register
enum by explicitly calling a function somewhere in the code. Possibility number 3 lacks the potential complication of source dependencies if you place the
enum inside one of the existing classes that work with it.
But no one bothers us to create a new
QObject- class! In general, for all the header file. And you can disable instantiation of this class. I will give an example (and for a warm-up, there is also a small example of the capabilities of the c ++ 11 standard):
As a result, we have the
Enums class available to everyone, having the necessary
enum , known to the system of meta-types, and not having the ability to create instances of itself!
However, it has some drawbacks. The macro
Q_OBJECT creates, besides a static meta-object, a bundle of never static functions. And our class will never be created! And these functions will never be needed. Alas, this is some waste inevitable. However, starting with Qt 5.5, the
Q_GADGET macro is described in the documentation.
Yes, yes, it is easier than Q_OBJECT , and does not require inheritance from QObject . Allows Q_ENUM , Q_PROPERTY , Q_INVOKABLE only . And for a long time he already exists, we just were silent about him!
Indeed, why were you silent! This is where it will perfectly suit us! Just a couple of changes, and the pants turn into ...
We really do not need the ability to declare properties and
invokable methods. But they are an integral part of the meta-objects, cut off will not work. But now, if you compare the old and the new moc * .cpp to this header file, you can detect the loss of the implementation of static
qt_static_metacall () static and standard
metaObject () ,
qt_metacast () ,
qt_metacall () . Trifle, but nice. For the sake of curiosity, I compared the sizes of binaries, a trifle turned out to be 512 bytes (build Release).
Conclusion
It is quite easy to define
enum in one header file, in the same place and throwing it into the system of meta-types, and then use it in other classes. For example, I had a task to use such an enum in some of the basic logic of the system, while providing the opportunity to select the values of this
enum through the interface. The additional
Q_ENUM feature in the form of enum name registration allowed not to reinvent the wheel, but this is another story. With models and patterns.