Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Emitting enum class in namespace not working



  • I ran into something weird today, maybe someone can explain what is going on.

    This is more or less my settup:

    my_class.h:

    namespace my_namespace {
        enum class my_enum : uint64_t { one, two three};
    
        class my_class : public QObject
        {
            Q_OBJECT
    
        signals:
            void EmittMyEnum(my_enum);
        }
    }
    

    Then there is a function registerAllOfTheThings that is called from main:

    meta_register.h:

    #include "my_class.h"
    Q_DECLARE_METATYPE(my_namespace ::BathyHint)
    
    void registerAllOfTheThings()
    {
        qRegisterMetaType<my_namespace ::BathyHint>();
    }
    

    Now when I emit EmittMyEnum it doesn't get emitted between threads. I get this message to the console:

    QObject::connect: Cannot queue arguments of type 'my_enum'
    (Make sure 'my_enum' is registered using qRegisterMetaType().)
    

    But if I change the Q_DECLARE_METATYPE call to:

    namespace my_namespace {
        Q_DECLARE_METATYPE(BathyHint)
    }
    

    everything workes fine.

    But the thing is, I have done this before:

    Q_DECLARE_METATYPE(somenamespace::sometype)
    

    Where sometype is a class or a struct and it workes fine, just doesn't seem to work for enum.

    BTW, running on Windows 10, compiling with Visual Studio 2019 and Qt 5.14.1


  • Lifetime Qt Champion

    Please show your connect statement. Looks like you're using the old style connect and forgot to add the namespace to your signal - otherwise there would have been a warning about my_namespace ::my_enum and not my_enum. Fix your signal and use the new style connect.



  • @Christian-Ehrlicher
    The connection is something like this

    QObject::connet(my_class_ptr, &my_class::EmittMyEnum,
    some_other_class_ptr, &some_other_class::other_class_slot);
    

    But this connection is made in my_namespace , but some_other_class is not in my_namespace.


  • Lifetime Qt Champion

    Your code above is not consistent with the enum naming and others. Please provide a minimal, compilable example so we can reproduce the issue.



  • @Christian-Ehrlicher

    Code: https://github.com/Drllap/EmitEnumFromNamspaceTest

    a8109696-e6d2-446d-8b09-f681ea3b238d-image.png

    Looks like I was wrong about this working with structs:
    MyEnum and MyStruct are metatype declared with:

    namespace MyNamespace {
        Q_DECLARE_METATYPE(MyEnum)
        Q_DECLARE_METATYPE(MyStruct)
    }
    

    and are successfully sent between threads but MyEnum2, MyStruct2

    Q_DECLARE_METATYPE(MyNamespace::MyEnum2)
    Q_DECLARE_METATYPE(MyNamespace::MyStruct2)
    

    are not sent between threads.

    Then there is another problem, this:

    namespace MyNamespace {
        Q_DECLARE_METATYPE(MyEnum)
        Q_DECLARE_METATYPE(MyStruct)
    }
    

    doesn't compile on Ubuntu18 with GCC


  • Lifetime Qt Champion

    @Palli said in Emitting enum class in namespace not working:

    are not sent between threads.

    They are, please recheck.

    doesn't compile on Ubuntu18 with GCC

    Because you use the macro wrong:

    If MyStruct is in a namespace, the Q_DECLARE_METATYPE() macro has to be outside the namespace.

    This works as expected (and shown in the documentation)

    
    Q_DECLARE_METATYPE(MyNamespace::MyEnum)
    Q_DECLARE_METATYPE(MyNamespace::MyEnum2)
    Q_DECLARE_METATYPE(MyNamespace::MyStruct)
    Q_DECLARE_METATYPE(MyNamespace::MyStruct2)
    
    void MetaRegister::RegisterAllOfTheThings()
    {
        qDebug() << "Registering meta type: " << qRegisterMetaType<MyNamespace::MyEnum>();
        qDebug() << "Registering meta type: " << qRegisterMetaType<MyNamespace::MyEnum2>();
        qDebug() << "Registering meta type: " << qRegisterMetaType<MyNamespace::MyStruct>();
        qDebug() << "Registering meta type: " << qRegisterMetaType<MyNamespace::MyStruct2>();
    }
    


  • @Christian-Ehrlicher

    They are, please recheck.

    I did, and they are not.

    Because you use the macro wrong:

    I know I'm using the macro wrong, but it is the only way I have found to get the signaling between threads to work.

    Q_DECLARE_METATYPE(MyNamespace::MyEnum)
    Q_DECLARE_METATYPE(MyNamespace::MyEnum2)
    Q_DECLARE_METATYPE(MyNamespace::MyStruct)
    Q_DECLARE_METATYPE(MyNamespace::MyStruct2)

    void MetaRegister::RegisterAllOfTheThings()
    {
    qDebug() << "Registering meta type: " << qRegisterMetaTypeMyNamespace::MyEnum();
    qDebug() << "Registering meta type: " << qRegisterMetaTypeMyNamespace::MyEnum2();
    qDebug() << "Registering meta type: " << qRegisterMetaTypeMyNamespace::MyStruct();
    qDebug() << "Registering meta type: " << qRegisterMetaTypeMyNamespace::MyStruct2();
    }

    If I use this code above, I get this:
    alt text


  • Lifetime Qt Champion

    Please push the code with my changes so others can test it




  • Lifetime Qt Champion

    Ah, you still forget to fully qualify the enums in the slots as I said in my first post. I did this locally.



  • @Christian-Ehrlicher

    I don't quite follow, are you talking about in the Receiver class?

    class Receiver : public QObject
    {
        Q_OBJECT
    
        public slots:
            void OnGettingEnum(MyNamespace::MyEnum e) {
                qDebug() << "Received on thread: " << QThread::currentThread();
                qDebug() << "Got the MyEnum: " << static_cast<int>(e);
            }
            void OnGettingEnum2(MyNamespace::MyEnum2 e) {
                qDebug() << "Received on thread: " << QThread::currentThread();
                qDebug() << "Got the MyEnum2: " << static_cast<int>(e);
            }
            void OnGettingStruct(MyNamespace::MyStruct s) {
                qDebug() << "Received on thread: " << QThread::currentThread();
                qDebug() << "Got the MyStruct";
            }
            void OnGettingStruct2(MyNamespace::MyStruct2 s) {
                qDebug() << "Received on thread: " << QThread::currentThread();
                qDebug() << "Got the MyStruct2";
            }
    };
    


  • @Christian-Ehrlicher

    Ok, you are talking about the signals in the Sender class?

    Changing this

        class Sender : public QObject
        {
            Q_OBJECT
        signals:
            void EmitEnum(MyEnum);
            void EmitEnum2(MyEnum2);
            void EmitStruct(MyStruct);
            void EmitStruct2(MyStruct2);
        };
    
    

    to this

        class Sender : public QObject
        {
            Q_OBJECT
        signals:
            void EmitEnum(MyNamespace::MyEnum);
            void EmitEnum2(MyNamespace::MyEnum2);
            void EmitStruct(MyNamespace::MyStruct);
            void EmitStruct2(MyNamespace::MyStruct2);
        };
    

    fixes it.


  • Lifetime Qt Champion

    @Palli said in Emitting enum class in namespace not working:

    Ok, you are talking about the signals in the Sender class?

    Yes:

    forgot to add the namespace to your signal - otherwise there would have been a warning about my_namespace ::my_enum and not my_enum.

    Please mark the topic as solved then.



  • @Christian-Ehrlicher Done, thanks for you help


Log in to reply