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 <volker.hilsheimer@qt.io>
This commit is contained in:
parent
2af45d0cee
commit
0e22001a3b
@ -112,6 +112,18 @@ public:
|
||||
private:
|
||||
int wd;
|
||||
int ht;
|
||||
|
||||
template <std::size_t I,
|
||||
typename S,
|
||||
std::enable_if_t<(I < 2), bool> = true,
|
||||
std::enable_if_t<std::is_same_v<std::decay_t<S>, QSize>, bool> = true>
|
||||
friend constexpr decltype(auto) get(S &&s) noexcept
|
||||
{
|
||||
if constexpr (I == 0)
|
||||
return (std::forward<S>(s).wd);
|
||||
else if constexpr (I == 1)
|
||||
return (std::forward<S>(s).ht);
|
||||
}
|
||||
};
|
||||
Q_DECLARE_TYPEINFO(QSize, Q_RELOCATABLE_TYPE);
|
||||
|
||||
@ -289,6 +301,18 @@ public:
|
||||
private:
|
||||
qreal wd;
|
||||
qreal ht;
|
||||
|
||||
template <std::size_t I,
|
||||
typename S,
|
||||
std::enable_if_t<(I < 2), bool> = true,
|
||||
std::enable_if_t<std::is_same_v<std::decay_t<S>, QSizeF>, bool> = true>
|
||||
friend constexpr decltype(auto) get(S &&s) noexcept
|
||||
{
|
||||
if constexpr (I == 0)
|
||||
return (std::forward<S>(s).wd);
|
||||
else if constexpr (I == 1)
|
||||
return (std::forward<S>(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<QT_PREPEND_NAMESPACE(QSize)> : public integral_constant<size_t, 2> {};
|
||||
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<QT_PREPEND_NAMESPACE(QSizeF)> : public integral_constant<size_t, 2> {};
|
||||
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
|
||||
|
@ -177,6 +177,18 @@ private:
|
||||
|
||||
friend class QVector3D;
|
||||
friend class QVector4D;
|
||||
|
||||
template <std::size_t I,
|
||||
typename V,
|
||||
std::enable_if_t<(I < 2), bool> = true,
|
||||
std::enable_if_t<std::is_same_v<std::decay_t<V>, QVector2D>, bool> = true>
|
||||
friend constexpr decltype(auto) get(V &&vec) noexcept
|
||||
{
|
||||
if constexpr (I == 0)
|
||||
return (std::forward<V>(vec).v[0]);
|
||||
else if constexpr (I == 1)
|
||||
return (std::forward<V>(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 <std::size_t I,
|
||||
typename V,
|
||||
std::enable_if_t<(I < 3), bool> = true,
|
||||
std::enable_if_t<std::is_same_v<std::decay_t<V>, QVector3D>, bool> = true>
|
||||
friend constexpr decltype(auto) get(V &&vec) noexcept
|
||||
{
|
||||
if constexpr (I == 0)
|
||||
return (std::forward<V>(vec).v[0]);
|
||||
else if constexpr (I == 1)
|
||||
return (std::forward<V>(vec).v[1]);
|
||||
else if constexpr (I == 2)
|
||||
return (std::forward<V>(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 <std::size_t I,
|
||||
typename V,
|
||||
std::enable_if_t<(I < 4), bool> = true,
|
||||
std::enable_if_t<std::is_same_v<std::decay_t<V>, QVector4D>, bool> = true>
|
||||
friend constexpr decltype(auto) get(V &&vec) noexcept
|
||||
{
|
||||
if constexpr (I == 0)
|
||||
return (std::forward<V>(vec).v[0]);
|
||||
else if constexpr (I == 1)
|
||||
return (std::forward<V>(vec).v[1]);
|
||||
else if constexpr (I == 2)
|
||||
return (std::forward<V>(vec).v[2]);
|
||||
else if constexpr (I == 3)
|
||||
return (std::forward<V>(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<QT_PREPEND_NAMESPACE(QVector2D)> : public integral_constant<size_t, 2> {};
|
||||
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<QT_PREPEND_NAMESPACE(QVector3D)> : public integral_constant<size_t, 3> {};
|
||||
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<QT_PREPEND_NAMESPACE(QVector4D)> : public integral_constant<size_t, 4> {};
|
||||
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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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<QVector4D>(), 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"
|
||||
|
Loading…
Reference in New Issue
Block a user