QLine(F): use comparison helper macros

Also explicitly add QLineF vs QLine comparison. Previously such
comparison was implicitly converting QLine to QLineF, and doing the
fuzzy comparison.
The new operators are directly calling operator==(QPointF, QPoint),
which also does the fuzzy comparison, so the old behavior is preserved.

Remove the old relational operators using QT_CORE_REMOVED_SINCE, but
also wrap the new operators in !defined(QT_CORE_REMOVED_SINCE).
That is required, because on Windows the instantiation of
QMetaTypeInterface<QLine(F)> happens in removed_api.cpp (as both
qline.h and qmetatype.h are already included there). If we just add
removed member operators into removed_api.cpp, the metatype interface
will not be able to create an equals() function, because of the
ambiguity in equality operators (member vs friend). That's why we have
to exclude the new friend operators from removed_api.cpp.

Done-with: Fabian Kosmale <fabian.kosmale@qt.io>
Task-number: QTBUG-120308
Change-Id: Ibbf5ec077f69c75da0d36a8be5596acd0fcd44d0
Reviewed-by: Tatiana Borisova <tatiana.borisova@qt.io>
bb10
Ivan Solovev 2024-04-05 11:59:30 +02:00
parent fa0d77e290
commit 2a847dd93b
5 changed files with 118 additions and 14 deletions

View File

@ -1005,6 +1005,8 @@ bool QJsonValue::operator!=(const QJsonValue &other) const
return !comparesEqual(*this, other);
}
#include "qline.h" // inlined API
#include "qmimetype.h"
bool QMimeType::operator==(const QMimeType &other) const

View File

@ -14,6 +14,9 @@ QT_BEGIN_NAMESPACE
\class QLine
\inmodule QtCore
\ingroup painting
\compares equality
\compareswith equality QLineF
\endcompareswith
\brief The QLine class provides a two-dimensional vector using
integer precision.
@ -133,18 +136,18 @@ QT_BEGIN_NAMESPACE
*/
/*!
\fn bool QLine::operator!=(const QLine &line) const
\fn bool QLine::operator!=(const QLine &lhs, const QLine &rhs)
Returns \c true if the given \a line is not the same as \e this line.
Returns \c true if the line \a lhs is not the same as line \a rhs.
A line is different from another line if any of their start or
end points differ, or the internal order of the points is different.
*/
/*!
\fn bool QLine::operator==(const QLine &line) const
\fn bool QLine::operator==(const QLine &lhs, const QLine &rhs)
Returns \c true if the given \a line is the same as \e this line.
Returns \c true if the line \a lhs is the same as line \a rhs.
A line is identical to another line if the start and end points
are identical, and the internal order of the points is the same.
@ -288,6 +291,9 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
\class QLineF
\inmodule QtCore
\ingroup painting
\compares equality
\compareswith equality QLine
\endcompareswith
\brief The QLineF class provides a two-dimensional vector using
floating point precision.
@ -508,18 +514,18 @@ QDataStream &operator>>(QDataStream &stream, QLine &line)
*/
/*!
\fn bool QLineF::operator!=(const QLineF &line) const
\fn bool QLineF::operator!=(const QLineF &lhs, const QLineF &rhs)
Returns \c true if the given \a line is not the same as \e this line.
Returns \c true if the line \a lhs is not the same as line \a rhs.
A line is different from another line if their start or end points
differ, or the internal order of the points is different.
*/
/*!
\fn bool QLineF::operator==(const QLineF &line) const
\fn bool QLineF::operator==(const QLineF &lhs, const QLineF &rhs)
Returns \c true if the given \a line is the same as this line.
Returns \c true if the line \a lhs is the same as line \a rhs.
A line is identical to another line if the start and end points
are identical, and the internal order of the points is the same.

View File

@ -48,12 +48,20 @@ public:
inline void setPoints(const QPoint &p1, const QPoint &p2);
inline void setLine(int x1, int y1, int x2, int y2);
#if QT_CORE_REMOVED_SINCE(6, 8)
constexpr inline bool operator==(const QLine &d) const noexcept;
constexpr inline bool operator!=(const QLine &d) const noexcept { return !(*this == d); }
constexpr inline bool operator!=(const QLine &d) const noexcept { return !operator==(d); }
#endif
[[nodiscard]] constexpr inline QLineF toLineF() const noexcept;
private:
friend constexpr bool comparesEqual(const QLine &lhs, const QLine &rhs) noexcept
{ return lhs.pt1 == rhs.pt1 && lhs.pt2 == rhs.pt2; }
#if !QT_CORE_REMOVED_SINCE(6, 8)
Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QLine)
#endif
QPoint pt1, pt2;
};
Q_DECLARE_TYPEINFO(QLine, Q_PRIMITIVE_TYPE);
@ -161,10 +169,12 @@ inline void QLine::setLine(int aX1, int aY1, int aX2, int aY2)
pt2 = QPoint(aX2, aY2);
}
#if QT_CORE_REMOVED_SINCE(6, 8)
constexpr inline bool QLine::operator==(const QLine &d) const noexcept
{
return pt1 == d.pt1 && pt2 == d.pt2;
return comparesEqual(*this, d);
}
#endif
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug d, const QLine &p);
@ -233,12 +243,24 @@ public:
inline void setPoints(const QPointF &p1, const QPointF &p2);
inline void setLine(qreal x1, qreal y1, qreal x2, qreal y2);
#if QT_CORE_REMOVED_SINCE(6, 8)
constexpr inline bool operator==(const QLineF &d) const;
constexpr inline bool operator!=(const QLineF &d) const { return !(*this == d); }
constexpr inline bool operator!=(const QLineF &d) const { return !operator==(d); }
#endif
constexpr QLine toLine() const;
private:
friend constexpr bool comparesEqual(const QLineF &lhs, const QLineF &rhs) noexcept
{ return lhs.pt1 == rhs.pt1 && lhs.pt2 == rhs.pt2; }
#if !QT_CORE_REMOVED_SINCE(6, 8)
Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QLineF)
#endif
friend constexpr bool comparesEqual(const QLineF &lhs, const QLine &rhs) noexcept
{ return comparesEqual(lhs, rhs.toLineF()); }
Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QLineF, QLine)
QPointF pt1, pt2;
};
Q_DECLARE_TYPEINFO(QLineF, Q_PRIMITIVE_TYPE);
@ -383,12 +405,12 @@ inline void QLineF::setLine(qreal aX1, qreal aY1, qreal aX2, qreal aY2)
pt2 = QPointF(aX2, aY2);
}
#if QT_CORE_REMOVED_SINCE(6, 8)
constexpr inline bool QLineF::operator==(const QLineF &d) const
{
return pt1 == d.pt1 && pt2 == d.pt2;
return comparesEqual(*this, d);
}
#endif
#ifndef QT_NO_DEBUG_STREAM

View File

@ -14,6 +14,8 @@ endif()
qt_internal_add_test(tst_qline
SOURCES
tst_qline.cpp
LIBRARIES
Qt::TestPrivate
)
## Scopes:

View File

@ -4,6 +4,7 @@
#include <QTest>
#include <qline.h>
#include <qmath.h>
#include <private/qcomparisontesthelper_p.h>
#include <array>
@ -11,6 +12,10 @@ class tst_QLine : public QObject
{
Q_OBJECT
private slots:
void testComparisonCompiles();
void testComparison_data();
void testComparison();
void testIntersection();
void testIntersection_data();
@ -42,6 +47,73 @@ private slots:
const qreal epsilon = sizeof(qreal) == sizeof(double) ? 1e-8 : 1e-4;
void tst_QLine::testComparisonCompiles()
{
QTestPrivate::testEqualityOperatorsCompile<QLine>();
QTestPrivate::testEqualityOperatorsCompile<QLineF>();
QTestPrivate::testEqualityOperatorsCompile<QLineF, QLine>();
}
void tst_QLine::testComparison_data()
{
QTest::addColumn<double>("xa1");
QTest::addColumn<double>("ya1");
QTest::addColumn<double>("xa2");
QTest::addColumn<double>("ya2");
QTest::addColumn<double>("xb1");
QTest::addColumn<double>("yb1");
QTest::addColumn<double>("xb2");
QTest::addColumn<double>("yb2");
QTest::addColumn<bool>("result");
QTest::addColumn<bool>("floatResult");
QTest::addColumn<bool>("mixedResult");
auto row = [&](double xa1, double ya1, double xa2, double ya2,
double xb1, double yb1, double xb2, double yb2,
bool result, bool floatResult, bool mixedResult)
{
QString str;
QDebug dbg(&str);
dbg.nospace() << "[(" << xa1 << ", " << ya1 << "); (" << xa2 << ", " << ya2 << ")] vs [("
<< xb1 << ", " << yb1 << "); (" << xb2 << ", " << yb2 << ")]";
QTest::addRow("%s", str.toLatin1().constData())
<< xa1 << ya1 << xa2 << ya2 << xb1 << yb1 << xb2 << yb2
<< result << floatResult << mixedResult;
};
constexpr static qreal qreal_min = std::numeric_limits<qreal>::min();
row(-1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, true, true, true);
row(-1.1, -0.9, 1.1, 0.9, -1.0, -1.0, 1.0, 1.0, true, false, false);
row(-1.0, -1.0, 1.0, 1.0, -0.9, -1.1, 0.9, 1.1, true, false, true);
row(-qreal_min, -1.0, 1.0, qreal_min, 0.0, -1.1, 0.9, 0.0, true, false, true);
}
void tst_QLine::testComparison()
{
QFETCH(double, xa1);
QFETCH(double, ya1);
QFETCH(double, xa2);
QFETCH(double, ya2);
QFETCH(double, xb1);
QFETCH(double, yb1);
QFETCH(double, xb2);
QFETCH(double, yb2);
QFETCH(bool, result);
QFETCH(bool, floatResult);
QFETCH(bool, mixedResult);
const QLineF l1f(xa1, ya1, xa2, ya2);
const QLine l1 = l1f.toLine();
const QLineF l2f(xb1, yb1, xb2, yb2);
const QLine l2 = l2f.toLine();
QT_TEST_EQUALITY_OPS(l1, l2, result);
QT_TEST_EQUALITY_OPS(l1f, l2f, floatResult);
QT_TEST_EQUALITY_OPS(l1f, l2, mixedResult);
}
void tst_QLine::testSet()
{
{