我试图在编译时获取QMetaType
的ID,但是当我尝试这个非常简单的基本情况时:
cmake_minimum_required(VERSION 3.10)
project(helloqt)
set(CMAKE_CXX_STANDARD 14)
find_package(Qt5Widgets REQUIRED)
add_executable(${PROJECT_NAME} main.cpp)
target_link_libraries(helloqt Qt5::Widgets)
#include <QApplication>
#include <QDebug>
struct Test{
};
Q_DECLARE_METATYPE (Test)
constexpr int test_enum = qMetaTypeId<Test>();
int main() {
qDebug() << test_enum;
return 0;
}
我收到以下错误:
In file included from C:/msys64/mingw64/include/QtCore/qobject.h:54:0,
from C:/msys64/mingw64/include/QtCore/qcoreapplication.h:46,
from C:/msys64/mingw64/include/QtWidgets/qapplication.h:44,
from C:/msys64/mingw64/include/QtWidgets/QApplication:1,
from ...\main.cpp:1:
...\main.cpp:8:51: in constexpr expansion of 'qMetaTypeId<Test>()'
C:/msys64/mingw64/include/QtCore/qmetatype.h:1754:43: error: 'static constexpr int QMetaTypeId2<T>::qt_metatype_id() [with T = Test]' called in a constant expression
return QMetaTypeId2<T>::qt_metatype_id();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
C:/msys64/mingw64/include/QtCore/qmetatype.h:1618:40: note: 'static constexpr int QMetaTypeId2<T>::qt_metatype_id() [with T = Test]' is not usable as a constexpr function because:
static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
^~~~~~~~~~~~~~
C:/msys64/mingw64/include/QtCore/qmetatype.h:1618:96: error: call to non-constexpr function 'static int QMetaTypeId<Test>::qt_metatype_id()'
static inline Q_DECL_CONSTEXPR int qt_metatype_id() { return QMetaTypeId<T>::qt_metatype_id(); }
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~
mingw32-make.exe[3]: *** [CMakeFiles\helloqt.dir\build.make:63: CMakeFiles/helloqt.dir/main.cpp.obj] Error 1
mingw32-make.exe[2]: *** [CMakeFiles\Makefile2:67: CMakeFiles/helloqt.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:79: CMakeFiles/helloqt.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:117: helloqt] Error 2
似乎暗示qMetaTypeID不是常量表达式,但这是我在编辑器中看到的。
并且此代码编译良好:
#include <QApplication>
#include <QDebug>
Q_DECL_CONSTEXPR int x = 3;
int main() {
static_assert(x == 3);
return 0;
}
(我已经使用constexpr进行了测试,它没有工作,这是预期的)。
我的编译器是Mingw-64,QT版本为5.10.1。
答案 0 :(得分:0)
这非常简单:元数据类型ID不是一般的 的常量表达式。除了一些基本类型之外的任何东西,分配的值都会有所不同 - 它们在运行时分配,并取决于各个Qt模块的使用的相对时间,Qt模块的变化,代码的变化等。您的设计不能假设那些是不变的值,甚至在运行之间是相同的,在机器之间不要介意。
id代码在运行时以线程安全的方式分配它们。
如果您必须自己使用Q_DECLARE_METATYPE
,则ID为不 constexpr
。
在Qt内置类型仅的特殊情况下,ID constexpr
。
如果您真的需要qMetatypeId<Type>()
成为constexpr,那么您必须负责通过专门化struct QMetaTypeId<Type>
(或QMetaTypeId2
)来实现这一目标。并且您必须确保动态注册的类型(因为是,动态注册是Qt捕获该类型的辅助函数所必需的)与静态分配的类型相同。
没有办法让Qt尝试在给定的ID上注册&#34;提示&#34;。它很好,但目前还没有办法(我知道,不需要使用私有标头等)。
// https://github.com/KubaO/stackoverflown/tree/master/questions/static-metatype-50703377
#include <QtCore>
// Interface
#if defined(QT_WIDGETS_LIB) && defined(Q_OS_MAC)
constexpr int StaticMetatypeId = QMetaType::User + 1;
#else
constexpr int StaticMetatypeId = QMetaType::User + 0;
#endif
#define MY_DECLARE_STATIC_METATYPE(TYPE, METATYPEID) \
MY_DECLARE_STATIC_METATYPE_IMPL(TYPE, METATYPEID)
#define MY_DECLARE_STATIC_METATYPE_IMPL(TYPE, METATYPEID) \
QT_BEGIN_NAMESPACE \
template<> struct QMetaTypeId2<TYPE> \
{ \
enum { Defined = 1, IsBuiltIn = false, MetaType = METATYPEID }; \
static inline constexpr int qt_metatype_id() { return METATYPEID; } \
static inline constexpr const char *static_name() { return #TYPE; } \
}; \
QT_END_NAMESPACE
template <typename T>
int registerStaticMetaType() {
auto id = qRegisterMetaType<T>(QMetaTypeId2<T>::static_name(),
reinterpret_cast<T*>(quintptr(-1)));
Q_ASSERT(id == qMetaTypeId<T>());
return id;
}
// Use
struct Foo {};
MY_DECLARE_STATIC_METATYPE(Foo, StaticMetatypeId + 0)
int main() {
registerStaticMetaType<Foo>(); // StaticMetatypeId + 0
// other registrations must follow in ascending order
static_assert(qMetaTypeId<Foo>() == StaticMetatypeId+0, "try again :(");
}