2

I would like to use Qt's reflection mechanism since C++ lacks of this feature. It seems to work, but calling all the macros and helper functions is very tedious. For example to register an enum as a proper meta type I had to go through all the following steps:

  1. Declare an enum inside of a wrapper class that contains the Q_GADGET macro.
  2. Register the enum using the Q_ENUM macro just after that.
  3. Register the class containing the enum: Q_DECLARE_METATYPE(MyClass)
  4. Call qRegisterMetaType<..>() for the type of the wrapping class and for each declared enum.

Now I know that some of the steps can be omitted if part of the full functionality is not required. But that is not what I am looking for, I need to use enums within signals and I need to be able to get the the meta method of a signal and query it for it's parameters type.

But still I can't help thinking that there must be a better/simpler way to do this.

Nils
  • 13,319
  • 19
  • 86
  • 108
  • What do you need to do exactly? Maybe indeed you just need a subset of all of that. – peppe Nov 08 '16 at 09:51
  • read the question – Nils Nov 08 '16 at 09:56
  • 1
    "I need to use enums within signals and I need to be able to get the the meta method of a signal and query it for it's parameters type" does not fully answer my question. You don't need `Q_DECLARE_METATYPE` for the class this. You don't need `qRegisterMetaType` for the class for this. That's why I was wondering why you're going "all in" and registering everything :) – peppe Nov 08 '16 at 10:01
  • Yes it works without qRegisterMetaType for the class, but then another use case might not work. As I said I want to be able to fully use it without having to think about every possible use case when declaring a type. – Nils Nov 08 '16 at 10:20
  • 2
    Keep in mind that there's a lot of legacy involved. In particular, Qt strongly predates C++11. Early versions didn't even rely on templates, and templates are still a sore point to `moc`. – MSalters Nov 08 '16 at 11:03

1 Answers1

6

Unfortunately, you can't do less than that.

  • Q_GADGET (or Q_OBJECT, for QObject subclasses) means "generate meta-object information for this class".
  • Q_ENUM means "generate meta-enum information for this particular enum". Now one might argue that all (public?) enumerations in a registered class should be also automatically registered. But since this has a cost (binary size), and we use C++, we don't want to pay for enums we're never going to use in the meta-object system, so it's opt-in.
  • Q_DECLARE_METATYPE (not needed on the enum itself if you're using Q_ENUM; not needed in general, in your scenario) enables the type to be used inside QVariants (Qt's C++98, RTTI-less incarnation of C++17's std::any). Whether you want this or not depends on the type. I would say that all "value types" should have it, but again, this generates extra code that you may not want to pay for. Also, this really applies to "value types" only -- this registration requires the type to have public default constructor, public copy constructor, public copy assignment, public destructor. If you've got a class which does not have these, you can't use this macro => you can't wrap it in a QVariant.
  • qRegisterMetaType registers the aforementioned constructors/destructors in a table at runtime, enabling you to have an unique id for the type (required if you want to identify types in method signatures), dynamically create or destroy instances of the type (required, amongst other things, to implement queued connections: Qt needs a generic way to copy the signal's arguments into an event to be sent to the target thread, and destroy such arguments later), use the Q_PROPERTY subsystem.

Depending on what exactly you need to do you need a subset of all of this.

peppe
  • 21,934
  • 4
  • 55
  • 70
  • Thanks for the detailed answer, I wonder if anybody tried to teach a code generator to generate Qt meta type enabled code, for example Protocol Buffers? – Nils Nov 08 '16 at 11:56