Modernize Tuple Protocol implementations

The existing get<I>() implementations are very clever™, if I, as their
inventor in at least the Qt ecosystem, may say so myself. E.g. the ()
around the return value are absolutely required, to ensure we return
by reference, not by value, through decltype(auto).

C++23 gives us forward_like, which doesn't require the parentheses,
because it always returns a reference.

Also replace decay_t with C++20's remove_cvref_t, the latter being
more efficient (performs less work).

Change-Id: Ic9ed0c25e6d6bfbd77d7c85858a8d97fe58be615
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2023-03-15 09:54:29 +01:00
parent 49e5f21908
commit 9e18e5c869
4 changed files with 40 additions and 28 deletions

View File

@ -6,6 +6,9 @@
#include <QtCore/qnamespace.h>
#include <QtCore/q20type_traits.h>
#include <QtCore/q23utility.h>
QT_BEGIN_NAMESPACE
class QMarginsF;
@ -66,17 +69,17 @@ private:
template <std::size_t I,
typename M,
std::enable_if_t<(I < 4), bool> = true,
std::enable_if_t<std::is_same_v<std::decay_t<M>, QMargins>, bool> = true>
std::enable_if_t<std::is_same_v<q20::remove_cvref_t<M>, QMargins>, bool> = true>
friend constexpr decltype(auto) get(M &&m) noexcept
{
if constexpr (I == 0)
return (std::forward<M>(m).m_left);
return q23::forward_like<M>(m.m_left);
else if constexpr (I == 1)
return (std::forward<M>(m).m_top);
return q23::forward_like<M>(m.m_top);
else if constexpr (I == 2)
return (std::forward<M>(m).m_right);
return q23::forward_like<M>(m.m_right);
else if constexpr (I == 3)
return (std::forward<M>(m).m_bottom);
return q23::forward_like<M>(m.m_bottom);
}
};
@ -315,17 +318,17 @@ private:
template <std::size_t I,
typename M,
std::enable_if_t<(I < 4), bool> = true,
std::enable_if_t<std::is_same_v<std::decay_t<M>, QMarginsF>, bool> = true>
std::enable_if_t<std::is_same_v<q20::remove_cvref_t<M>, QMarginsF>, bool> = true>
friend constexpr decltype(auto) get(M &&m) noexcept
{
if constexpr (I == 0)
return (std::forward<M>(m).m_left);
return q23::forward_like<M>(m.m_left);
else if constexpr (I == 1)
return (std::forward<M>(m).m_top);
return q23::forward_like<M>(m.m_top);
else if constexpr (I == 2)
return (std::forward<M>(m).m_right);
return q23::forward_like<M>(m.m_right);
else if constexpr (I == 3)
return (std::forward<M>(m).m_bottom);
return q23::forward_like<M>(m.m_bottom);
}
};

View File

@ -6,6 +6,9 @@
#include <QtCore/qnamespace.h>
#include <QtCore/q20type_traits.h>
#include <QtCore/q23utility.h>
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
struct CGPoint;
#endif
@ -86,13 +89,13 @@ private:
template <std::size_t I,
typename P,
std::enable_if_t<(I < 2), bool> = true,
std::enable_if_t<std::is_same_v<std::decay_t<P>, QPoint>, bool> = true>
std::enable_if_t<std::is_same_v<q20::remove_cvref_t<P>, QPoint>, bool> = true>
friend constexpr decltype(auto) get(P &&p) noexcept
{
if constexpr (I == 0)
return (std::forward<P>(p).xp);
return q23::forward_like<P>(p.xp);
else if constexpr (I == 1)
return (std::forward<P>(p).yp);
return q23::forward_like<P>(p.yp);
}
};
@ -283,13 +286,13 @@ private:
template <std::size_t I,
typename P,
std::enable_if_t<(I < 2), bool> = true,
std::enable_if_t<std::is_same_v<std::decay_t<P>, QPointF>, bool> = true>
std::enable_if_t<std::is_same_v<q20::remove_cvref_t<P>, QPointF>, bool> = true>
friend constexpr decltype(auto) get(P &&p) noexcept
{
if constexpr (I == 0)
return (std::forward<P>(p).xp);
return q23::forward_like<P>(p.xp);
else if constexpr (I == 1)
return (std::forward<P>(p).yp);
return q23::forward_like<P>(p.yp);
}
};

View File

@ -8,6 +8,9 @@
#include <QtCore/qhashfunctions.h>
#include <QtCore/qmargins.h>
#include <QtCore/q20type_traits.h>
#include <QtCore/q23utility.h>
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
struct CGSize;
#endif
@ -83,13 +86,13 @@ private:
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>
std::enable_if_t<std::is_same_v<q20::remove_cvref_t<S>, QSize>, bool> = true>
friend constexpr decltype(auto) get(S &&s) noexcept
{
if constexpr (I == 0)
return (std::forward<S>(s).wd);
return q23::forward_like<S>(s.wd);
else if constexpr (I == 1)
return (std::forward<S>(s).ht);
return q23::forward_like<S>(s.ht);
}
};
Q_DECLARE_TYPEINFO(QSize, Q_RELOCATABLE_TYPE);
@ -272,13 +275,13 @@ private:
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>
std::enable_if_t<std::is_same_v<q20::remove_cvref_t<S>, QSizeF>, bool> = true>
friend constexpr decltype(auto) get(S &&s) noexcept
{
if constexpr (I == 0)
return (std::forward<S>(s).wd);
return q23::forward_like<S>(s.wd);
else if constexpr (I == 1)
return (std::forward<S>(s).ht);
return q23::forward_like<S>(s.ht);
}
};
Q_DECLARE_TYPEINFO(QSizeF, Q_RELOCATABLE_TYPE);

View File

@ -10,6 +10,9 @@
#include <QtCore/qrect.h>
#include <QtCore/qmath.h>
#include <QtCore/q20type_traits.h>
#include <QtCore/q23utility.h>
QT_BEGIN_NAMESPACE
class QVector2D;
@ -145,10 +148,10 @@ private:
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>
std::enable_if_t<std::is_same_v<q20::remove_cvref_t<V>, QVector2D>, bool> = true>
friend constexpr decltype(auto) get(V &&vec) noexcept
{
return (std::forward<V>(vec).v[I]);
return q23::forward_like<V>(vec.v[I]);
}
};
@ -304,10 +307,10 @@ private:
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>
std::enable_if_t<std::is_same_v<q20::remove_cvref_t<V>, QVector3D>, bool> = true>
friend constexpr decltype(auto) get(V &&vec) noexcept
{
return (std::forward<V>(vec).v[I]);
return q23::forward_like<V>(vec.v[I]);
}
};
@ -456,10 +459,10 @@ private:
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>
std::enable_if_t<std::is_same_v<q20::remove_cvref_t<V>, QVector4D>, bool> = true>
friend constexpr decltype(auto) get(V &&vec) noexcept
{
return (std::forward<V>(vec).v[I]);
return q23::forward_like<V>(vec.v[I]);
}
};