diff options
author | Lars Knoll <lars.knoll@qt.io> | 2020-02-26 12:50:31 +0100 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2020-06-25 06:20:18 +0200 |
commit | 95e84c0ea95d3d3b7556c5c12bb2a52f856675d5 (patch) | |
tree | 5f0bbb285e8683240d6131070b5ee6ac1830979f /src/corelib/global | |
parent | 0dbd2dd86389c0705dbe9f518aed12f609ed09a1 (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.h | 43 |
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__ |