From 8a17835180648934149b601ca58f77396ac5aab1 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Thu, 4 Jul 2024 20:02:32 +0200 Subject: [PATCH] Long live QT_DEFINE_TAG(_STRUCT)! We seem to be using more and more of these, and their definition is a bit subtle (need to have an explicit default ctor to avoid {} being an initializer for the type). Port the existing tag structs over to the new macro and add a test, even though we found two users of QT_DEFINE_TAG in QtBase alone, one of which is actually widely used (Disambiguated_t). There are more in other modules. Change-Id: I046bb2b70a2c7e79be2315d91c43e5fd2f0968a0 Reviewed-by: Ivan Solovev (cherry picked from commit 74a87a329498422db0dea3e469fb84704accbb2b) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/global/qnamespace.h | 6 ++--- src/corelib/global/qtclasshelpermacros.h | 24 +++++++++++++++++++ src/corelib/global/qtdeprecationmarkers.h | 4 ++-- src/corelib/kernel/qcoreevent.h | 6 ++--- src/corelib/kernel/qtmetamacros.h | 3 ++- .../corelib/global/qglobal/tst_qglobal.cpp | 18 ++++++++++++++ 6 files changed, 51 insertions(+), 10 deletions(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index b81ad1375d4..f5bb2ad921f 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -11,6 +11,7 @@ #include #include +#include #include #if defined(__OBJC__) && !defined(__cplusplus) @@ -1596,10 +1597,7 @@ namespace Qt { }; inline constexpr Initialization Uninitialized = Initialization::Uninitialized; - struct Disambiguated_t { - explicit Disambiguated_t() = default; - }; - inline constexpr Disambiguated_t Disambiguated{}; + inline QT_DEFINE_TAG(Disambiguated); enum CoordinateSystem { DeviceCoordinates, diff --git a/src/corelib/global/qtclasshelpermacros.h b/src/corelib/global/qtclasshelpermacros.h index 8839e80fb97..0b7f943ea73 100644 --- a/src/corelib/global/qtclasshelpermacros.h +++ b/src/corelib/global/qtclasshelpermacros.h @@ -74,6 +74,30 @@ QT_BEGIN_NAMESPACE return *this; \ } +/* + These macros can be used to define tag structs in the preferred way (ie. + with explicit default ctor). + + The _STRUCT version only defines the tag type, no variable, while the + normal macro defines also a variable (and appends _t to the type name to + distinguish the two). + + E.g. if we were std, we could use + + QT_DEFINE_TAG(nullopt); // nullopt of type nullopt_t + + The variable will be constexpr by default. If you want to make it static, + or inline, or both, prepend those keywords: + + static QT_DEFINE_TAG(MyTag); // static constexpr + static inline QT_DEFINE_TAG(MyTag); // static inline constexpr +*/ +#define QT_DEFINE_TAG_STRUCT(TAG) \ + struct TAG { explicit TAG () = default; } +#define QT_DEFINE_TAG(TAG) \ + constexpr QT_DEFINE_TAG_STRUCT(TAG ## _t) TAG{} + + template inline T *qGetPtrHelper(T *ptr) noexcept { return ptr; } template inline auto qGetPtrHelper(Ptr &ptr) noexcept -> decltype(ptr.get()) { static_assert(noexcept(ptr.get()), "Smart d pointers for Q_DECLARE_PRIVATE must have noexcept get()"); return ptr.get(); } diff --git a/src/corelib/global/qtdeprecationmarkers.h b/src/corelib/global/qtdeprecationmarkers.h index 68f4fda1863..b985e7708ef 100644 --- a/src/corelib/global/qtdeprecationmarkers.h +++ b/src/corelib/global/qtdeprecationmarkers.h @@ -5,6 +5,7 @@ #define QTDEPRECATIONMARKERS_H #include +#include #include #include #include // for Q_DECL_DEPRECATED @@ -309,8 +310,7 @@ QT_BEGIN_NAMESPACE #ifdef __cplusplus // A tag to help mark stuff deprecated (cf. QStringViewLiteral) namespace QtPrivate { -enum class Deprecated_t {}; -constexpr inline Deprecated_t Deprecated = {}; +inline QT_DEFINE_TAG(Deprecated); } #endif diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index a65dbee7dac..38c0680a123 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -319,11 +319,11 @@ public: virtual QEvent *clone() const; protected: - struct InputEventTag { explicit InputEventTag() = default; }; + QT_DEFINE_TAG_STRUCT(InputEventTag); QEvent(Type type, InputEventTag) : QEvent(type) { m_inputEvent = true; } - struct PointerEventTag { explicit PointerEventTag() = default; }; + QT_DEFINE_TAG_STRUCT(PointerEventTag); QEvent(Type type, PointerEventTag) : QEvent(type, InputEventTag{}) { m_pointerEvent = true; } - struct SinglePointEventTag { explicit SinglePointEventTag() = default; }; + QT_DEFINE_TAG_STRUCT(SinglePointEventTag); QEvent(Type type, SinglePointEventTag) : QEvent(type, PointerEventTag{}) { m_singlePointEvent = true; } quint16 t; diff --git a/src/corelib/kernel/qtmetamacros.h b/src/corelib/kernel/qtmetamacros.h index ae68abcfeeb..2ef5c0df9d6 100644 --- a/src/corelib/kernel/qtmetamacros.h +++ b/src/corelib/kernel/qtmetamacros.h @@ -6,6 +6,7 @@ #define QTMETAMACROS_H #include +#include QT_BEGIN_NAMESPACE @@ -129,7 +130,7 @@ private: \ Q_OBJECT_NO_ATTRIBUTES_WARNING \ Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \ QT_WARNING_POP \ - struct QPrivateSignal { explicit QPrivateSignal() = default; }; \ + QT_DEFINE_TAG_STRUCT(QPrivateSignal); \ QT_ANNOTATE_CLASS(qt_qobject, "") /* qmake ignore Q_OBJECT */ diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp index b444183f775..e98bdacd44a 100644 --- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp +++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp @@ -75,6 +75,7 @@ private slots: void PRImacros(); void testqToUnderlying(); void nodiscard(); + void tagStructDefinitions(); }; extern "C" { // functions in qglobal.c @@ -941,6 +942,23 @@ void tst_QGlobal::nodiscard() QCOMPARE(t2.get(), 42); } +void tst_QGlobal::tagStructDefinitions() +{ + { + // predefined: + static_assert(std::is_same_v); + [[maybe_unused]] constexpr auto tag = QtPrivate::Deprecated; + static_assert(std::is_same_v); + } + { + // self-defined: + QT_DEFINE_TAG(MyTag); + static_assert(std::is_same_v); + [[maybe_unused]] constexpr auto tag = MyTag; + static_assert(std::is_same_v); + } +} + QT_BEGIN_NAMESPACE // Compile-time typeinfo tests