From c6fe64b17c87ec985f17389bf08eee46606862d4 Mon Sep 17 00:00:00 2001 From: Dennis Oberst Date: Thu, 4 May 2023 13:11:26 +0200 Subject: [PATCH] Add QStrongOrdering and QWeakOrdering These new classes align with the criteria of std::strong_ordering and std::weak_ordering and were the missing types required by the three-way comparison operator. References: https://en.cppreference.com/w/cpp/utility/compare/strong_ordering https://en.cppreference.com/w/cpp/utility/compare/weak_ordering Change-Id: Ie6620ca98103800fd5504810dc5689c1dd1c2972 Reviewed-by: Thiago Macieira Reviewed-by: Marc Mutz --- src/corelib/global/qcompare.h | 368 ++++++++++++++++++ src/corelib/global/qcompare.qdoc | 366 ++++++++++++++++- .../corelib/global/qcompare/tst_qcompare.cpp | 272 +++++++++++++ 3 files changed, 985 insertions(+), 21 deletions(-) diff --git a/src/corelib/global/qcompare.h b/src/corelib/global/qcompare.h index eb4167168e7..fadd10f4228 100644 --- a/src/corelib/global/qcompare.h +++ b/src/corelib/global/qcompare.h @@ -1,4 +1,5 @@ // Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QCOMPARE_H @@ -11,6 +12,10 @@ #include #include +#ifdef __cpp_lib_three_way_comparison +#include +#endif + QT_BEGIN_NAMESPACE namespace QtPrivate { @@ -97,7 +102,49 @@ public: friend constexpr bool operator!=(QPartialOrdering lhs, QPartialOrdering rhs) noexcept { return lhs.m_order != rhs.m_order; } +#ifdef __cpp_lib_three_way_comparison + constexpr Q_IMPLICIT QPartialOrdering(std::partial_ordering stdorder) noexcept + { + if (stdorder == std::partial_ordering::less) + m_order = static_cast(QtPrivate::Ordering::Less); + else if (stdorder == std::partial_ordering::equivalent) + m_order = static_cast(QtPrivate::Ordering::Equivalent); + else if (stdorder == std::partial_ordering::greater) + m_order = static_cast(QtPrivate::Ordering::Greater); + else if (stdorder == std::partial_ordering::unordered) + m_order = static_cast(QtPrivate::Uncomparable::Unordered); + } + + constexpr Q_IMPLICIT operator std::partial_ordering() const noexcept + { + if (static_cast(m_order) == QtPrivate::Ordering::Less) + return std::partial_ordering::less; + else if (static_cast(m_order) == QtPrivate::Ordering::Equivalent) + return std::partial_ordering::equivalent; + else if (static_cast(m_order) == QtPrivate::Ordering::Greater) + return std::partial_ordering::greater; + else if (static_cast(m_order) == QtPrivate::Uncomparable::Unordered) + return std::partial_ordering::unordered; + return std::partial_ordering::unordered; + } + + friend constexpr bool operator==(QPartialOrdering lhs, std::partial_ordering rhs) noexcept + { return static_cast(lhs) == rhs; } + + friend constexpr bool operator!=(QPartialOrdering lhs, std::partial_ordering rhs) noexcept + { return static_cast(lhs) != rhs; } + + friend constexpr bool operator==(std::partial_ordering lhs, QPartialOrdering rhs) noexcept + { return lhs == static_cast(rhs); } + + friend constexpr bool operator!=(std::partial_ordering lhs, QPartialOrdering rhs) noexcept + { return lhs != static_cast(rhs); } +#endif // __cpp_lib_three_way_comparison + private: + friend class QWeakOrdering; + friend class QStrongOrdering; + constexpr explicit QPartialOrdering(QtPrivate::Ordering order) noexcept : m_order(static_cast(order)) {} @@ -118,6 +165,327 @@ inline constexpr QPartialOrdering QPartialOrdering::Equivalent(QtPrivate::Orderi inline constexpr QPartialOrdering QPartialOrdering::Greater(QtPrivate::Ordering::Greater); inline constexpr QPartialOrdering QPartialOrdering::Unordered(QtPrivate::Uncomparable::Unordered); +class QWeakOrdering +{ +public: + static const QWeakOrdering Less; + static const QWeakOrdering Equivalent; + static const QWeakOrdering Greater; + + constexpr Q_IMPLICIT operator QPartialOrdering() const noexcept + { return QPartialOrdering(static_cast(m_order)); } + + friend constexpr bool operator==(QWeakOrdering lhs, + QtPrivate::CompareAgainstLiteralZero) noexcept + { return lhs.m_order == 0; } + + friend constexpr bool operator!=(QWeakOrdering lhs, + QtPrivate::CompareAgainstLiteralZero) noexcept + { return lhs.m_order != 0; } + + friend constexpr bool operator< (QWeakOrdering lhs, + QtPrivate::CompareAgainstLiteralZero) noexcept + { return lhs.m_order < 0; } + + friend constexpr bool operator<=(QWeakOrdering lhs, + QtPrivate::CompareAgainstLiteralZero) noexcept + { return lhs.m_order <= 0; } + + friend constexpr bool operator> (QWeakOrdering lhs, + QtPrivate::CompareAgainstLiteralZero) noexcept + { return lhs.m_order > 0; } + + friend constexpr bool operator>=(QWeakOrdering lhs, + QtPrivate::CompareAgainstLiteralZero) noexcept + { return lhs.m_order >= 0; } + + + friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero, + QWeakOrdering rhs) noexcept + { return 0 == rhs.m_order; } + + friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero, + QWeakOrdering rhs) noexcept + { return 0 != rhs.m_order; } + + friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero, + QWeakOrdering rhs) noexcept + { return 0 < rhs.m_order; } + + friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero, + QWeakOrdering rhs) noexcept + { return 0 <= rhs.m_order; } + + friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero, + QWeakOrdering rhs) noexcept + { return 0 > rhs.m_order; } + + friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero, + QWeakOrdering rhs) noexcept + { return 0 >= rhs.m_order; } + + + friend constexpr bool operator==(QWeakOrdering lhs, QWeakOrdering rhs) noexcept + { return lhs.m_order == rhs.m_order; } + + friend constexpr bool operator!=(QWeakOrdering lhs, QWeakOrdering rhs) noexcept + { return lhs.m_order != rhs.m_order; } + + friend constexpr bool operator==(QWeakOrdering lhs, QPartialOrdering rhs) noexcept + { return static_cast(lhs) == rhs; } + + friend constexpr bool operator!=(QWeakOrdering lhs, QPartialOrdering rhs) noexcept + { return static_cast(lhs) != rhs; } + + friend constexpr bool operator==(QPartialOrdering lhs, QWeakOrdering rhs) noexcept + { return lhs == static_cast(rhs); } + + friend constexpr bool operator!=(QPartialOrdering lhs, QWeakOrdering rhs) noexcept + { return lhs != static_cast(rhs); } + +#ifdef __cpp_lib_three_way_comparison + constexpr Q_IMPLICIT QWeakOrdering(std::weak_ordering stdorder) noexcept + { + if (stdorder == std::weak_ordering::less) + m_order = static_cast(QtPrivate::Ordering::Less); + else if (stdorder == std::weak_ordering::equivalent) + m_order = static_cast(QtPrivate::Ordering::Equivalent); + else if (stdorder == std::weak_ordering::greater) + m_order = static_cast(QtPrivate::Ordering::Greater); + } + + constexpr Q_IMPLICIT operator std::weak_ordering() const noexcept + { + if (static_cast(m_order) == QtPrivate::Ordering::Less) + return std::weak_ordering::less; + else if (static_cast(m_order) == QtPrivate::Ordering::Equivalent) + return std::weak_ordering::equivalent; + else if (static_cast(m_order) == QtPrivate::Ordering::Greater) + return std::weak_ordering::greater; + return std::weak_ordering::equivalent; + } + + friend constexpr bool operator==(QWeakOrdering lhs, std::weak_ordering rhs) noexcept + { return static_cast(lhs) == rhs; } + + friend constexpr bool operator!=(QWeakOrdering lhs, std::weak_ordering rhs) noexcept + { return static_cast(lhs) != rhs; } + + friend constexpr bool operator==(QWeakOrdering lhs, std::partial_ordering rhs) noexcept + { return static_cast(lhs) == rhs; } + + friend constexpr bool operator!=(QWeakOrdering lhs, std::partial_ordering rhs) noexcept + { return static_cast(lhs) != rhs; } + + friend constexpr bool operator==(QWeakOrdering lhs, std::strong_ordering rhs) noexcept + { return static_cast(lhs) == rhs; } + + friend constexpr bool operator!=(QWeakOrdering lhs, std::strong_ordering rhs) noexcept + { return static_cast(lhs) != rhs; } + + friend constexpr bool operator==(std::weak_ordering lhs, QWeakOrdering rhs) noexcept + { return lhs == static_cast(rhs); } + + friend constexpr bool operator!=(std::weak_ordering lhs, QWeakOrdering rhs) noexcept + { return lhs != static_cast(rhs); } + + friend constexpr bool operator==(std::partial_ordering lhs, QWeakOrdering rhs) noexcept + { return lhs == static_cast(rhs); } + + friend constexpr bool operator!=(std::partial_ordering lhs, QWeakOrdering rhs) noexcept + { return lhs != static_cast(rhs); } + + friend constexpr bool operator==(std::strong_ordering lhs, QWeakOrdering rhs) noexcept + { return lhs == static_cast(rhs); } + + friend constexpr bool operator!=(std::strong_ordering lhs, QWeakOrdering rhs) noexcept + { return lhs != static_cast(rhs); } +#endif // __cpp_lib_three_way_comparison + +private: + friend class QStrongOrdering; + + constexpr explicit QWeakOrdering(QtPrivate::Ordering order) noexcept + : m_order(static_cast(order)) + {} + + QtPrivate::CompareUnderlyingType m_order; +}; + +inline constexpr QWeakOrdering QWeakOrdering::Less(QtPrivate::Ordering::Less); +inline constexpr QWeakOrdering QWeakOrdering::Equivalent(QtPrivate::Ordering::Equivalent); +inline constexpr QWeakOrdering QWeakOrdering::Greater(QtPrivate::Ordering::Greater); + +class QStrongOrdering +{ +public: + static const QStrongOrdering Less; + static const QStrongOrdering Equivalent; + static const QStrongOrdering Equal; + static const QStrongOrdering Greater; + + constexpr Q_IMPLICIT operator QPartialOrdering() const noexcept + { return QPartialOrdering(static_cast(m_order)); } + + constexpr Q_IMPLICIT operator QWeakOrdering() const noexcept + { return QWeakOrdering(static_cast(m_order)); } + + friend constexpr bool operator==(QStrongOrdering lhs, + QtPrivate::CompareAgainstLiteralZero) noexcept + { return lhs.m_order == 0; } + + friend constexpr bool operator!=(QStrongOrdering lhs, + QtPrivate::CompareAgainstLiteralZero) noexcept + { return lhs.m_order != 0; } + + friend constexpr bool operator< (QStrongOrdering lhs, + QtPrivate::CompareAgainstLiteralZero) noexcept + { return lhs.m_order < 0; } + + friend constexpr bool operator<=(QStrongOrdering lhs, + QtPrivate::CompareAgainstLiteralZero) noexcept + { return lhs.m_order <= 0; } + + friend constexpr bool operator> (QStrongOrdering lhs, + QtPrivate::CompareAgainstLiteralZero) noexcept + { return lhs.m_order > 0; } + + friend constexpr bool operator>=(QStrongOrdering lhs, + QtPrivate::CompareAgainstLiteralZero) noexcept + { return lhs.m_order >= 0; } + + + friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero, + QStrongOrdering rhs) noexcept + { return 0 == rhs.m_order; } + + friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero, + QStrongOrdering rhs) noexcept + { return 0 != rhs.m_order; } + + friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero, + QStrongOrdering rhs) noexcept + { return 0 < rhs.m_order; } + + friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero, + QStrongOrdering rhs) noexcept + { return 0 <= rhs.m_order; } + + friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero, + QStrongOrdering rhs) noexcept + { return 0 > rhs.m_order; } + + friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero, + QStrongOrdering rhs) noexcept + { return 0 >= rhs.m_order; } + + + friend constexpr bool operator==(QStrongOrdering lhs, QStrongOrdering rhs) noexcept + { return lhs.m_order == rhs.m_order; } + + friend constexpr bool operator!=(QStrongOrdering lhs, QStrongOrdering rhs) noexcept + { return lhs.m_order != rhs.m_order; } + + friend constexpr bool operator==(QStrongOrdering lhs, QPartialOrdering rhs) noexcept + { return static_cast(lhs) == rhs; } + + friend constexpr bool operator!=(QStrongOrdering lhs, QPartialOrdering rhs) noexcept + { return static_cast(lhs) == rhs; } + + friend constexpr bool operator==(QPartialOrdering lhs, QStrongOrdering rhs) noexcept + { return lhs == static_cast(rhs); } + + friend constexpr bool operator!=(QPartialOrdering lhs, QStrongOrdering rhs) noexcept + { return lhs != static_cast(rhs); } + + friend constexpr bool operator==(QStrongOrdering lhs, QWeakOrdering rhs) noexcept + { return static_cast(lhs) == rhs; } + + friend constexpr bool operator!=(QStrongOrdering lhs, QWeakOrdering rhs) noexcept + { return static_cast(lhs) == rhs; } + + friend constexpr bool operator==(QWeakOrdering lhs, QStrongOrdering rhs) noexcept + { return lhs == static_cast(rhs); } + + friend constexpr bool operator!=(QWeakOrdering lhs, QStrongOrdering rhs) noexcept + { return lhs != static_cast(rhs); } + +#ifdef __cpp_lib_three_way_comparison + constexpr Q_IMPLICIT QStrongOrdering(std::strong_ordering stdorder) noexcept + { + if (stdorder == std::strong_ordering::less) + m_order = static_cast(QtPrivate::Ordering::Less); + else if (stdorder == std::strong_ordering::equivalent) + m_order = static_cast(QtPrivate::Ordering::Equivalent); + else if (stdorder == std::strong_ordering::equal) + m_order = static_cast(QtPrivate::Ordering::Equal); + else if (stdorder == std::strong_ordering::greater) + m_order = static_cast(QtPrivate::Ordering::Greater); + } + + constexpr Q_IMPLICIT operator std::strong_ordering() const noexcept + { + if (static_cast(m_order) == QtPrivate::Ordering::Less) + return std::strong_ordering::less; + else if (static_cast(m_order) == QtPrivate::Ordering::Equivalent) + return std::strong_ordering::equivalent; + else if (static_cast(m_order) == QtPrivate::Ordering::Equal) + return std::strong_ordering::equal; + else if (static_cast(m_order) == QtPrivate::Ordering::Greater) + return std::strong_ordering::greater; + return std::strong_ordering::equivalent; + } + + friend constexpr bool operator==(QStrongOrdering lhs, std::strong_ordering rhs) noexcept + { return static_cast(lhs) == rhs; } + + friend constexpr bool operator!=(QStrongOrdering lhs, std::strong_ordering rhs) noexcept + { return static_cast(lhs) != rhs; } + + friend constexpr bool operator==(QStrongOrdering lhs, std::partial_ordering rhs) noexcept + { return static_cast(lhs) == rhs; } + + friend constexpr bool operator!=(QStrongOrdering lhs, std::partial_ordering rhs) noexcept + { return static_cast(lhs) != rhs; } + + friend constexpr bool operator==(QStrongOrdering lhs, std::weak_ordering rhs) noexcept + { return static_cast(lhs) == rhs; } + + friend constexpr bool operator!=(QStrongOrdering lhs, std::weak_ordering rhs) noexcept + { return static_cast(lhs) != rhs; } + + friend constexpr bool operator==(std::strong_ordering lhs, QStrongOrdering rhs) noexcept + { return lhs == static_cast(rhs); } + + friend constexpr bool operator!=(std::strong_ordering lhs, QStrongOrdering rhs) noexcept + { return lhs != static_cast(rhs); } + + friend constexpr bool operator==(std::partial_ordering lhs, QStrongOrdering rhs) noexcept + { return lhs == static_cast(rhs); } + + friend constexpr bool operator!=(std::partial_ordering lhs, QStrongOrdering rhs) noexcept + { return lhs != static_cast(rhs); } + + friend constexpr bool operator==(std::weak_ordering lhs, QStrongOrdering rhs) noexcept + { return lhs == static_cast(rhs); } + + friend constexpr bool operator!=(std::weak_ordering lhs, QStrongOrdering rhs) noexcept + { return lhs != static_cast(rhs); } +#endif // __cpp_lib_three_way_comparison + + private: + constexpr explicit QStrongOrdering(QtPrivate::Ordering order) noexcept + : m_order(static_cast(order)) + {} + + QtPrivate::CompareUnderlyingType m_order; +}; + +inline constexpr QStrongOrdering QStrongOrdering::Less(QtPrivate::Ordering::Less); +inline constexpr QStrongOrdering QStrongOrdering::Equivalent(QtPrivate::Ordering::Equivalent); +inline constexpr QStrongOrdering QStrongOrdering::Equal(QtPrivate::Ordering::Equal); +inline constexpr QStrongOrdering QStrongOrdering::Greater(QtPrivate::Ordering::Greater); + QT_END_NAMESPACE #endif // QCOMPARE_H diff --git a/src/corelib/global/qcompare.qdoc b/src/corelib/global/qcompare.qdoc index 56a17d6b422..9d595e30fec 100644 --- a/src/corelib/global/qcompare.qdoc +++ b/src/corelib/global/qcompare.qdoc @@ -1,10 +1,310 @@ // Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo +// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only +/*! + \class QStrongOrdering + \inmodule QtCore + \brief QStrongOrdering represents a comparison where equivalent values are + indistinguishable. + \sa QWeakOrdering, QPartialOrdering + \since 6.6 + + A value of type QStrongOrdering is typically returned from a three-way + comparison function. Such a function compares two objects and establishes + that the two objects are in a strict ordering relationship; that is, the + function establishes a well-defined total order. + + The possible values of type QStrongOrdering are fully represented by the + following four symbolic constants: + + \list + \li \c Less represents that the left operand is less than the right; + \li \c Equal represents that the left operand is equivalent to the right; + \li \c Equivalent is an alias for \c Equal; + \li \c Greater represents that the left operand is greater than the right. + \endlist + + QStrongOrdering is idiomatically used by comparing an instance against a + literal zero, for instance like this: + + \code + + // given a, b, c, d as objects of some type that allows for a 3-way compare, + // and a compare function declared as follows: + + QStrongOrdering compare(T lhs, T rhs); // defined out-of-line + ~~~ + + QStrongOrdering result = compare(a, b); + if (result < 0) { + // a is less than b + } + + if (compare(c, d) >= 0) { + // c is greater than or equal to d + } + + \endcode +*/ + +/*! + \fn QStrongOrdering::operator QPartialOrdering() const + + Converts this QStrongOrdering value to a QPartialOrdering object using the + following rules: + + \list + \li \l Less converts to \l {QPartialOrdering::Less}. + \li \l Equivalent converts to \l {QPartialOrdering::Equivalent}. + \li \l Equal converts to \l {QPartialOrdering::Equivalent}. + \li \l Greater converts to \l {QPartialOrdering::Greater}. + \endlist +*/ + +/*! + \fn QStrongOrdering::operator QWeakOrdering() const + + Converts this QStrongOrdering value to a QWeakOrdering object using the + following rules: + + \list + \li \l Less converts to \l {QWeakOrdering::Less}. + \li \l Equivalent converts to \l {QWeakOrdering::Equivalent}. + \li \l Equal converts to \l {QWeakOrdering::Equivalent}. + \li \l Greater converts to \l {QWeakOrdering::Greater}. + \endlist +*/ + +/*! + \fn QStrongOrdering::QStrongOrdering(std::strong_ordering stdorder) + + Constructs a QStrongOrdering object from \a stdorder using the following rules: + + \list + \li std::strong_ordering::less converts to \l Less. + \li std::strong_ordering::equivalent converts to \l Equivalent. + \li std::strong_ordering::equal converts to \l Equal. + \li std::strong_ordering::greater converts to \l Greater. + \endlist +*/ + +/*! + \fn QStrongOrdering::operator std::strong_ordering() const + + Converts this QStrongOrdering value to a std::strong_ordering object using + the following rules: + + \list + \li \l Less converts to std::strong_ordering::less. + \li \l Equivalent converts to std::strong_ordering::equivalent. + \li \l Equal converts to std::strong_ordering::equal. + \li \l Greater converts to std::strong_ordering::greater. + \endlist +*/ + +/*! + \fn bool QStrongOrdering::operator==(QStrongOrdering lhs, QStrongOrdering rhs) + + Returns true if \a lhs and \a rhs represent the same result; + otherwise, returns false. +*/ + +/*! + \fn bool QStrongOrdering::operator!=(QStrongOrdering lhs, QStrongOrdering rhs) + + Returns true if \a lhs and \a rhs represent different results; + otherwise, returns true. +*/ + +/*! + \internal + \relates QStrongOrdering + \fn bool operator==(QStrongOrdering lhs, QtPrivate::CompareAgainstLiteralZero) + \fn bool operator!=(QStrongOrdering lhs, QtPrivate::CompareAgainstLiteralZero) + \fn bool operator< (QStrongOrdering lhs, QtPrivate::CompareAgainstLiteralZero) + \fn bool operator<=(QStrongOrdering lhs, QtPrivate::CompareAgainstLiteralZero) + \fn bool operator> (QStrongOrdering lhs, QtPrivate::CompareAgainstLiteralZero) + \fn bool operator>=(QStrongOrdering lhs, QtPrivate::CompareAgainstLiteralZero) + + \fn bool operator==(QtPrivate::CompareAgainstLiteralZero, QStrongOrdering rhs) + \fn bool operator!=(QtPrivate::CompareAgainstLiteralZero, QStrongOrdering rhs) + \fn bool operator< (QtPrivate::CompareAgainstLiteralZero, QStrongOrdering rhs) + \fn bool operator<=(QtPrivate::CompareAgainstLiteralZero, QStrongOrdering rhs) + \fn bool operator> (QtPrivate::CompareAgainstLiteralZero, QStrongOrdering rhs) + \fn bool operator>=(QtPrivate::CompareAgainstLiteralZero, QStrongOrdering rhs) +*/ + +/*! + \variable QStrongOrdering::Less + + Represents the result of a comparison where the left operand is less + than the right operand. +*/ + +/*! + \variable QStrongOrdering::Equivalent + + Represents the result of a comparison where the left operand is equal + to the right operand. Same as \l {QStrongOrdering::Equal}. +*/ + +/*! + \variable QStrongOrdering::Equal + + Represents the result of a comparison where the left operand is equal + to the right operand. Same as \l {QStrongOrdering::Equivalent}. +*/ + +/*! + \variable QStrongOrdering::Greater + + Represents the result of a comparison where the left operand is greater + than the right operand. +*/ + +/*! + \class QWeakOrdering + \inmodule QtCore + \brief QWeakOrdering represents a comparison where equivalent values are + still distinguishable. + \sa QStrongOrdering, QPartialOrdering + \since 6.6 + + A value of type QWeakOrdering is typically returned from a three-way + comparison function. Such a function compares two objects and establishes + the order of the elements relative to each other. + + The possible values of type QWeakOrdering are fully represented by the + following three symbolic constants: + + \list + \li \c Less represents that the left operand is less than the right; + \li \c Equivalent represents that the left operand is equivalent to the + right; + \li \c Greater represents that the left operand is greater than the right, + \endlist + + QWeakOrdering is idiomatically used by comparing an instance against a + literal zero, for instance like this: + + \code + + // given a, b, c, d as objects of some type that allows for a 3-way compare, + // and a compare function declared as follows: + + QWeakOrdering compare(T lhs, T rhs); // defined out-of-line + ~~~ + + QWeakOrdering result = compare(a, b); + if (result < 0) { + // a is less than b + } + + if (compare(c, d) >= 0) { + // c is greater than or equivalent to d + } + + \endcode +*/ + +/*! + \fn QWeakOrdering::operator QPartialOrdering() const + + Converts this QWeakOrdering value to a QPartialOrdering object using the + following rules: + + \list + \li \l Less converts to \l {QPartialOrdering::Less}. + \li \l Equivalent converts to \l {QPartialOrdering::Equivalent}. + \li \l Greater converts to \l {QPartialOrdering::Greater}. + \endlist +*/ + +/*! + \fn QWeakOrdering::QWeakOrdering(std::weak_ordering stdorder) + + Constructs a QWeakOrdering object from \a stdorder using the following rules: + + \list + \li std::weak_ordering::less converts to \l Less. + \li std::weak_ordering::equivalent converts to \l Equivalent. + \li std::weak_ordering::greater converts to \l Greater. + \endlist +*/ + +/*! + \fn QWeakOrdering::operator std::weak_ordering() const + + Converts this QWeakOrdering value to a std::weak_ordering object using + the following rules: + + \list + \li \l Less converts to std::weak_ordering::less. + \li \l Equivalent converts to std::weak_ordering::equivalent. + \li \l Greater converts to std::weak_ordering::greater. + \endlist +*/ + +/*! + \fn bool QWeakOrdering::operator==(QWeakOrdering lhs, QWeakOrdering rhs) + + Return true if \a lhs and \a rhs represent the same result; + otherwise, returns false. +*/ + +/*! + \fn bool QWeakOrdering::operator!=(QWeakOrdering lhs, QWeakOrdering rhs) + + Return true if \a lhs and \a rhs represent different results; + otherwise, returns true. +*/ + +/*! + \internal + \relates QWeakOrdering + \fn bool operator==(QWeakOrdering lhs, QtPrivate::CompareAgainstLiteralZero) + \fn bool operator!=(QWeakOrdering lhs, QtPrivate::CompareAgainstLiteralZero) + \fn bool operator< (QWeakOrdering lhs, QtPrivate::CompareAgainstLiteralZero) + \fn bool operator<=(QWeakOrdering lhs, QtPrivate::CompareAgainstLiteralZero) + \fn bool operator> (QWeakOrdering lhs, QtPrivate::CompareAgainstLiteralZero) + \fn bool operator>=(QWeakOrdering lhs, QtPrivate::CompareAgainstLiteralZero) + + \fn bool operator==(QtPrivate::CompareAgainstLiteralZero, QWeakOrdering rhs) + \fn bool operator!=(QtPrivate::CompareAgainstLiteralZero, QWeakOrdering rhs) + \fn bool operator< (QtPrivate::CompareAgainstLiteralZero, QWeakOrdering rhs) + \fn bool operator<=(QtPrivate::CompareAgainstLiteralZero, QWeakOrdering rhs) + \fn bool operator> (QtPrivate::CompareAgainstLiteralZero, QWeakOrdering rhs) + \fn bool operator>=(QtPrivate::CompareAgainstLiteralZero, QWeakOrdering rhs) +*/ + +/*! + \variable QWeakOrdering::Less + + Represents the result of a comparison where the left operand is less than + the right operand. +*/ + +/*! + \variable QWeakOrdering::Equivalent + + Represents the result of a comparison where the left operand is equivalent + to the right operand. +*/ + +/*! + \variable QWeakOrdering::Greater + + Represents the result of a comparison where the left operand is greater + than the right operand. +*/ + /*! \class QPartialOrdering \inmodule QtCore - \brief QPartialOrdering represents the result of a comparison that allows for unordered results. + \brief QPartialOrdering represents the result of a comparison that allows + for unordered results. + \sa QStrongOrdering, QWeakOrdering \since 6.0 A value of type QPartialOrdering is typically returned from a @@ -15,17 +315,14 @@ represents one of those possibilities. The possible values of type QPartialOrdering are, in fact, fully - represented by the following four static values: + represented by the following four symbolic constants: \list - \li \c QPartialOrdering::Less represents that the first object is - less than the second; - \li \c QPartialOrdering::Equivalent represents that the first - object is equivalent to the second; - \li \c QPartialOrdering::Greater represents that the first object - is greater than the second; - \li \c QPartialOrdering::Unordered represents that the first object - is \e{not ordered} with respect to the second. + \li \c Less represents that the left operand is less than the right; + \li \c Equivalent represents that left operand is equivalent to the right; + \li \c Greater represents that the left operand is greater than the right; + \li \c Unordered represents that the left operand is \e {not ordered} with + respect to the right operand. \endlist QPartialOrdering is idiomatically used by comparing an instance @@ -54,6 +351,34 @@ always return false when compared against literal 0. */ +/*! + \fn QPartialOrdering::QPartialOrdering(std::partial_ordering stdorder) + + Constructs a QPartialOrdering object from \a stdorder using the following + rules: + + \list + \li std::partial_ordering::less converts to \l Less. + \li std::partial_ordering::equivalent converts to \l Equivalent. + \li std::partial_ordering::greater converts to \l Greater. + \li std::partial_ordering::unordered converts to \l Unordered + \endlist +*/ + +/*! + \fn QPartialOrdering::operator std::partial_ordering() const + + Converts this QPartialOrdering value to a std::partial_ordering object using + the following rules: + + \list + \li \l Less converts to std::partial_ordering::less. + \li \l Equivalent converts to std::partial_ordering::equivalent. + \li \l Greater converts to std::partial_ordering::greater. + \li \l Unordered converts to std::partial_ordering::unordered. + \endlist +*/ + /*! \fn bool QPartialOrdering::operator==(QPartialOrdering lhs, QPartialOrdering rhs) @@ -69,6 +394,8 @@ */ /*! + \internal + \relates QPartialOrdering \fn bool operator==(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) \fn bool operator!=(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) \fn bool operator< (QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) @@ -82,35 +409,32 @@ \fn bool operator<=(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) \fn bool operator> (QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) \fn bool operator>=(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) - \relates QPartialOrdering - \internal */ /*! \variable QPartialOrdering::Less - Represents the result of a comparison where the value on the left - hand side is less than the value on the right hand side. + Represents the result of a comparison where the left operand is less than + the right operand. */ /*! \variable QPartialOrdering::Equivalent - Represents the result of a comparison where the value on the left - hand side is equivalent to the value on the right hand side. + Represents the result of a comparison where the left operand is equivalent + to the right operand. */ /*! \variable QPartialOrdering::Greater - Represents the result of a comparison where the value on the left - hand side is greater than the value on the right hand side. + Represents the result of a comparison where the left operand is greater + than the right operand. */ /*! \variable QPartialOrdering::Unordered - Represents the result of a comparison where the value on the left - hand side is not ordered with respect to the value on the right hand - side. + Represents the result of a comparison where the left operand is not ordered + with respect to the right operand. */ diff --git a/tests/auto/corelib/global/qcompare/tst_qcompare.cpp b/tests/auto/corelib/global/qcompare/tst_qcompare.cpp index cc21bd9d149..a8dcc3a2019 100644 --- a/tests/auto/corelib/global/qcompare/tst_qcompare.cpp +++ b/tests/auto/corelib/global/qcompare/tst_qcompare.cpp @@ -4,11 +4,18 @@ #include #include +#ifdef __cpp_lib_three_way_comparison +#include +#endif // __cpp_lib_three_way_comparison + class tst_QCompare: public QObject { Q_OBJECT private slots: void partialOrdering(); + void weakOrdering(); + void strongOrdering(); + void conversions(); }; void tst_QCompare::partialOrdering() @@ -94,5 +101,270 @@ void tst_QCompare::partialOrdering() static_assert(!(0 >= QPartialOrdering::Greater)); } +void tst_QCompare::weakOrdering() +{ + static_assert(QWeakOrdering::Less == QWeakOrdering::Less); + static_assert(QWeakOrdering::Less != QWeakOrdering::Equivalent); + static_assert(QWeakOrdering::Less != QWeakOrdering::Greater); + + static_assert(QWeakOrdering::Equivalent != QWeakOrdering::Less); + static_assert(QWeakOrdering::Equivalent == QWeakOrdering::Equivalent); + static_assert(QWeakOrdering::Equivalent != QWeakOrdering::Greater); + + static_assert(QWeakOrdering::Greater != QWeakOrdering::Less); + static_assert(QWeakOrdering::Greater != QWeakOrdering::Equivalent); + static_assert(QWeakOrdering::Greater == QWeakOrdering::Greater); + + static_assert(!(QWeakOrdering::Less == 0)); + static_assert( (QWeakOrdering::Less != 0)); + static_assert( (QWeakOrdering::Less < 0)); + static_assert( (QWeakOrdering::Less <= 0)); + static_assert(!(QWeakOrdering::Less > 0)); + static_assert(!(QWeakOrdering::Less >= 0)); + + static_assert(!(0 == QWeakOrdering::Less)); + static_assert( (0 != QWeakOrdering::Less)); + static_assert(!(0 < QWeakOrdering::Less)); + static_assert(!(0 <= QWeakOrdering::Less)); + static_assert( (0 > QWeakOrdering::Less)); + static_assert( (0 >= QWeakOrdering::Less)); + + static_assert( (QWeakOrdering::Equivalent == 0)); + static_assert(!(QWeakOrdering::Equivalent != 0)); + static_assert(!(QWeakOrdering::Equivalent < 0)); + static_assert( (QWeakOrdering::Equivalent <= 0)); + static_assert(!(QWeakOrdering::Equivalent > 0)); + static_assert( (QWeakOrdering::Equivalent >= 0)); + + static_assert( (0 == QWeakOrdering::Equivalent)); + static_assert(!(0 != QWeakOrdering::Equivalent)); + static_assert(!(0 < QWeakOrdering::Equivalent)); + static_assert( (0 <= QWeakOrdering::Equivalent)); + static_assert(!(0 > QWeakOrdering::Equivalent)); + static_assert( (0 >= QWeakOrdering::Equivalent)); + + static_assert(!(QWeakOrdering::Greater == 0)); + static_assert( (QWeakOrdering::Greater != 0)); + static_assert(!(QWeakOrdering::Greater < 0)); + static_assert(!(QWeakOrdering::Greater <= 0)); + static_assert( (QWeakOrdering::Greater > 0)); + static_assert( (QWeakOrdering::Greater >= 0)); + + static_assert(!(0 == QWeakOrdering::Greater)); + static_assert( (0 != QWeakOrdering::Greater)); + static_assert( (0 < QWeakOrdering::Greater)); + static_assert( (0 <= QWeakOrdering::Greater)); + static_assert(!(0 > QWeakOrdering::Greater)); + static_assert(!(0 >= QWeakOrdering::Greater)); +} + +void tst_QCompare::strongOrdering() +{ + static_assert(QStrongOrdering::Less == QStrongOrdering::Less); + static_assert(QStrongOrdering::Less != QStrongOrdering::Equal); + static_assert(QStrongOrdering::Less != QStrongOrdering::Equivalent); + static_assert(QStrongOrdering::Less != QStrongOrdering::Greater); + + static_assert(QStrongOrdering::Equal != QStrongOrdering::Less); + static_assert(QStrongOrdering::Equal == QStrongOrdering::Equal); + static_assert(QStrongOrdering::Equal == QStrongOrdering::Equivalent); + static_assert(QStrongOrdering::Equal != QStrongOrdering::Greater); + + static_assert(QStrongOrdering::Equivalent != QStrongOrdering::Less); + static_assert(QStrongOrdering::Equivalent == QStrongOrdering::Equal); + static_assert(QStrongOrdering::Equivalent == QStrongOrdering::Equivalent); + static_assert(QStrongOrdering::Equivalent != QStrongOrdering::Greater); + + static_assert(QStrongOrdering::Greater != QStrongOrdering::Less); + static_assert(QStrongOrdering::Greater != QStrongOrdering::Equal); + static_assert(QStrongOrdering::Greater != QStrongOrdering::Equivalent); + static_assert(QStrongOrdering::Greater == QStrongOrdering::Greater); + + static_assert(!(QStrongOrdering::Less == 0)); + static_assert( (QStrongOrdering::Less != 0)); + static_assert( (QStrongOrdering::Less < 0)); + static_assert( (QStrongOrdering::Less <= 0)); + static_assert(!(QStrongOrdering::Less > 0)); + static_assert(!(QStrongOrdering::Less >= 0)); + + static_assert(!(0 == QStrongOrdering::Less)); + static_assert( (0 != QStrongOrdering::Less)); + static_assert(!(0 < QStrongOrdering::Less)); + static_assert(!(0 <= QStrongOrdering::Less)); + static_assert( (0 > QStrongOrdering::Less)); + static_assert( (0 >= QStrongOrdering::Less)); + + static_assert( (QStrongOrdering::Equal == 0)); + static_assert(!(QStrongOrdering::Equal != 0)); + static_assert(!(QStrongOrdering::Equal < 0)); + static_assert( (QStrongOrdering::Equal <= 0)); + static_assert(!(QStrongOrdering::Equal > 0)); + static_assert( (QStrongOrdering::Equal >= 0)); + + static_assert( (0 == QStrongOrdering::Equal)); + static_assert(!(0 != QStrongOrdering::Equal)); + static_assert(!(0 < QStrongOrdering::Equal)); + static_assert( (0 <= QStrongOrdering::Equal)); + static_assert(!(0 > QStrongOrdering::Equal)); + static_assert( (0 >= QStrongOrdering::Equal)); + + static_assert( (QStrongOrdering::Equivalent == 0)); + static_assert(!(QStrongOrdering::Equivalent != 0)); + static_assert(!(QStrongOrdering::Equivalent < 0)); + static_assert( (QStrongOrdering::Equivalent <= 0)); + static_assert(!(QStrongOrdering::Equivalent > 0)); + static_assert( (QStrongOrdering::Equivalent >= 0)); + + static_assert( (0 == QStrongOrdering::Equivalent)); + static_assert(!(0 != QStrongOrdering::Equivalent)); + static_assert(!(0 < QStrongOrdering::Equivalent)); + static_assert( (0 <= QStrongOrdering::Equivalent)); + static_assert(!(0 > QStrongOrdering::Equivalent)); + static_assert( (0 >= QStrongOrdering::Equivalent)); + + static_assert(!(QStrongOrdering::Greater == 0)); + static_assert( (QStrongOrdering::Greater != 0)); + static_assert(!(QStrongOrdering::Greater < 0)); + static_assert(!(QStrongOrdering::Greater <= 0)); + static_assert( (QStrongOrdering::Greater > 0)); + static_assert( (QStrongOrdering::Greater >= 0)); + + static_assert(!(0 == QStrongOrdering::Greater)); + static_assert( (0 != QStrongOrdering::Greater)); + static_assert( (0 < QStrongOrdering::Greater)); + static_assert( (0 <= QStrongOrdering::Greater)); + static_assert(!(0 > QStrongOrdering::Greater)); + static_assert(!(0 >= QStrongOrdering::Greater)); +} + +void tst_QCompare::conversions() +{ + // QWeakOrdering -> QPartialOrdering + { + constexpr QPartialOrdering less = QWeakOrdering::Less; + static_assert(less == QPartialOrdering::Less); + constexpr QPartialOrdering equivalent = QWeakOrdering::Equivalent; + static_assert(equivalent == QPartialOrdering::Equivalent); + constexpr QPartialOrdering greater = QWeakOrdering::Greater; + static_assert(greater == QPartialOrdering::Greater); + } + // QStrongOrdering -> QPartialOrdering + { + constexpr QPartialOrdering less = QStrongOrdering::Less; + static_assert(less == QPartialOrdering::Less); + constexpr QPartialOrdering equal = QStrongOrdering::Equal; + static_assert(equal == QPartialOrdering::Equivalent); + constexpr QPartialOrdering equivalent = QStrongOrdering::Equivalent; + static_assert(equivalent == QPartialOrdering::Equivalent); + constexpr QPartialOrdering greater = QStrongOrdering::Greater; + static_assert(greater == QPartialOrdering::Greater); + } + // QStrongOrdering -> QWeakOrdering + { + constexpr QWeakOrdering less = QStrongOrdering::Less; + static_assert(less == QWeakOrdering::Less); + constexpr QWeakOrdering equal = QStrongOrdering::Equal; + static_assert(equal == QWeakOrdering::Equivalent); + constexpr QWeakOrdering equivalent = QStrongOrdering::Equivalent; + static_assert(equivalent == QWeakOrdering::Equivalent); + constexpr QWeakOrdering greater = QStrongOrdering::Greater; + static_assert(greater == QWeakOrdering::Greater); + } + // Mixed types + { + static_assert(QPartialOrdering::Less == QStrongOrdering::Less); + static_assert(QPartialOrdering::Equivalent != QStrongOrdering::Less); + static_assert(QPartialOrdering::Equivalent == QStrongOrdering::Equal); + static_assert(QPartialOrdering::Greater == QStrongOrdering::Greater); + + static_assert(QPartialOrdering::Less == QWeakOrdering::Less); + static_assert(QPartialOrdering::Equivalent == QWeakOrdering::Equivalent); + static_assert(QPartialOrdering::Greater == QWeakOrdering::Greater); + + static_assert(QWeakOrdering::Less == QStrongOrdering::Less); + static_assert(QWeakOrdering::Equivalent != QStrongOrdering::Greater); + static_assert(QWeakOrdering::Equivalent == QStrongOrdering::Equal); + static_assert(QWeakOrdering::Greater == QStrongOrdering::Greater); + + static_assert(QWeakOrdering::Less == QPartialOrdering::Less); + static_assert(QWeakOrdering::Equivalent == QPartialOrdering::Equivalent); + static_assert(QWeakOrdering::Greater == QPartialOrdering::Greater); + + static_assert(QStrongOrdering::Less == QPartialOrdering::Less); + static_assert(QStrongOrdering::Equivalent == QPartialOrdering::Equivalent); + static_assert(QStrongOrdering::Equal == QPartialOrdering::Equivalent); + static_assert(QStrongOrdering::Greater == QPartialOrdering::Greater); + + static_assert(QStrongOrdering::Less == QWeakOrdering::Less); + static_assert(QStrongOrdering::Equivalent == QWeakOrdering::Equivalent); + static_assert(QStrongOrdering::Equal == QWeakOrdering::Equivalent); + static_assert(QStrongOrdering::Greater == QWeakOrdering::Greater); + } +#ifdef __cpp_lib_three_way_comparison + // QPartialOrdering <-> std::partial_ordering + { + static_assert(QPartialOrdering::Less == std::partial_ordering::less); + static_assert(QPartialOrdering::Less != std::partial_ordering::greater); + static_assert(std::partial_ordering::unordered != QPartialOrdering::Equivalent); + static_assert(std::partial_ordering::unordered == QPartialOrdering::Unordered); + + static_assert((QPartialOrdering(std::partial_ordering::less) == + std::partial_ordering::less)); + static_assert((QPartialOrdering(std::partial_ordering::equivalent) == + std::partial_ordering::equivalent)); + static_assert((QPartialOrdering(std::partial_ordering::greater) == + std::partial_ordering::greater)); + static_assert((QPartialOrdering(std::partial_ordering::unordered) == + std::partial_ordering::unordered)); + } + // QWeakOrdering <-> std::weak_ordering + { + static_assert(QWeakOrdering::Less == std::weak_ordering::less); + static_assert(QWeakOrdering::Less != std::weak_ordering::equivalent); + static_assert(std::weak_ordering::greater != QWeakOrdering::Less); + static_assert(std::weak_ordering::equivalent == QWeakOrdering::Equivalent); + + static_assert((QWeakOrdering(std::weak_ordering::less) == + std::weak_ordering::less)); + static_assert((QWeakOrdering(std::weak_ordering::equivalent) == + std::weak_ordering::equivalent)); + static_assert((QWeakOrdering(std::weak_ordering::greater) == + std::weak_ordering::greater)); + } + // QStrongOrdering <-> std::strong_ordering + { + static_assert(QStrongOrdering::Less == std::strong_ordering::less); + static_assert(QStrongOrdering::Less != std::strong_ordering::equivalent); + static_assert(std::strong_ordering::greater != QStrongOrdering::Less); + static_assert(std::strong_ordering::equivalent == QStrongOrdering::Equivalent); + + static_assert((QStrongOrdering(std::strong_ordering::less) == + std::strong_ordering::less)); + static_assert((QStrongOrdering(std::strong_ordering::equivalent) == + std::strong_ordering::equivalent)); + static_assert((QStrongOrdering(std::strong_ordering::greater) == + std::strong_ordering::greater)); + } + // Mixed Q*Ordering <> std::*ordering types + { + static_assert(QStrongOrdering::Less == std::partial_ordering::less); + static_assert(QStrongOrdering::Less != std::partial_ordering::greater); + static_assert(QStrongOrdering::Equal == std::weak_ordering::equivalent); + static_assert(QStrongOrdering::Equivalent != std::weak_ordering::less); + + static_assert(QWeakOrdering::Less != std::partial_ordering::greater); + static_assert(QWeakOrdering::Less == std::partial_ordering::less); + static_assert(QWeakOrdering::Equivalent == std::strong_ordering::equivalent); + static_assert(QWeakOrdering::Equivalent != std::strong_ordering::less); + + static_assert(QPartialOrdering::Less != std::weak_ordering::greater); + static_assert(QPartialOrdering::Less == std::weak_ordering::less); + static_assert(QPartialOrdering::Equivalent == std::strong_ordering::equivalent); + static_assert(QPartialOrdering::Equivalent != std::strong_ordering::less); + } +#endif + +} + QTEST_MAIN(tst_QCompare) #include "tst_qcompare.moc"