Strange MOC related error with Q_DECLARE_METATYPE()
-
I'm porting an application from Qt5 to Qt6 and ran into a bizarre issue.
Minimal Example
[CMakeLists.txt]cmake_minimum_required(VERSION 3.19) project(MetaTypeIssue VERSION 0.1 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets) set(PROJECT_SOURCES main.cpp m.h foo.h ) if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) qt_add_executable(${PROJECT_NAME} ${PROJECT_SOURCES}) else() add_executable(${PROJECT_NAME} ${PROJECT_SOURCES}) endif() target_link_libraries(MetaTypeIssue PRIVATE Qt${QT_VERSION_MAJOR}::Core)
[foo.h]
#ifndef FOO_H #define FOO_H #include <QObject> class Foo : public QObject { Q_OBJECT public: Foo() {} signals: void sig(std::shared_ptr<int> var); }; #endif // FOO_H
[m.h]
#ifndef BAR_H #define BAR_H #include <QObject> class Bar : public QObject { Q_OBJECT public: Bar() {} }; Q_DECLARE_METATYPE(std::shared_ptr<int>); #endif // BAR_H
[main.cpp]
#include <QCoreApplication> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); return a.exec(); }
Trying to compile this setup with Qt 6 (6.2.4) results in:
m.h:13: error: C2908: explicit specialization; 'QMetaTypeId<T>' has already been instantiated m.h:13: error: C2766: explicit specialization; 'QMetaTypeId<T>' has already been defined qmetatype.h:1132: see previous definition of 'QMetaTypeId<std::shared_ptr<int> >'
Some changes that "prevent" the errors:
- Change the parameter type of Foo::sig() to be different than that in Q_DECLARE_METATYPE() (obviously breaks functionality)
- Disable auto-MOC (obviously causes linker errors)
- Rename
m.h
to any name that doesn't start with an 'm' - Compile with Qt 5 (tested with 5.12.3)
I was hoping to see if anyone could reproduce this or note if/why this outright shouldn't work if that really is the case for some reason.
Here is the above MRE for convenience: https://www.mediafire.com/file/lm35jkzipj0hmwy/MetaTypeIssue.zip/file
The original application was able to use shared_ptr<int> as a signal argument just fine, though it was only through a queued connection briefly before threading changes were made, but I'm pretty sure it worked the same when queued.
EDIT: Corrected accidental usage of unique_ptr in example code instead of shared_ptr (what it actually was/is).
-
@oblivioncth
This is to confirm that I am able to reproduce the issue on QT 6.4.2 on MacOS.
The project I am trying to port is much bigger and the filename that results in this error does not start with 'm'.[ 25%] Automatic MOC for target MetaTypeIssue
[ 25%] Built target MetaTypeIssue_autogen
[ 50%] Building CXX object CMakeFiles/MetaTypeIssue.dir/MetaTypeIssue_autogen/mocs_compilation.cpp.o
In file included from /var/tmp/meta_issue/build/MetaTypeIssue_autogen/mocs_compilation.cpp:3:
In file included from /var/tmp/meta_issue/build/MetaTypeIssue_autogen/EWIEGA46WW/moc_m.cpp:10:
/var/tmp/meta_issue/build/MetaTypeIssue_autogen/EWIEGA46WW/../../../m.h:13:1: error: explicit specialization of 'QMetaTypeId<std::shared_ptr<int>>' after instantiation
Q_DECLARE_METATYPE(std::shared_ptr<int>);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/homebrew/include/QtCore/qmetatype.h:1399:34: note: expanded from macro 'Q_DECLARE_METATYPE'
#define Q_DECLARE_METATYPE(TYPE) Q_DECLARE_METATYPE_IMPL(TYPE)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/homebrew/include/QtCore/qmetatype.h:1403:12: note: expanded from macro 'Q_DECLARE_METATYPE_IMPL'
struct QMetaTypeId< TYPE >
^~~~~~~~~~~~~~~~~~~
/opt/homebrew/include/QtCore/qmetatype.h:1122:22: note: implicit instantiation first required here
enum { Defined = QMetaTypeId<T>::Defined, IsBuiltIn=false };
^
1 error generated. -
I have created a bug report regarding this. I used the minimal example that you have created in the bug report. Thanks for sharing your minimal example.