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 <ivan.solovev@qt.io>
(cherry picked from commit 74a87a329498422db0dea3e469fb84704accbb2b)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2024-07-04 20:02:32 +02:00 committed by Qt Cherry-pick Bot
parent 377b4df13b
commit 8a17835180
6 changed files with 51 additions and 10 deletions

View File

@ -11,6 +11,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qcompare.h>
#include <QtCore/qtclasshelpermacros.h>
#include <QtCore/qtmetamacros.h>
#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,

View File

@ -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 <typename T> inline T *qGetPtrHelper(T *ptr) noexcept { return ptr; }
template <typename Ptr> 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(); }

View File

@ -5,6 +5,7 @@
#define QTDEPRECATIONMARKERS_H
#include <QtCore/qtconfigmacros.h>
#include <QtCore/qtclasshelpermacros.h>
#include <QtCore/qtdeprecationdefinitions.h>
#include <QtCore/qtversionchecks.h>
#include <QtCore/qcompilerdetection.h> // 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

View File

@ -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;

View File

@ -6,6 +6,7 @@
#define QTMETAMACROS_H
#include <QtCore/qglobal.h>
#include <QtCore/qtclasshelpermacros.h>
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 */

View File

@ -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<decltype(QtPrivate::Deprecated), const QtPrivate::Deprecated_t>);
[[maybe_unused]] constexpr auto tag = QtPrivate::Deprecated;
static_assert(std::is_same_v<decltype(tag), const QtPrivate::Deprecated_t>);
}
{
// self-defined:
QT_DEFINE_TAG(MyTag);
static_assert(std::is_same_v<decltype(MyTag), const MyTag_t>);
[[maybe_unused]] constexpr auto tag = MyTag;
static_assert(std::is_same_v<decltype(tag), const MyTag_t>);
}
}
QT_BEGIN_NAMESPACE
// Compile-time typeinfo tests