QPointer: ensure construction from nullptr is constinit'able

Construction from nullptr wasn't, before, because it was using the
QPointer(T*) constructor, which cannot be constexpr. Add a constexpr
QPointer(std::nullptr_t) constructor to enable this use-case.

This requires to mark the (T*) constructor as Q_WEAK_OVERLOAD,
otherwise legacy construction from a literal 0 would be ambiguous.

No documentation changes needed, as the set of valid expressions
(apart from constinit'ing) has not changed. Mention the nullptr ctor,
though, without \since.

Add a test to confirm that contruction from derived still works.

Change-Id: If9d5281f6eca0c408a69f03fecba64a70a0c9cf0
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Marc Mutz 2023-10-02 18:27:51 +02:00
parent c0ba4ad49d
commit 1219dbcd12
3 changed files with 11 additions and 0 deletions

View File

@ -76,6 +76,7 @@
/*!
\fn template <class T> QPointer<T>::QPointer()
\fn template <class T> QPointer<T>::QPointer(std::nullptr_t)
Constructs a guarded pointer with value \nullptr.

View File

@ -30,6 +30,9 @@ public:
Q_NODISCARD_CTOR
QPointer() noexcept = default;
Q_NODISCARD_CTOR
constexpr QPointer(std::nullptr_t) noexcept : QPointer{} {}
Q_WEAK_OVERLOAD
Q_NODISCARD_CTOR
inline QPointer(T *p) : wp(p, true) { }
// compiler-generated copy/move ctor/assignment operators are fine!
// compiler-generated dtor is fine!

View File

@ -39,15 +39,22 @@ private slots:
// check that nullptr QPointer construction is Q_CONSTINIT:
[[maybe_unused]] Q_CONSTINIT static QPointer<QFile> s_file1;
[[maybe_unused]] Q_CONSTINIT static QPointer<QFile> s_file2 = {};
[[maybe_unused]] Q_CONSTINIT static QPointer<QFile> s_file3 = nullptr;
[[maybe_unused]] Q_CONSTINIT static QPointer<QFile> s_file4 = 0; // legacy nullptr
void tst_QPointer::constructors()
{
struct Derived : QObject {};
Derived derived;
QPointer<QObject> p1;
QPointer<QObject> p2(this);
QPointer<QObject> p3(p2);
QPointer<QObject> p4 = &derived;
QCOMPARE(p1, QPointer<QObject>(0));
QCOMPARE(p2, QPointer<QObject>(this));
QCOMPARE(p3, QPointer<QObject>(this));
QCOMPARE(p4, &derived);
}
void tst_QPointer::ctad()