From 0e22001a3bb070d4e9956e89543ec0e5ac6f23f8 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Wed, 24 Feb 2021 19:44:09 +0100 Subject: Add more support for structured bindings After QPoint(F), it's now the time of QSize(F) and QVectorND, which can be unambiguously decomposed. [ChangeLog][QtCore][QSize] QSize is now usable in a structured binding declaration. [ChangeLog][QtCore][QSizeF] QSizeF is now usable in a structured binding declaration. [ChangeLog][QtGui][QVector2D] QVector2D is now usable in a structured binding declaration. [ChangeLog][QtGui][QVector3D] QVector3D is now usable in a structured binding declaration. [ChangeLog][QtGui][QVector4D] QVector4D is now usable in a structured binding declaration. Change-Id: I67bb152f4210f2be27607179cd2ec522174cc483 Reviewed-by: Volker Hilsheimer --- src/corelib/tools/qsize.h | 44 +++++++++++++ src/gui/math3d/qvectornd.h | 79 +++++++++++++++++++++++ tests/auto/corelib/tools/qsize/tst_qsize.cpp | 23 +++++++ tests/auto/corelib/tools/qsizef/tst_qsizef.cpp | 23 +++++++ tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp | 69 ++++++++++++++++++++ 5 files changed, 238 insertions(+) diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h index 23b4396d79..bab193031c 100644 --- a/src/corelib/tools/qsize.h +++ b/src/corelib/tools/qsize.h @@ -112,6 +112,18 @@ public: private: int wd; int ht; + + template = true, + std::enable_if_t, QSize>, bool> = true> + friend constexpr decltype(auto) get(S &&s) noexcept + { + if constexpr (I == 0) + return (std::forward(s).wd); + else if constexpr (I == 1) + return (std::forward(s).ht); + } }; Q_DECLARE_TYPEINFO(QSize, Q_RELOCATABLE_TYPE); @@ -289,6 +301,18 @@ public: private: qreal wd; qreal ht; + + template = true, + std::enable_if_t, QSizeF>, bool> = true> + friend constexpr decltype(auto) get(S &&s) noexcept + { + if constexpr (I == 0) + return (std::forward(s).wd); + else if constexpr (I == 1) + return (std::forward(s).ht); + } }; Q_DECLARE_TYPEINFO(QSizeF, Q_RELOCATABLE_TYPE); @@ -402,4 +426,24 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QSizeF &); QT_END_NAMESPACE +/***************************************************************************** + QSize/QSizeF tuple protocol + *****************************************************************************/ + +namespace std { + template <> + class tuple_size : public integral_constant {}; + template <> + class tuple_element<0, QT_PREPEND_NAMESPACE(QSize)> { public: using type = int; }; + template <> + class tuple_element<1, QT_PREPEND_NAMESPACE(QSize)> { public: using type = int; }; + + template <> + class tuple_size : public integral_constant {}; + template <> + class tuple_element<0, QT_PREPEND_NAMESPACE(QSizeF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); }; + template <> + class tuple_element<1, QT_PREPEND_NAMESPACE(QSizeF)> { public: using type = QT_PREPEND_NAMESPACE(qreal); }; +} + #endif // QSIZE_H diff --git a/src/gui/math3d/qvectornd.h b/src/gui/math3d/qvectornd.h index 153f3743d8..dec98bd936 100644 --- a/src/gui/math3d/qvectornd.h +++ b/src/gui/math3d/qvectornd.h @@ -177,6 +177,18 @@ private: friend class QVector3D; friend class QVector4D; + + template = true, + std::enable_if_t, QVector2D>, bool> = true> + friend constexpr decltype(auto) get(V &&vec) noexcept + { + if constexpr (I == 0) + return (std::forward(vec).v[0]); + else if constexpr (I == 1) + return (std::forward(vec).v[1]); + } }; Q_DECLARE_TYPEINFO(QVector2D, Q_PRIMITIVE_TYPE); @@ -327,6 +339,20 @@ private: friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix); friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector); #endif + + template = true, + std::enable_if_t, QVector3D>, bool> = true> + friend constexpr decltype(auto) get(V &&vec) noexcept + { + if constexpr (I == 0) + return (std::forward(vec).v[0]); + else if constexpr (I == 1) + return (std::forward(vec).v[1]); + else if constexpr (I == 2) + return (std::forward(vec).v[2]); + } }; Q_DECLARE_TYPEINFO(QVector3D, Q_PRIMITIVE_TYPE); @@ -470,6 +496,22 @@ private: friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix); friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector); #endif + + template = true, + std::enable_if_t, QVector4D>, bool> = true> + friend constexpr decltype(auto) get(V &&vec) noexcept + { + if constexpr (I == 0) + return (std::forward(vec).v[0]); + else if constexpr (I == 1) + return (std::forward(vec).v[1]); + else if constexpr (I == 2) + return (std::forward(vec).v[2]); + else if constexpr (I == 3) + return (std::forward(vec).v[3]); + } }; Q_DECLARE_TYPEINFO(QVector4D, Q_PRIMITIVE_TYPE); @@ -1050,4 +1092,41 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QVector4D &); QT_END_NAMESPACE +/***************************** Tuple protocol *****************************/ + +namespace std { +#ifndef QT_NO_VECTOR2D + template <> + class tuple_size : public integral_constant {}; + template <> + class tuple_element<0, QT_PREPEND_NAMESPACE(QVector2D)> { public: using type = float; }; + template <> + class tuple_element<1, QT_PREPEND_NAMESPACE(QVector2D)> { public: using type = float; }; +#endif // QT_NO_VECTOR2D + +#ifndef QT_NO_VECTOR3D + template <> + class tuple_size : public integral_constant {}; + template <> + class tuple_element<0, QT_PREPEND_NAMESPACE(QVector3D)> { public: using type = float; }; + template <> + class tuple_element<1, QT_PREPEND_NAMESPACE(QVector3D)> { public: using type = float; }; + template <> + class tuple_element<2, QT_PREPEND_NAMESPACE(QVector3D)> { public: using type = float; }; +#endif // QT_NO_VECTOR3D + +#ifndef QT_NO_VECTOR4D + template <> + class tuple_size : public integral_constant {}; + template <> + class tuple_element<0, QT_PREPEND_NAMESPACE(QVector4D)> { public: using type = float; }; + template <> + class tuple_element<1, QT_PREPEND_NAMESPACE(QVector4D)> { public: using type = float; }; + template <> + class tuple_element<2, QT_PREPEND_NAMESPACE(QVector4D)> { public: using type = float; }; + template <> + class tuple_element<3, QT_PREPEND_NAMESPACE(QVector4D)> { public: using type = float; }; +#endif // QT_NO_VECTOR4D +} + #endif // QVECTORND_H diff --git a/tests/auto/corelib/tools/qsize/tst_qsize.cpp b/tests/auto/corelib/tools/qsize/tst_qsize.cpp index 1bac2bd19b..83b4f1bd34 100644 --- a/tests/auto/corelib/tools/qsize/tst_qsize.cpp +++ b/tests/auto/corelib/tools/qsize/tst_qsize.cpp @@ -49,6 +49,8 @@ private slots: void transpose_data(); void transpose(); + + void structuredBinding(); }; // Testing get/set functions @@ -250,5 +252,26 @@ void tst_QSize::transpose() QCOMPARE(input1 , expected); } +void tst_QSize::structuredBinding() +{ + { + QSize size(10, 20); + auto [width, height] = size; + QCOMPARE(width, 10); + QCOMPARE(height, 20); + } + { + QSize size(30, 40); + auto &[width, height] = size; + QCOMPARE(width, 30); + QCOMPARE(height, 40); + + width = 100; + height = 200; + QCOMPARE(size.width(), 100); + QCOMPARE(size.height(), 200); + } +} + QTEST_APPLESS_MAIN(tst_QSize) #include "tst_qsize.moc" diff --git a/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp b/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp index af45c3c91f..3a65506dee 100644 --- a/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp +++ b/tests/auto/corelib/tools/qsizef/tst_qsizef.cpp @@ -51,6 +51,8 @@ private slots: void transpose_data(); void transpose(); + + void structuredBinding(); }; void tst_QSizeF::isNull_data() @@ -214,5 +216,26 @@ void tst_QSizeF::transpose() { QCOMPARE(input1 , expected); } +void tst_QSizeF::structuredBinding() +{ + { + QSizeF size(10.0, 20.0); + auto [width, height] = size; + QCOMPARE(width, 10.0); + QCOMPARE(height, 20.0); + } + { + QSizeF size(30.0, 40.0); + auto &[width, height] = size; + QCOMPARE(width, 30.0); + QCOMPARE(height, 40.0); + + width = 100.0; + height = 200.0; + QCOMPARE(size.width(), 100.0); + QCOMPARE(size.height(), 200.0); + } +} + QTEST_APPLESS_MAIN(tst_QSizeF) #include "tst_qsizef.moc" diff --git a/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp b/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp index 9d3f7dda7c..c7bcb9d262 100644 --- a/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp +++ b/tests/auto/gui/math3d/qvectornd/tst_qvectornd.cpp @@ -152,6 +152,8 @@ private slots: void properties(); void metaTypes(); + + void structuredBinding(); }; // Test the creation of QVector2D objects in various ways: @@ -2682,6 +2684,73 @@ void tst_QVectorND::metaTypes() QCOMPARE(qMetaTypeId(), int(QMetaType::QVector4D)); } +void tst_QVectorND::structuredBinding() +{ + { + QVector2D v(1.0f, 2.0f); + auto [x, y] = v; + QCOMPARE(x, 1.0f); + QCOMPARE(y, 2.0f); + } + { + QVector2D v(1.0f, 2.0f); + auto &[x, y] = v; + QCOMPARE(x, 1.0f); + QCOMPARE(y, 2.0f); + + x = 10.0f; + y = 20.0f; + QCOMPARE(v.x(), 10.0f); + QCOMPARE(v.y(), 20.0f); + } + { + QVector3D v(1.0f, 2.0f, 3.0); + auto [x, y, z] = v; + QCOMPARE(x, 1.0f); + QCOMPARE(y, 2.0f); + QCOMPARE(z, 3.0f); + } + { + QVector3D v(1.0f, 2.0f, 3.0); + auto &[x, y, z] = v; + QCOMPARE(x, 1.0f); + QCOMPARE(y, 2.0f); + QCOMPARE(z, 3.0f); + + x = 10.0f; + y = 20.0f; + z = 30.0f; + QCOMPARE(v.x(), 10.0f); + QCOMPARE(v.y(), 20.0f); + QCOMPARE(v.z(), 30.0f); + } + { + QVector4D v(1.0f, 2.0f, 3.0, 4.0); + auto [x, y, z, w] = v; + QCOMPARE(x, 1.0f); + QCOMPARE(y, 2.0f); + QCOMPARE(z, 3.0f); + QCOMPARE(w, 4.0f); + } + { + QVector4D v(1.0f, 2.0f, 3.0, 4.0); + auto &[x, y, z, w] = v; + QCOMPARE(x, 1.0f); + QCOMPARE(y, 2.0f); + QCOMPARE(z, 3.0f); + QCOMPARE(w, 4.0f); + + x = 10.0f; + y = 20.0f; + z = 30.0f; + w = 40.0f; + QCOMPARE(v.x(), 10.0f); + QCOMPARE(v.y(), 20.0f); + QCOMPARE(v.z(), 30.0f); + QCOMPARE(v.w(), 40.0f); + } +} + QTEST_APPLESS_MAIN(tst_QVectorND) #include "tst_qvectornd.moc" -- cgit v1.2.3