summaryrefslogtreecommitdiffstats
path: root/src/corelib/global
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-02-26 12:50:31 +0100
committerLars Knoll <lars.knoll@qt.io>2020-06-25 06:20:18 +0200
commit95e84c0ea95d3d3b7556c5c12bb2a52f856675d5 (patch)
tree5f0bbb285e8683240d6131070b5ee6ac1830979f /src/corelib/global
parent0dbd2dd86389c0705dbe9f518aed12f609ed09a1 (diff)
Allow qMin, qMax and qBound for types that can be losslessly converted
Add overloads for qMin and friends where the arguments are of different type, but one can be easily promoted to the other. Return the promoted type. Promotions are only allowed if both types are either signed, unsigned or floating point numbers. This should simplify writing code in many case (as for example qMin(myint64, 1)) and also help reduce source incompatibilities between Qt 5 and Qt 6, where the return types for sizes of our containers changes from int to qsizetype. Change-Id: Ia6bcf16bef0469ea568063e7c32f532da610d1cd Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/corelib/global')
-rw-r--r--src/corelib/global/qglobal.h43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index bbcb1d5880..08e631568d 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -617,6 +617,24 @@ Q_DECL_CONSTEXPR inline qint64 qRound64(double d)
Q_DECL_CONSTEXPR inline qint64 qRound64(float d)
{ return d >= 0.0f ? qint64(d + 0.5f) : qint64(d - float(qint64(d-1)) + 0.5f) + qint64(d-1); }
+namespace QTypeTraits {
+
+namespace detail {
+template<typename T, typename U,
+ typename = std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U> &&
+ std::is_floating_point_v<T> == std::is_floating_point_v<U> &&
+ std::is_signed_v<T> == std::is_signed_v<U>> >
+struct Promoted
+{
+ using type = decltype(T() + U());
+};
+}
+
+template <typename T, typename U>
+using Promoted = typename detail::Promoted<T, U>::type;
+
+}
+
template <typename T>
constexpr inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; }
template <typename T>
@@ -624,6 +642,31 @@ constexpr inline const T &qMax(const T &a, const T &b) { return (a < b) ? b : a;
template <typename T>
constexpr inline const T &qBound(const T &min, const T &val, const T &max)
{ return qMax(min, qMin(max, val)); }
+template <typename T, typename U>
+constexpr inline QTypeTraits::Promoted<T, U> qMin(const T &a, const U &b)
+{
+ using P = QTypeTraits::Promoted<T, U>;
+ P _a = a;
+ P _b = b;
+ return (_a < _b) ? _a : _b;
+}
+template <typename T, typename U>
+constexpr inline QTypeTraits::Promoted<T, U> qMax(const T &a, const U &b)
+{
+ using P = QTypeTraits::Promoted<T, U>;
+ P _a = a;
+ P _b = b;
+ return (_a < _b) ? _b : _a;
+}
+template <typename T, typename U>
+constexpr inline QTypeTraits::Promoted<T, U> qBound(const T &min, const U &val, const T &max)
+{ return qMax(min, qMin(max, val)); }
+template <typename T, typename U>
+constexpr inline QTypeTraits::Promoted<T, U> qBound(const T &min, const T &val, const U &max)
+{ return qMax(min, qMin(max, val)); }
+template <typename T, typename U>
+constexpr inline QTypeTraits::Promoted<T, U> qBound(const U &min, const T &val, const T &max)
+{ return qMax(min, qMin(max, val)); }
#ifndef Q_FORWARD_DECLARE_OBJC_CLASS
# ifdef __OBJC__