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
-
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 notmy_enum
. Fix your signal and use the new style connect. -
@Christian-Ehrlicher
The connection is something like thisQObject::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
, butsome_other_class
is not inmy_namespace
. -
Your code above is not consistent with the enum naming and others. Please provide a minimal, compilable example so we can reproduce the issue.
-
Code: https://github.com/Drllap/EmitEnumFromNamspaceTest
Looks like I was wrong about this working with structs:
MyEnum
andMyStruct
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
-
@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>(); }
-
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:
-
Please push the code with my changes so others can test it
-
@Christian-Ehrlicher Done
-
Ah, you still forget to fully qualify the enums in the slots as I said in my first post. I did this locally.
-
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"; } };
-
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.
-
@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