Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Q_DECLARE_METATYPE for template class
Forum Updated to NodeBB v4.3 + New Features

Q_DECLARE_METATYPE for template class

Scheduled Pinned Locked Moved General and Desktop
16 Posts 4 Posters 13.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • S Offline
    S Offline
    silicomancer
    wrote on last edited by
    #1

    I just wrote a little templated container class. Something like this:

    @
    template <typename T> class Container: public ContainerBase
    {
    ......
    T data;
    };
    @

    I need to register all instances of that template automatically to meta type system and binary data streams. I was able to implement automatic creation and registration of data streams. It was also no big issue to call qRegisterMetaType() automatically.

    However Q_DECLARE_METATYPE() is a bit more complicated.

    Using the macro directly turned out to be impossible. So I played around, copied the original macro and adapted it a bit:

    @
    template <typename T> struct QMetaTypeId<Container<T>>
    {
    enum { Defined = 1 };
    static int qt_metatype_id()
    {
    static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
    if (const int id = metatype_id.loadAcquire()) return id;
    const int newId = qRegisterMetaType<Container<T>>(typeid(Container<T>).name(), reinterpret_cast<Container<T>*>(quintptr(-1)));
    metatype_id.storeRelease(newId);
    return newId;
    }
    };
    @

    This works fine. But I would like to avoid copying Qt internals.

    Is there any solution for that problem that involves official Qt API only?

    1 Reply Last reply
    0
    • N Offline
      N Offline
      NicuPopescu
      wrote on last edited by
      #2

      Q_DECLARE_METATYPE_TEMPLATE_1ARG(Container)

      1 Reply Last reply
      0
      • S Offline
        S Offline
        silicomancer
        wrote on last edited by
        #3

        Thanks for your answer! That macro looks very promising. I replaced my snippet by

        @ Q_DECLARE_METATYPE_TEMPLATE_1ARG(Container) @

        but I get the usual static assert

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

        However I do not understand why. I would have expected that it works.

        1 Reply Last reply
        0
        • N Offline
          N Offline
          NicuPopescu
          wrote on last edited by
          #4

          Here I tested and it works, even I tested the metatype ids for some instances and looks ok: are you sure that error comes from where you call the macro definition for templates?

          and one more issue: you can still improve your workaround to make it completely generic ... for this have a look at qt code how they use strays "" ... I'm not good at this but I tested like there and it works

          1 Reply Last reply
          0
          • S Offline
            S Offline
            silicomancer
            wrote on last edited by
            #5

            Yes, I checked the "Type is not registered" error. It definitely corresponds to the missing container declaration.

            BTW that Container and ContainerBase class is not a QList or QSet or something. I should have mentioned that these are custom classes holding a single data instance. They are not similar to the Qt container.

            I did some tests. This one works too (however this isn't what I want to do):

            @Q_DECLARE_METATYPE(Container<ConcreteType>) @

            I also tried to declare the contained type first before declaring the container:

            @Q_DECLARE_METATYPE(ConcreteType)
            Q_DECLARE_METATYPE_TEMPLATE_1ARG(Container); @

            This gives me a different error "value_type is not an element of Container<T>" in this line of qmetatype.h:

            @template<typename T, bool = QMetaTypeId2<typename T::value_type>::Defined> @

            Then I added

            @typedef T value_type; @

            to my Container class. Now I get an error about a missing iterator.

            My impressions is that there are lot of concrete features that are expected being implemented in the provided container class. I can't fulfil all of them (especially iterators). Is that macro specialized for Qt containers and alike?

            Any ideas on this?

            1 Reply Last reply
            0
            • N Offline
              N Offline
              NicuPopescu
              wrote on last edited by
              #6

              how I tested here:

              in simple main window app, in mainwindow.h:

              @
              ...
              class ContainerBase
              {

              };

              template <class T> class Container: public ContainerBase
              {

              T data;
              };

              Q_DECLARE_METATYPE_TEMPLATE_1ARG(Container)
              @

              what is ConcreteType, a built in one?

              1 Reply Last reply
              0
              • N Offline
                N Offline
                NicuPopescu
                wrote on last edited by
                #7

                bq. This gives me a different error “value_type is not an element of Container<T>” in this line of qmetatype.h:
                template<typename T, bool = QMetaTypeId2<typename T::value_type>::Defined>

                this line does not exist here! :) I use qt 5.1.1 mingw

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  silicomancer
                  wrote on last edited by
                  #8

                  I used an enum class as concrete type and I am using Qt5.2.0 beta here.
                  How did you involve QVariant?

                  This is a minimum example that breaks compilation when used in one of projects headers:

                  @
                  template <class T> class Container
                  {
                  };

                  Q_DECLARE_METATYPE_TEMPLATE_1ARG(Container)

                  inline void Test()
                  {
                  QVariant x = QVariant::fromValue(Container<int>());
                  }
                  @

                  1 Reply Last reply
                  0
                  • N Offline
                    N Offline
                    NicuPopescu
                    wrote on last edited by
                    #9

                    it gives no error here ...

                    @Container<int> y = x.value< Container<int> >();@

                    returns the correctly too

                    shall I understand that Q_DECLARE_METATYPE_TEMPLATE_1ARG is working now?

                    1 Reply Last reply
                    0
                    • S Offline
                      S Offline
                      silicomancer
                      wrote on last edited by
                      #10

                      No, it does NOT work. I also tried the code in one if the Qt examples to make sure there are no collisions in my custom project.

                      Adding the following code:

                      @
                      #include <QVariant>

                      template <class T> class Container
                      {
                      };

                      Q_DECLARE_METATYPE_TEMPLATE_1ARG(Container)

                      inline void Test()
                      {
                      QVariant x = QVariant::fromValue(Container<int>());
                      }

                      @

                      to the bottom of the tabdialog.h header of TabWidget example returns errors on building:

                      @
                      C:\Qt\Qt5.2.0\5.2.0-beta1\msvc2012\include\QtCore\qmetatype.h:1372: Fehler:C2039: 'value_type': Ist kein Element von 'Container<T>'
                      with
                      [
                      T=int
                      ]
                      C:\Qt\Qt5.2.0\5.2.0-beta1\msvc2012\include\QtCore/qmetatype.h(1578): Siehe Verweis auf die Instanziierung der gerade kompilierten Klassen-template "QtPrivate::SequentialContainerConverterHelper<T>".
                      with
                      [
                      T=Container<int>
                      ]

                      ..... and a lot more

                      @

                      If it works for you I suppose this is a Qt 5.2.0 beta problem. I am using 5.2.0 beta, VS2012, ANGLE, 32 Bit.

                      1 Reply Last reply
                      0
                      • R Offline
                        R Offline
                        Rigel
                        wrote on last edited by
                        #11

                        I did this test with Qt5.1.1 (VS2012, ANGLE, 32 Bit) and it worked.

                        I also did it with Qt5.2.0-beta1 and it failed.

                        So I can definitely confirm that there is some strange issue with Qt5.2.0-beta1 (VS2012, ANGLE, 32 Bit).

                        1 Reply Last reply
                        0
                        • SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #12

                          Hi,

                          It sounds like a regression (I may be wrong though), there has been a lot of work on QMetatype lately. Can you open a bug report so it might get fixed before 5.2 official release ?

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          1 Reply Last reply
                          0
                          • N Offline
                            N Offline
                            NicuPopescu
                            wrote on last edited by
                            #13

                            bq. I did this test with Qt5.1.1 (VS2012, ANGLE, 32 Bit) and it worked.
                            I also did it with Qt5.2.0-beta1 and it failed.
                            So I can definitely confirm that there is some strange issue with Qt5.2.0-beta1 (VS2012, ANGLE, 32 Bit).

                            I can confirm these tests too, but I want to do one more with Qt 5.2.0-beta1 with mingw

                            1 Reply Last reply
                            0
                            • N Offline
                              N Offline
                              NicuPopescu
                              wrote on last edited by
                              #14

                              I found a solution for Qt 5.2.0-beta1:

                              @class ContainerBase: public QString /!!!inherits a core class which is compatible with the new meta type system!!!/
                              {

                              };

                              template <class T> class Container: public ContainerBase
                              {
                              T data;

                              };

                              Q_DECLARE_METATYPE_TEMPLATE_1ARG(Container)@

                              1 Reply Last reply
                              0
                              • S Offline
                                S Offline
                                silicomancer
                                wrote on last edited by
                                #15

                                EDIT: I created an issue, see https://bugreports.qt-project.org/browse/QTBUG-34957

                                1 Reply Last reply
                                0
                                • S Offline
                                  S Offline
                                  silicomancer
                                  wrote on last edited by
                                  #16

                                  Update:

                                  According to the report (see above), the Q_DECLARE_METATYPE_TEMPLATE_1ARG in Qt5 seem to work as expected.

                                  Unfortunately they do not intend to support registering template types (using a new public macro). So I will need to stick to my nasty workaround :-(

                                  Anyway thanks for your help!

                                  1 Reply Last reply
                                  0

                                  • Login

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • Users
                                  • Groups
                                  • Search
                                  • Get Qt Extensions
                                  • Unsolved