diff --git a/src/corelib/tools/qrect.cpp b/src/corelib/tools/qrect.cpp index 6d345ce543..c0e5127c6e 100644 --- a/src/corelib/tools/qrect.cpp +++ b/src/corelib/tools/qrect.cpp @@ -15,6 +15,10 @@ QT_BEGIN_NAMESPACE \ingroup painting \reentrant + \compares equality + \compareswith equality QRectF + \endcompareswith + \brief The QRect class defines a rectangle in the plane using integer precision. @@ -1105,18 +1109,18 @@ bool QRect::intersects(const QRect &r) const noexcept } /*! - \fn bool QRect::operator==(const QRect &r1, const QRect &r2) + \fn bool QRect::operator==(const QRect &lhs, const QRect &rhs) - Returns \c true if the rectangles \a r1 and \a r2 are equal, + Returns \c true if the rectangles \a lhs and \a rhs are equal, otherwise returns \c false. */ /*! - \fn bool QRect::operator!=(const QRect &r1, const QRect &r2) + \fn bool QRect::operator!=(const QRect &lhs, const QRect &rhs) - Returns \c true if the rectangles \a r1 and \a r2 are different, otherwise - returns \c false. + Returns \c true if the rectangles \a lhs and \a rhs are different, + otherwise returns \c false. */ /*! @@ -1279,6 +1283,10 @@ QDebug operator<<(QDebug dbg, const QRect &r) \ingroup painting \reentrant + \compares equality + \compareswith equality QRect + \endcompareswith + \brief The QRectF class defines a finite rectangle in the plane using floating point precision. @@ -2346,10 +2354,10 @@ QRect QRectF::toAlignedRect() const noexcept */ /*! - \fn bool QRectF::operator==(const QRectF &r1, const QRectF &r2) + \fn bool QRectF::operator==(const QRectF &lhs, const QRectF &rhs) - Returns \c true if the rectangles \a r1 and \a r2 are \b approximately equal, - otherwise returns \c false. + Returns \c true if the rectangles \a lhs and \a rhs are \b approximately + equal, otherwise returns \c false. \warning This function does not check for strict equality; instead, it uses a fuzzy comparison to compare the rectangles' coordinates. @@ -2359,9 +2367,9 @@ QRect QRectF::toAlignedRect() const noexcept /*! - \fn bool QRectF::operator!=(const QRectF &r1, const QRectF &r2) + \fn bool QRectF::operator!=(const QRectF &lhs, const QRectF &rhs) - Returns \c true if the rectangles \a r1 and \a r2 are sufficiently + Returns \c true if the rectangles \a lhs and \a rhs are sufficiently different, otherwise returns \c false. \warning This function does not check for strict inequality; instead, diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h index e69a217f48..db70535a18 100644 --- a/src/corelib/tools/qrect.h +++ b/src/corelib/tools/qrect.h @@ -119,12 +119,13 @@ public: [[nodiscard]] static constexpr inline QRect span(const QPoint &p1, const QPoint &p2) noexcept; - friend constexpr inline bool operator==(const QRect &r1, const QRect &r2) noexcept +private: + friend constexpr bool comparesEqual(const QRect &r1, const QRect &r2) noexcept { return r1.x1==r2.x1 && r1.x2==r2.x2 && r1.y1==r2.y1 && r1.y2==r2.y2; } - friend constexpr inline bool operator!=(const QRect &r1, const QRect &r2) noexcept - { return r1.x1!=r2.x1 || r1.x2!=r2.x2 || r1.y1!=r2.y1 || r1.y2!=r2.y2; } + Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QRect) friend constexpr inline size_t qHash(const QRect &, size_t) noexcept; +public: #if defined(Q_OS_DARWIN) || defined(Q_QDOC) [[nodiscard]] CGRect toCGRect() const noexcept; #endif @@ -572,17 +573,19 @@ public: constexpr inline QRectF &operator+=(const QMarginsF &margins) noexcept; constexpr inline QRectF &operator-=(const QMarginsF &margins) noexcept; - friend constexpr inline bool operator==(const QRectF &r1, const QRectF &r2) noexcept +private: + friend constexpr bool comparesEqual(const QRectF &r1, const QRectF &r2) noexcept { return r1.topLeft() == r2.topLeft() && r1.size() == r2.size(); } - friend constexpr inline bool operator!=(const QRectF &r1, const QRectF &r2) noexcept - { - return r1.topLeft() != r2.topLeft() - || r1.size() != r2.size(); - } + Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QRectF) + friend constexpr bool comparesEqual(const QRectF &r1, const QRect &r2) noexcept + { return r1.topLeft() == r2.topLeft() && r1.size() == r2.size(); } + Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QRectF, QRect) + +public: [[nodiscard]] constexpr inline QRect toRect() const noexcept; [[nodiscard]] QRect toAlignedRect() const noexcept; diff --git a/tests/auto/corelib/tools/qrect/CMakeLists.txt b/tests/auto/corelib/tools/qrect/CMakeLists.txt index a02e1c33a5..c98c836379 100644 --- a/tests/auto/corelib/tools/qrect/CMakeLists.txt +++ b/tests/auto/corelib/tools/qrect/CMakeLists.txt @@ -14,4 +14,6 @@ endif() qt_internal_add_test(tst_qrect SOURCES tst_qrect.cpp + LIBRARIES + Qt::TestPrivate ) diff --git a/tests/auto/corelib/tools/qrect/tst_qrect.cpp b/tests/auto/corelib/tools/qrect/tst_qrect.cpp index 0f3dd1a0ef..43b46d8d8e 100644 --- a/tests/auto/corelib/tools/qrect/tst_qrect.cpp +++ b/tests/auto/corelib/tools/qrect/tst_qrect.cpp @@ -7,6 +7,8 @@ #include #include +#include + #include class tst_QRect : public QObject @@ -33,6 +35,9 @@ public: static QPoint getQPointCase( QPointCases p ); private slots: + void comparisonCompiles(); + void comparison_data(); + void comparison(); void isNull_data(); void isNull(); void newIsEmpty_data(); @@ -160,6 +165,8 @@ private slots: #define LARGE 1000000000 static bool isLarge(int x) { return x > LARGE || x < -LARGE; } +static constexpr qreal qreal_min = std::numeric_limits::min(); + QRect tst_QRect::getQRectCase( QRectCases c ) { // Should return the best variety of possible QRects, if a @@ -242,6 +249,66 @@ QPoint tst_QRect::getQPointCase( QPointCases p ) } } +void tst_QRect::comparisonCompiles() +{ + QTestPrivate::testEqualityOperatorsCompile(); + QTestPrivate::testEqualityOperatorsCompile(); + QTestPrivate::testEqualityOperatorsCompile(); +} + +void tst_QRect::comparison_data() +{ + QTest::addColumn("lhsF"); + QTest::addColumn("rhsF"); + QTest::addColumn("result"); + QTest::addColumn("floatResult"); + QTest::addColumn("mixedResult"); + + QTest::newRow("Invalid_vs_Invalid") << getQRectCase(InvalidQRect).toRectF() + << getQRectCase(InvalidQRect).toRectF() + << true << true << true; + + QTest::newRow("Null_vs_Null") << getQRectCase(NullQRect).toRectF() + << getQRectCase(NullQRect).toRectF() + << true << true << true; + + QTest::newRow("Empty_vs_Empty") << getQRectCase(EmptyQRect).toRectF() + << getQRectCase(EmptyQRect).toRectF() + << true << true << true; + + QTest::newRow("NegativeSize_vs_NegativeSize") << getQRectCase(NegativeSizeQRect).toRectF() + << getQRectCase(NegativeSizeQRect).toRectF() + << true << true << true; + + QTest::newRow("Invalid_vs_Null") << getQRectCase(InvalidQRect).toRectF() + << getQRectCase(NullQRect).toRectF() + << false << false << false; + + QTest::newRow("NearlySimilar") << QRectF(QPointF(1.1, 9.9), QPointF(9.9, 1.1)) + << QRectF(QPointF(1., 10.), QPointF(10., 1.)) + << true << false << true; + + QTest::newRow("WithQREAL_MIN") << QRectF(QPointF(0., -10.), QPointF(-1., 0.)) + << QRectF(QPointF(-qreal_min, -10.), QPointF(-1., qreal_min)) + << true << true << true; +} + +void tst_QRect::comparison() +{ + QFETCH(const QRectF, lhsF); + QFETCH(const QRectF, rhsF); + QFETCH(const bool, result); + QFETCH(const bool, floatResult); + QFETCH(const bool, mixedResult); + + const QRect lhs = lhsF.toRect(); + const QRect rhs = rhsF.toRect(); + + QT_TEST_EQUALITY_OPS(lhs, rhs, result); + QT_TEST_EQUALITY_OPS(lhsF, rhsF, floatResult); + QT_TEST_EQUALITY_OPS(lhs, rhsF, mixedResult); +} + void tst_QRect::isNull_data() { QTest::addColumn("r");