From fb6b7869e8bdda94f7e791db7f281f3bb6e0e004 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Thu, 19 Mar 2020 17:57:05 +0100 Subject: [PATCH] QPoint(F): add support for structured binding QPoint(F) are "naturally" destructurable in their x/y counterparts (hello Mac/Carbon users, we don't live in 1999 any more, it's x and then y, and not vice versa...). [ChangeLog][QtCore][QPoint] QPoint is usable in a structured binding. [ChangeLog][QtCore][QPointF] QPointF is usable in a structured binding. Change-Id: I8718a4e80be4ce03f37f012034f1fba009304b32 Reviewed-by: Thiago Macieira --- src/corelib/tools/qpoint.h | 44 ++++++++++++++ .../auto/corelib/tools/qpoint/tst_qpoint.cpp | 59 ++++++++++++++++++ .../corelib/tools/qpointf/tst_qpointf.cpp | 60 +++++++++++++++++++ 3 files changed, 163 insertions(+) diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h index d69e793d3a..f2acb9f3ad 100644 --- a/src/corelib/tools/qpoint.h +++ b/src/corelib/tools/qpoint.h @@ -115,6 +115,18 @@ private: friend class QTransform; int xp; int yp; + + template = true, + std::enable_if_t, QPoint>, bool> = true> + friend constexpr decltype(auto) get(P &&p) noexcept + { + if constexpr (I == 0) + return (std::forward

(p).xp); + else if constexpr (I == 1) + return (std::forward

(p).yp); + } }; Q_DECLARE_TYPEINFO(QPoint, Q_MOVABLE_TYPE); @@ -297,6 +309,18 @@ private: qreal xp; qreal yp; + + template = true, + std::enable_if_t, QPointF>, bool> = true> + friend constexpr decltype(auto) get(P &&p) noexcept + { + if constexpr (I == 0) + return (std::forward

(p).xp); + else if constexpr (I == 1) + return (std::forward

(p).yp); + } }; Q_DECLARE_TYPEINFO(QPointF, Q_MOVABLE_TYPE); @@ -398,4 +422,24 @@ Q_CORE_EXPORT QDebug operator<<(QDebug d, const QPointF &p); QT_END_NAMESPACE +/***************************************************************************** + QPoint/QPointF tuple protocol + *****************************************************************************/ + +namespace std { + template <> + class tuple_size : public integral_constant {}; + template <> + class tuple_element<0, QT_PREPEND_NAMESPACE(QPoint)> { public: using type = int; }; + template <> + class tuple_element<1, QT_PREPEND_NAMESPACE(QPoint)> { public: using type = int; }; + + template <> + class tuple_size : public integral_constant {}; + template <> + class tuple_element<0, QT_PREPEND_NAMESPACE(QPointF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); }; + template <> + class tuple_element<1, QT_PREPEND_NAMESPACE(QPointF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); }; +} + #endif // QPOINT_H diff --git a/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp b/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp index 0f3edb3eed..59ea28454e 100644 --- a/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp +++ b/tests/auto/corelib/tools/qpoint/tst_qpoint.cpp @@ -75,6 +75,8 @@ private slots: void stream_data(); void stream(); #endif + + void structuredBinding(); }; void tst_QPoint::isNull() @@ -381,5 +383,62 @@ void tst_QPoint::stream() } #endif +void tst_QPoint::structuredBinding() +{ + { + QPoint p(1, 2); + auto [x, y] = p; + QCOMPARE(x, 1); + QCOMPARE(y, 2); + + p.setX(42); + QCOMPARE(x, 1); + QCOMPARE(y, 2); + + p.setY(-123); + QCOMPARE(x, 1); + QCOMPARE(y, 2); + } + { + QPoint p(1, 2); + + auto &[x, y] = p; + QCOMPARE(x, 1); + QCOMPARE(y, 2); + + x = 42; + QCOMPARE(x, 42); + QCOMPARE(p.x(), 42); + QCOMPARE(p.rx(), 42); + QCOMPARE(y, 2); + QCOMPARE(p.y(), 2); + QCOMPARE(p.ry(), 2); + + y = -123; + QCOMPARE(x, 42); + QCOMPARE(p.x(), 42); + QCOMPARE(p.rx(), 42); + QCOMPARE(y, -123); + QCOMPARE(p.y(), -123); + QCOMPARE(p.ry(), -123); + + p.setX(0); + QCOMPARE(x, 0); + QCOMPARE(p.x(), 0); + QCOMPARE(p.rx(), 0); + QCOMPARE(y, -123); + QCOMPARE(p.y(), -123); + QCOMPARE(p.ry(), -123); + + p.ry() = 10; + QCOMPARE(x, 0); + QCOMPARE(p.x(), 0); + QCOMPARE(p.rx(), 0); + QCOMPARE(y, 10); + QCOMPARE(p.y(), 10); + QCOMPARE(p.ry(), 10); + } +} + QTEST_MAIN(tst_QPoint) #include "tst_qpoint.moc" diff --git a/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp b/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp index ef08352dfc..21b9d56737 100644 --- a/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp +++ b/tests/auto/corelib/tools/qpointf/tst_qpointf.cpp @@ -86,6 +86,8 @@ private slots: void stream(); #endif + void structuredBinding(); + private: const qreal QREAL_MIN; const qreal QREAL_MAX; @@ -462,5 +464,63 @@ void tst_QPointF::compare() QVERIFY(QPointF(1.9543e-14, -32.0) == QPointF(0.0, -32.0)); } + +void tst_QPointF::structuredBinding() +{ + { + QPointF p(1.5, 2.25); + auto [x, y] = p; + QCOMPARE(x, 1.5); + QCOMPARE(y, 2.25); + + p.setX(42); + QCOMPARE(x, 1.5); + QCOMPARE(y, 2.25); + + p.setY(-123); + QCOMPARE(x, 1.5); + QCOMPARE(y, 2.25); + } + { + QPointF p(1.5, 2.25); + + auto &[x, y] = p; + QCOMPARE(x, 1.5); + QCOMPARE(y, 2.25); + + x = 42.0; + QCOMPARE(x, 42.0); + QCOMPARE(p.x(), 42.0); + QCOMPARE(p.rx(), 42.0); + QCOMPARE(y, 2.25); + QCOMPARE(p.y(), 2.25); + QCOMPARE(p.ry(), 2.25); + + y = -123.5; + QCOMPARE(x, 42.0); + QCOMPARE(p.x(), 42.0); + QCOMPARE(p.rx(), 42.0); + QCOMPARE(y, -123.5); + QCOMPARE(p.y(), -123.5); + QCOMPARE(p.ry(), -123.5); + + p.setX(0.0); + QCOMPARE(x, 0.0); + QCOMPARE(p.x(), 0.0); + QCOMPARE(p.rx(), 0.0); + QCOMPARE(y, -123.5); + QCOMPARE(p.y(), -123.5); + QCOMPARE(p.ry(), -123.5); + + p.ry() = 10.5; + QCOMPARE(x, 0.0); + QCOMPARE(p.x(), 0.0); + QCOMPARE(p.rx(), 0.0); + QCOMPARE(y, 10.5); + QCOMPARE(p.y(), 10.5); + QCOMPARE(p.ry(), 10.5); + } +} + QTEST_MAIN(tst_QPointF) #include "tst_qpointf.moc"