QPointer: Use new comparison helper macros

Provide the new comparesEqual() helper function as an implementation of
(in)equality operators.
Use QT_DECLARE_EQUALITY_OPERATORS_HELPER macro instead of
Q_DECLARE_EQUALITY_COMPARABLE for the comparison between QPointer<T>
and QPointer<X> to avoid creating the reversed version of the
operators in C++17 mode.

Use new \compares command in the documentation to describe the
comparison operators provided by QPointer.

Task-number: QTBUG-120306
Change-Id: Iff24d3ef5c790de7f06ab825f853e06186fa1471
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
bb10
Rym Bouabid 2024-03-20 12:44:44 +01:00
parent 99475db542
commit 890c270b9b
4 changed files with 66 additions and 60 deletions

View File

@ -4,6 +4,7 @@
#ifndef QPOINTER_H
#define QPOINTER_H
#include <QtCore/qcompare.h>
#include <QtCore/qsharedpointer.h>
#include <QtCore/qtypeinfo.h>
@ -90,27 +91,21 @@ public:
friend void swap(QPointer &lhs, QPointer &rhs) noexcept
{ lhs.swap(rhs); }
#define DECLARE_COMPARE_SET(T1, A1, T2, A2) \
friend bool operator==(T1, T2) noexcept \
{ return A1 == A2; } \
friend bool operator!=(T1, T2) noexcept \
{ return A1 != A2; }
private:
template <typename X>
friend bool comparesEqual(const QPointer &lhs, const QPointer<X> &rhs) noexcept
{ return lhs.data() == rhs.data(); }
QT_DECLARE_EQUALITY_OPERATORS_HELPER(QPointer, QPointer<X>, /* non-constexpr */,
template <typename X>)
#define DECLARE_TEMPLATE_COMPARE_SET(T1, A1, T2, A2) \
template <typename X> \
friend bool operator==(T1, T2) noexcept \
{ return A1 == A2; } \
template <typename X> \
friend bool operator!=(T1, T2) noexcept \
{ return A1 != A2; }
template <typename X>
friend bool comparesEqual(const QPointer &lhs, X *rhs) noexcept
{ return lhs.data() == rhs; }
Q_DECLARE_EQUALITY_COMPARABLE(QPointer, X*, template <typename X>)
DECLARE_TEMPLATE_COMPARE_SET(const QPointer &p1, p1.data(), const QPointer<X> &p2, p2.data())
DECLARE_TEMPLATE_COMPARE_SET(const QPointer &p1, p1.data(), X *ptr, ptr)
DECLARE_TEMPLATE_COMPARE_SET(X *ptr, ptr, const QPointer &p2, p2.data())
DECLARE_COMPARE_SET(const QPointer &p1, p1.data(), std::nullptr_t, nullptr)
DECLARE_COMPARE_SET(std::nullptr_t, nullptr, const QPointer &p2, p2.data())
#undef DECLARE_COMPARE_SET
#undef DECLARE_TEMPLATE_COMPARE_SET
friend bool comparesEqual(const QPointer &lhs, std::nullptr_t) noexcept
{ return lhs.data() == nullptr; }
Q_DECLARE_EQUALITY_COMPARABLE(QPointer, std::nullptr_t)
};
template <class T> Q_DECLARE_TYPEINFO_BODY(QPointer<T>, Q_RELOCATABLE_TYPE);

View File

@ -8,6 +8,12 @@
\ingroup objectmodel
\compares equality
\compareswith equality QPointer<X> X* std::nullptr_t
Where X and T are compatible types, which means that they are either the same (except
for their cv-qualifiers), or one is a base type of the other.
\endcompareswith
A guarded pointer, QPointer<T>, behaves like a normal C++
pointer \c{T *}, except that it is automatically cleared when the
referenced object is destroyed (unlike normal C++ pointers, which
@ -202,38 +208,38 @@
*/
/*!
\fn template <typename T> template<typename X> bool QPointer<T>::operator==(X *o, const QPointer<T> &p)
\fn template <typename T> template<typename X> bool QPointer<T>::operator==(X* const &lhs, const QPointer<T> &rhs)
Equality operator. Returns \c true if \a o and the guarded
pointer \a p are pointing to the same object, otherwise
Equality operator. Returns \c true if \a lhs and the guarded
pointer \a rhs are pointing to the same object, otherwise
returns \c false.
*/
/*!
\fn template <typename T> template<typename X> bool QPointer<T>::operator==(const QPointer<T> &p, X *o)
\fn template <typename T> template<typename X> bool QPointer<T>::operator==(const QPointer<T> &lhs, X* const &rhs)
Equality operator. Returns \c true if \a o and the guarded
pointer \a p are pointing to the same object, otherwise
Equality operator. Returns \c true if \a rhs and the guarded
pointer \a lhs are pointing to the same object, otherwise
returns \c false.
*/
/*!
\fn template <typename T> template<typename X> bool QPointer<T>::operator==(const QPointer<T> &p1, const QPointer<X> &p2)
\fn template <typename T> template<typename X> bool QPointer<T>::operator==(const QPointer<T> &lhs, const QPointer<X> &rhs)
Equality operator. Returns \c true if the guarded pointers \a p1 and \a p2
Equality operator. Returns \c true if the guarded pointers \a lhs and \a rhs
are pointing to the same object, otherwise
returns \c false.
*/
/*!
\fn template <typename T> bool QPointer<T>::operator==(std::nullptr_t, const QPointer<T> &rhs)
\fn template <typename T> bool QPointer<T>::operator==(std::nullptr_t const &lhs, const QPointer<T> &rhs)
Equality operator. Returns \c true if the pointer guarded by \a rhs
is \nullptr, otherwise
returns \c false.
*/
/*!
\fn template <typename T> bool QPointer<T>::operator==(const QPointer<T> &lhs, std::nullptr_t)
\fn template <typename T> bool QPointer<T>::operator==(const QPointer<T> &lhs, std::nullptr_t const &rhs)
Equality operator. Returns \c true if the pointer guarded by \a lhs
is \nullptr, otherwise
@ -241,35 +247,35 @@
*/
/*!
\fn template <typename T> template<typename X> bool QPointer<T>::operator!=(const QPointer<T> &p, X *o)
\fn template <typename T> template<typename X> bool QPointer<T>::operator!=(const QPointer<T> &lhs, X* const &rhs)
Inequality operator. Returns \c true if \a o and the guarded
pointer \a p are not pointing to the same object, otherwise
Inequality operator. Returns \c true if \a rhs and the guarded
pointer \a lhs are not pointing to the same object, otherwise
returns \c false.
*/
/*!
\fn template <typename T> template<typename X> bool QPointer<T>::operator!=(X *o, const QPointer<T> &p)
\fn template <typename T> template<typename X> bool QPointer<T>::operator!=(X* const &lhs, const QPointer<T> &rhs)
Inequality operator. Returns \c true if \a o and the guarded
pointer \a p are not pointing to the same object, otherwise
Inequality operator. Returns \c true if \a lhs and the guarded
pointer \a rhs are not pointing to the same object, otherwise
returns \c false.
*/
/*!
\fn template <typename T> template<typename X> bool QPointer<T>::operator!=(const QPointer<T> &p1, const QPointer<X> &p2)
\fn template <typename T> template<typename X> bool QPointer<T>::operator!=(const QPointer<T> &lhs, const QPointer<X> &rhs)
Inequality operator. Returns \c true if the guarded pointers \a p1 and
\a p2 are not pointing to the same object, otherwise
Inequality operator. Returns \c true if the guarded pointers \a lhs and
\a rhs are not pointing to the same object, otherwise
returns \c false.
*/
/*!
\fn template <typename T> bool QPointer<T>::operator!=(std::nullptr_t, const QPointer<T> &rhs)
\fn template <typename T> bool QPointer<T>::operator!=(std::nullptr_t const &lhs, const QPointer<T> &rhs)
Inequality operator. Returns \c true if the pointer guarded by \a rhs is
a valid (ie not \nullptr) pointer, otherwise
returns \c false.
*/
/*!
\fn template <typename T> bool QPointer<T>::operator!=(const QPointer<T> &lhs, std::nullptr_t)
\fn template <typename T> bool QPointer<T>::operator!=(const QPointer<T> &lhs, std::nullptr_t const &rhs)
Inequality operator. Returns \c true if the pointer guarded by \a lhs is
a valid (ie not \nullptr) pointer, otherwise

View File

@ -20,6 +20,7 @@ qt_internal_add_test(tst_qpointer
tst_qpointer.cpp
LIBRARIES
Qt::Gui
Qt::TestPrivate
)
## Scopes:

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include <QTest>
#include <QtTest/private/qcomparisontesthelper_p.h>
#include <QRunnable>
#include <QThreadPool>
@ -23,6 +24,7 @@ private slots:
void conversion();
void destructor();
void assignment_operators();
void compareCompiles();
void equality_operators();
void swap();
void isNull();
@ -203,12 +205,21 @@ void tst_QPointer::assignment_operators()
delete object;
}
void tst_QPointer::compareCompiles()
{
QTestPrivate::testEqualityOperatorsCompile<QPointer<QObject>>();
QTestPrivate::testEqualityOperatorsCompile<QPointer<QObject>, QObject*>();
QTestPrivate::testEqualityOperatorsCompile<QPointer<QObject>, QWidget*>();
QTestPrivate::testEqualityOperatorsCompile<QPointer<QObject>, QPointer<QWidget>>();
QTestPrivate::testEqualityOperatorsCompile<QPointer<QObject>, std::nullptr_t>();
}
void tst_QPointer::equality_operators()
{
QPointer<QObject> p1;
QPointer<QObject> p2;
QVERIFY(p1 == p2);
QT_TEST_EQUALITY_OPS(p1, p2, true);
QObject *object = nullptr;
#ifndef QT_NO_WIDGETS
@ -216,16 +227,15 @@ void tst_QPointer::equality_operators()
#endif
p1 = object;
QVERIFY(p1 == p2);
QVERIFY(p1 == object);
QT_TEST_EQUALITY_OPS(p1, p2, true);
QT_TEST_EQUALITY_OPS(p1, object, true);
p2 = object;
QVERIFY(p2 == p1);
QVERIFY(p2 == object);
QT_TEST_EQUALITY_OPS(p2, p1, true);
QT_TEST_EQUALITY_OPS(p2, object, true);
p1 = this;
QVERIFY(p1 != p2);
QT_TEST_EQUALITY_OPS(p1, p2, false);
p2 = p1;
QVERIFY(p1 == p2);
QT_TEST_EQUALITY_OPS(p1, p2, true);
// compare to zero
p1 = nullptr;
@ -233,19 +243,13 @@ void tst_QPointer::equality_operators()
QVERIFY(0 == p1);
QVERIFY(p2 != 0);
QVERIFY(0 != p2);
QVERIFY(p1 == nullptr);
QVERIFY(nullptr == p1);
QVERIFY(p2 != nullptr);
QVERIFY(nullptr != p2);
QVERIFY(p1 == object);
QVERIFY(object == p1);
QVERIFY(p2 != object);
QVERIFY(object != p2);
QT_TEST_EQUALITY_OPS(p1, nullptr, true);
QT_TEST_EQUALITY_OPS(p2, nullptr, false);
QT_TEST_EQUALITY_OPS(p1, object, true);
QT_TEST_EQUALITY_OPS(p2, object, false);
#ifndef QT_NO_WIDGETS
QVERIFY(p1 == widget);
QVERIFY(widget == p1);
QVERIFY(p2 != widget);
QVERIFY(widget != p2);
QT_TEST_EQUALITY_OPS(p1, widget, true);
QT_TEST_EQUALITY_OPS(p2, widget, false);
#endif
}