From 3f5b5e48595b52000421a339d95d1a30d783aed5 Mon Sep 17 00:00:00 2001 From: Fabian Kosmale Date: Fri, 29 May 2020 14:59:09 +0200 Subject: [PATCH] Use static function instead of lambda to workaround a MSVC compiler bug The seemingly useless template parameters are needed to avoid a (distinct) bug in MSVC 2019 < 16.6, and should be removed once we have a newer version in the CI. Task-number: QTBUG-82945 Fixes: QTBUG-83600 Change-Id: I5b22a2259aa16ae90eca7d4f3bd2e4fa1116a73b Reviewed-by: Qt CI Bot Reviewed-by: Lars Knoll --- src/corelib/kernel/qmetatype.h | 128 ++++++++++++++++++--------------- 1 file changed, 70 insertions(+), 58 deletions(-) diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 3c7781c8509..6939adb678c 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -2682,26 +2682,77 @@ struct BuiltinMetaType::IsBuiltIn>> { }; -template +template class QMetaTypeForType { - static const decltype(typenameHelper()) name; + static const decltype(typenameHelper()) name; + + template + static constexpr QMetaTypeInterface::DefaultCtrFn getDefaultCtr() + { + if constexpr (std::is_default_constructible_v) { + return [](const QMetaTypeInterface *, void *addr) { new (addr) T(); }; + } else { + return nullptr; + } + } + + template + static constexpr QMetaTypeInterface::CopyCtrFn getCopyCtr() + { + if constexpr (std::is_copy_constructible_v) { + return [](const QMetaTypeInterface *, void *addr, const void *other) { + new (addr) T(*reinterpret_cast(other)); + }; + } else { + return nullptr; + } + } + + template + static constexpr QMetaTypeInterface::MoveCtrFn getMoveCtr() + { + if constexpr (std::is_move_constructible_v) { + return [](const QMetaTypeInterface *, void *addr, void *other) { + new (addr) T(std::move(*reinterpret_cast(other))); + }; + } else { + return nullptr; + } + } + + template + static constexpr QMetaTypeInterface::DtorFn getDtor() + { + if constexpr (std::is_destructible_v) + return [](const QMetaTypeInterface *, void *addr) { reinterpret_cast(addr)->~T(); }; + else + return nullptr; + } + + template + static constexpr QMetaTypeInterface::LegacyRegisterOp getLegacyRegister() + { + if constexpr (QMetaTypeId2::Defined && !QMetaTypeId2::IsBuiltIn) { + return []() { QMetaTypeId2::qt_metatype_id(); }; + } else { + return nullptr; + } + } + + static constexpr const char *getName() + { + if constexpr (bool(QMetaTypeId2::IsBuiltIn)) { + return QMetaTypeId2::name; + } else { + return name.data(); + } + } public: static QMetaTypeInterface metaType; }; -#ifdef Q_CC_CLANG -// Workaround for https://bugs.llvm.org/show_bug.cgi?id=44554 : Every lambda used for initializing -// static members need a different signature for explicit instentiation -#define QT_METATYPE_CONSTEXPRLAMDA(...) [](std::integral_constant = {}) constexpr __VA_ARGS__ () -#elif defined(Q_CC_MSVC) -// Workaround a bug with 'if constexpr' not working in lambda that are not generic in MSVC -#define QT_METATYPE_CONSTEXPRLAMDA(...) [](auto) constexpr __VA_ARGS__ (0) -#else -#define QT_METATYPE_CONSTEXPRLAMDA(...) []() constexpr __VA_ARGS__ () -#endif - template QMetaTypeInterface QMetaTypeForType::metaType = { /*.revision=*/ 0, @@ -2709,54 +2760,15 @@ QMetaTypeInterface QMetaTypeForType::metaType = { /*.alignment=*/ alignof(T), /*.flags=*/ QMetaTypeTypeFlags::Flags, /*.metaObject=*/ MetaObjectForType::value(), - /*.name=*/ QT_METATYPE_CONSTEXPRLAMDA( -> const char * { - if constexpr (bool(QMetaTypeId2::IsBuiltIn)) { - return QMetaTypeId2::name; - } else { - return name.data(); - } - }), + /*.name=*/ getName(), /*.typeId=*/ BuiltinMetaType::value, /*.ref=*/ Q_REFCOUNT_INITIALIZE_STATIC, /*.deleteSelf=*/ nullptr, - /*.defaultCtr=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::DefaultCtrFn { - if constexpr (std::is_default_constructible_v) { - return [](const QMetaTypeInterface *, void *addr) { new (addr) T(); }; - } else { - return nullptr; - } - }), - /*.copyCtr=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::CopyCtrFn { - if constexpr (std::is_copy_constructible_v) { - return [](const QMetaTypeInterface *, void *addr, const void *other) { - new (addr) T(*reinterpret_cast(other)); - }; - } else { - return nullptr; - } - }), - /*.moveCtr=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::MoveCtrFn { - if constexpr (std::is_move_constructible_v) { - return [](const QMetaTypeInterface *, void *addr, void *other) { - new (addr) T(std::move(*reinterpret_cast(other))); - }; - } else { - return nullptr; - } - }), - /*.dtor=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::DtorFn { - if constexpr (std::is_destructible_v) - return [](const QMetaTypeInterface *, void *addr) { reinterpret_cast(addr)->~T(); }; - else - return nullptr; - }), - /*.legacyRegisterOp=*/ QT_METATYPE_CONSTEXPRLAMDA( -> QMetaTypeInterface::LegacyRegisterOp { - if constexpr (QMetaTypeId2::Defined && !QMetaTypeId2::IsBuiltIn) { - return []() { QMetaTypeId2::qt_metatype_id(); }; - } else { - return nullptr; - } - }) + /*.defaultCtr=*/ getDefaultCtr(), + /*.copyCtr=*/ getCopyCtr(), + /*.moveCtr=*/ getMoveCtr(), + /*.dtor=*/ getDtor(), + /*.legacyRegisterOp=*/ getLegacyRegister() }; template