summaryrefslogtreecommitdiffstats
path: root/src/corelib/global/qcompare.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/global/qcompare.h')
-rw-r--r--src/corelib/global/qcompare.h903
1 files changed, 830 insertions, 73 deletions
diff --git a/src/corelib/global/qcompare.h b/src/corelib/global/qcompare.h
index 8bc3029c89..9dd244c8f9 100644
--- a/src/corelib/global/qcompare.h
+++ b/src/corelib/global/qcompare.h
@@ -1,41 +1,6 @@
-/****************************************************************************
-**
-** Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Giuseppe D'Angelo <giuseppe.dangelo@kdab.com>
+// 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
#define QCOMPARE_H
@@ -47,6 +12,13 @@
#include <QtCore/qglobal.h>
#include <QtCore/qcompare_impl.h>
+#ifdef __cpp_lib_bit_cast
+#include <bit>
+#endif
+#ifdef __cpp_lib_three_way_comparison
+#include <compare>
+#endif
+
QT_BEGIN_NAMESPACE
namespace QtPrivate {
@@ -63,11 +35,645 @@ enum class Ordering : CompareUnderlyingType
enum class Uncomparable : CompareUnderlyingType
{
- Unordered = -127
+ Unordered =
+ #if defined(_LIBCPP_VERSION) // libc++
+ -127
+ #elif defined(__GLIBCXX__) // libstdc++
+ 2
+ #else // assume MSSTL
+ -128
+ #endif
};
} // namespace QtPrivate
+namespace QtOrderingPrivate {
+
+template <typename O>
+constexpr O reversed(O o) noexcept
+{
+ // https://eel.is/c++draft/cmp.partialord#5
+ return is_lt(o) ? O::greater :
+ is_gt(o) ? O::less :
+ /*else*/ o ;
+}
+
+} // namespace QtOrderingPrivate
+
+namespace Qt {
+
+class partial_ordering
+{
+public:
+ static const partial_ordering less;
+ static const partial_ordering equivalent;
+ static const partial_ordering greater;
+ static const partial_ordering unordered;
+
+ friend constexpr bool operator==(partial_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order == 0; }
+
+ friend constexpr bool operator!=(partial_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order != 0; }
+
+ friend constexpr bool operator< (partial_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order < 0; }
+
+ friend constexpr bool operator<=(partial_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order <= 0; }
+
+ friend constexpr bool operator> (partial_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order > 0; }
+
+ friend constexpr bool operator>=(partial_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order >= 0; }
+
+
+ friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero,
+ partial_ordering rhs) noexcept
+ { return rhs.isOrdered() && 0 == rhs.m_order; }
+
+ friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero,
+ partial_ordering rhs) noexcept
+ { return rhs.isOrdered() && 0 != rhs.m_order; }
+
+ friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero,
+ partial_ordering rhs) noexcept
+ { return rhs.isOrdered() && 0 < rhs.m_order; }
+
+ friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero,
+ partial_ordering rhs) noexcept
+ { return rhs.isOrdered() && 0 <= rhs.m_order; }
+
+ friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero,
+ partial_ordering rhs) noexcept
+ { return rhs.isOrdered() && 0 > rhs.m_order; }
+
+ friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero,
+ partial_ordering rhs) noexcept
+ { return rhs.isOrdered() && 0 >= rhs.m_order; }
+
+
+#ifdef __cpp_lib_three_way_comparison
+ friend constexpr std::partial_ordering
+ operator<=>(partial_ordering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs; } // https://eel.is/c++draft/cmp.partialord#4
+
+ friend constexpr std::partial_ordering
+ operator<=>(QtPrivate::CompareAgainstLiteralZero, partial_ordering rhs) noexcept
+ { return QtOrderingPrivate::reversed(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+
+ friend constexpr bool operator==(partial_ordering lhs, partial_ordering rhs) noexcept
+ { return lhs.m_order == rhs.m_order; }
+
+ friend constexpr bool operator!=(partial_ordering lhs, partial_ordering rhs) noexcept
+ { return lhs.m_order != rhs.m_order; }
+
+#ifdef __cpp_lib_three_way_comparison
+ constexpr Q_IMPLICIT partial_ordering(std::partial_ordering stdorder) noexcept
+ {
+ if (stdorder == std::partial_ordering::less)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
+ else if (stdorder == std::partial_ordering::equivalent)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equivalent);
+ else if (stdorder == std::partial_ordering::greater)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
+ else if (stdorder == std::partial_ordering::unordered)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Uncomparable::Unordered);
+ }
+
+ constexpr Q_IMPLICIT operator std::partial_ordering() const noexcept
+ {
+ static_assert(sizeof(*this) == sizeof(std::partial_ordering));
+#ifdef __cpp_lib_bit_cast
+ return std::bit_cast<std::partial_ordering>(*this);
+#else
+ using O = QtPrivate::Ordering;
+ using U = QtPrivate::Uncomparable;
+ using R = std::partial_ordering;
+ switch (m_order) {
+ case qToUnderlying(O::Less): return R::less;
+ case qToUnderlying(O::Greater): return R::greater;
+ case qToUnderlying(O::Equivalent): return R::equivalent;
+ case qToUnderlying(U::Unordered): return R::unordered;
+ }
+ Q_UNREACHABLE_RETURN(R::unordered);
+#endif // __cpp_lib_bit_cast
+ }
+
+ friend constexpr bool operator==(partial_ordering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::partial_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(partial_ordering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::partial_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(std::partial_ordering lhs, partial_ordering rhs) noexcept
+ { return lhs == static_cast<std::partial_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::partial_ordering lhs, partial_ordering rhs) noexcept
+ { return lhs != static_cast<std::partial_ordering>(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+private:
+ friend class weak_ordering;
+ friend class strong_ordering;
+
+ constexpr explicit partial_ordering(QtPrivate::Ordering order) noexcept
+ : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
+ {}
+ constexpr explicit partial_ordering(QtPrivate::Uncomparable order) noexcept
+ : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
+ {}
+
+ QT_WARNING_PUSH
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
+ QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
+ friend constexpr bool is_eq (partial_ordering o) noexcept { return o == 0; }
+ friend constexpr bool is_neq (partial_ordering o) noexcept { return o != 0; }
+ friend constexpr bool is_lt (partial_ordering o) noexcept { return o < 0; }
+ friend constexpr bool is_lteq(partial_ordering o) noexcept { return o <= 0; }
+ friend constexpr bool is_gt (partial_ordering o) noexcept { return o > 0; }
+ friend constexpr bool is_gteq(partial_ordering o) noexcept { return o >= 0; }
+ QT_WARNING_POP
+
+ // instead of the exposition only is_ordered member in [cmp.partialord],
+ // use a private function
+ constexpr bool isOrdered() const noexcept
+ { return m_order != static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Uncomparable::Unordered); }
+
+ QtPrivate::CompareUnderlyingType m_order;
+};
+
+inline constexpr partial_ordering partial_ordering::less(QtPrivate::Ordering::Less);
+inline constexpr partial_ordering partial_ordering::equivalent(QtPrivate::Ordering::Equivalent);
+inline constexpr partial_ordering partial_ordering::greater(QtPrivate::Ordering::Greater);
+inline constexpr partial_ordering partial_ordering::unordered(QtPrivate::Uncomparable::Unordered);
+
+class weak_ordering
+{
+public:
+ static const weak_ordering less;
+ static const weak_ordering equivalent;
+ static const weak_ordering greater;
+
+ constexpr Q_IMPLICIT operator partial_ordering() const noexcept
+ { return partial_ordering(static_cast<QtPrivate::Ordering>(m_order)); }
+
+ friend constexpr bool operator==(weak_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order == 0; }
+
+ friend constexpr bool operator!=(weak_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order != 0; }
+
+ friend constexpr bool operator< (weak_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order < 0; }
+
+ friend constexpr bool operator<=(weak_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order <= 0; }
+
+ friend constexpr bool operator> (weak_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order > 0; }
+
+ friend constexpr bool operator>=(weak_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order >= 0; }
+
+
+ friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero,
+ weak_ordering rhs) noexcept
+ { return 0 == rhs.m_order; }
+
+ friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero,
+ weak_ordering rhs) noexcept
+ { return 0 != rhs.m_order; }
+
+ friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero,
+ weak_ordering rhs) noexcept
+ { return 0 < rhs.m_order; }
+
+ friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero,
+ weak_ordering rhs) noexcept
+ { return 0 <= rhs.m_order; }
+
+ friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero,
+ weak_ordering rhs) noexcept
+ { return 0 > rhs.m_order; }
+
+ friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero,
+ weak_ordering rhs) noexcept
+ { return 0 >= rhs.m_order; }
+
+
+#ifdef __cpp_lib_three_way_comparison
+ friend constexpr std::weak_ordering
+ operator<=>(weak_ordering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs; } // https://eel.is/c++draft/cmp.weakord#5
+
+ friend constexpr std::weak_ordering
+ operator<=>(QtPrivate::CompareAgainstLiteralZero, weak_ordering rhs) noexcept
+ { return QtOrderingPrivate::reversed(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+
+ friend constexpr bool operator==(weak_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs.m_order == rhs.m_order; }
+
+ friend constexpr bool operator!=(weak_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs.m_order != rhs.m_order; }
+
+ friend constexpr bool operator==(weak_ordering lhs, partial_ordering rhs) noexcept
+ { return static_cast<partial_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(weak_ordering lhs, partial_ordering rhs) noexcept
+ { return static_cast<partial_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(partial_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs == static_cast<partial_ordering>(rhs); }
+
+ friend constexpr bool operator!=(partial_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs != static_cast<partial_ordering>(rhs); }
+
+#ifdef __cpp_lib_three_way_comparison
+ constexpr Q_IMPLICIT weak_ordering(std::weak_ordering stdorder) noexcept
+ {
+ if (stdorder == std::weak_ordering::less)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
+ else if (stdorder == std::weak_ordering::equivalent)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equivalent);
+ else if (stdorder == std::weak_ordering::greater)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
+ }
+
+ constexpr Q_IMPLICIT operator std::weak_ordering() const noexcept
+ {
+ static_assert(sizeof(*this) == sizeof(std::weak_ordering));
+#ifdef __cpp_lib_bit_cast
+ return std::bit_cast<std::weak_ordering>(*this);
+#else
+ using O = QtPrivate::Ordering;
+ using R = std::weak_ordering;
+ switch (m_order) {
+ case qToUnderlying(O::Less): return R::less;
+ case qToUnderlying(O::Greater): return R::greater;
+ case qToUnderlying(O::Equivalent): return R::equivalent;
+ }
+ Q_UNREACHABLE_RETURN(R::equivalent);
+#endif // __cpp_lib_bit_cast
+ }
+
+ friend constexpr bool operator==(weak_ordering lhs, std::weak_ordering rhs) noexcept
+ { return static_cast<std::weak_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(weak_ordering lhs, std::weak_ordering rhs) noexcept
+ { return static_cast<std::weak_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(weak_ordering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::weak_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(weak_ordering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::weak_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(weak_ordering lhs, std::strong_ordering rhs) noexcept
+ { return static_cast<std::weak_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(weak_ordering lhs, std::strong_ordering rhs) noexcept
+ { return static_cast<std::weak_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(std::weak_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs == static_cast<std::weak_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::weak_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs != static_cast<std::weak_ordering>(rhs); }
+
+ friend constexpr bool operator==(std::partial_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs == static_cast<std::weak_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::partial_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs != static_cast<std::weak_ordering>(rhs); }
+
+ friend constexpr bool operator==(std::strong_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs == static_cast<std::weak_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::strong_ordering lhs, weak_ordering rhs) noexcept
+ { return lhs != static_cast<std::weak_ordering>(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+private:
+ friend class strong_ordering;
+
+ constexpr explicit weak_ordering(QtPrivate::Ordering order) noexcept
+ : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
+ {}
+
+ QT_WARNING_PUSH
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
+ QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
+ friend constexpr bool is_eq (weak_ordering o) noexcept { return o == 0; }
+ friend constexpr bool is_neq (weak_ordering o) noexcept { return o != 0; }
+ friend constexpr bool is_lt (weak_ordering o) noexcept { return o < 0; }
+ friend constexpr bool is_lteq(weak_ordering o) noexcept { return o <= 0; }
+ friend constexpr bool is_gt (weak_ordering o) noexcept { return o > 0; }
+ friend constexpr bool is_gteq(weak_ordering o) noexcept { return o >= 0; }
+ QT_WARNING_POP
+
+ QtPrivate::CompareUnderlyingType m_order;
+};
+
+inline constexpr weak_ordering weak_ordering::less(QtPrivate::Ordering::Less);
+inline constexpr weak_ordering weak_ordering::equivalent(QtPrivate::Ordering::Equivalent);
+inline constexpr weak_ordering weak_ordering::greater(QtPrivate::Ordering::Greater);
+
+class strong_ordering
+{
+public:
+ static const strong_ordering less;
+ static const strong_ordering equivalent;
+ static const strong_ordering equal;
+ static const strong_ordering greater;
+
+ constexpr Q_IMPLICIT operator partial_ordering() const noexcept
+ { return partial_ordering(static_cast<QtPrivate::Ordering>(m_order)); }
+
+ constexpr Q_IMPLICIT operator weak_ordering() const noexcept
+ { return weak_ordering(static_cast<QtPrivate::Ordering>(m_order)); }
+
+ friend constexpr bool operator==(strong_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order == 0; }
+
+ friend constexpr bool operator!=(strong_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order != 0; }
+
+ friend constexpr bool operator< (strong_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order < 0; }
+
+ friend constexpr bool operator<=(strong_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order <= 0; }
+
+ friend constexpr bool operator> (strong_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order > 0; }
+
+ friend constexpr bool operator>=(strong_ordering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.m_order >= 0; }
+
+
+ friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero,
+ strong_ordering rhs) noexcept
+ { return 0 == rhs.m_order; }
+
+ friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero,
+ strong_ordering rhs) noexcept
+ { return 0 != rhs.m_order; }
+
+ friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero,
+ strong_ordering rhs) noexcept
+ { return 0 < rhs.m_order; }
+
+ friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero,
+ strong_ordering rhs) noexcept
+ { return 0 <= rhs.m_order; }
+
+ friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero,
+ strong_ordering rhs) noexcept
+ { return 0 > rhs.m_order; }
+
+ friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero,
+ strong_ordering rhs) noexcept
+ { return 0 >= rhs.m_order; }
+
+
+#ifdef __cpp_lib_three_way_comparison
+ friend constexpr std::strong_ordering
+ operator<=>(strong_ordering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs; } // https://eel.is/c++draft/cmp.strongord#6
+
+ friend constexpr std::strong_ordering
+ operator<=>(QtPrivate::CompareAgainstLiteralZero, strong_ordering rhs) noexcept
+ { return QtOrderingPrivate::reversed(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+
+ friend constexpr bool operator==(strong_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs.m_order == rhs.m_order; }
+
+ friend constexpr bool operator!=(strong_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs.m_order != rhs.m_order; }
+
+ friend constexpr bool operator==(strong_ordering lhs, partial_ordering rhs) noexcept
+ { return static_cast<partial_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(strong_ordering lhs, partial_ordering rhs) noexcept
+ { return static_cast<partial_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator==(partial_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs == static_cast<partial_ordering>(rhs); }
+
+ friend constexpr bool operator!=(partial_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs != static_cast<partial_ordering>(rhs); }
+
+ friend constexpr bool operator==(strong_ordering lhs, weak_ordering rhs) noexcept
+ { return static_cast<weak_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(strong_ordering lhs, weak_ordering rhs) noexcept
+ { return static_cast<weak_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator==(weak_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs == static_cast<weak_ordering>(rhs); }
+
+ friend constexpr bool operator!=(weak_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs != static_cast<weak_ordering>(rhs); }
+
+#ifdef __cpp_lib_three_way_comparison
+ constexpr Q_IMPLICIT strong_ordering(std::strong_ordering stdorder) noexcept
+ {
+ if (stdorder == std::strong_ordering::less)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
+ else if (stdorder == std::strong_ordering::equivalent)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equivalent);
+ else if (stdorder == std::strong_ordering::equal)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equal);
+ else if (stdorder == std::strong_ordering::greater)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
+ }
+
+ constexpr Q_IMPLICIT operator std::strong_ordering() const noexcept
+ {
+ static_assert(sizeof(*this) == sizeof(std::strong_ordering));
+#ifdef __cpp_lib_bit_cast
+ return std::bit_cast<std::strong_ordering>(*this);
+#else
+ using O = QtPrivate::Ordering;
+ using R = std::strong_ordering;
+ switch (m_order) {
+ case qToUnderlying(O::Less): return R::less;
+ case qToUnderlying(O::Greater): return R::greater;
+ case qToUnderlying(O::Equal): return R::equal;
+ }
+ Q_UNREACHABLE_RETURN(R::equal);
+#endif // __cpp_lib_bit_cast
+ }
+
+ friend constexpr bool operator==(strong_ordering lhs, std::strong_ordering rhs) noexcept
+ { return static_cast<std::strong_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(strong_ordering lhs, std::strong_ordering rhs) noexcept
+ { return static_cast<std::strong_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(strong_ordering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::strong_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(strong_ordering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::strong_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(strong_ordering lhs, std::weak_ordering rhs) noexcept
+ { return static_cast<std::strong_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(strong_ordering lhs, std::weak_ordering rhs) noexcept
+ { return static_cast<std::strong_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(std::strong_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs == static_cast<std::strong_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::strong_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs != static_cast<std::strong_ordering>(rhs); }
+
+ friend constexpr bool operator==(std::partial_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs == static_cast<std::strong_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::partial_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs != static_cast<std::strong_ordering>(rhs); }
+
+ friend constexpr bool operator==(std::weak_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs == static_cast<std::strong_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::weak_ordering lhs, strong_ordering rhs) noexcept
+ { return lhs != static_cast<std::strong_ordering>(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+ private:
+ constexpr explicit strong_ordering(QtPrivate::Ordering order) noexcept
+ : m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
+ {}
+
+ QT_WARNING_PUSH
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
+ QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
+ friend constexpr bool is_eq (strong_ordering o) noexcept { return o == 0; }
+ friend constexpr bool is_neq (strong_ordering o) noexcept { return o != 0; }
+ friend constexpr bool is_lt (strong_ordering o) noexcept { return o < 0; }
+ friend constexpr bool is_lteq(strong_ordering o) noexcept { return o <= 0; }
+ friend constexpr bool is_gt (strong_ordering o) noexcept { return o > 0; }
+ friend constexpr bool is_gteq(strong_ordering o) noexcept { return o >= 0; }
+ QT_WARNING_POP
+
+ QtPrivate::CompareUnderlyingType m_order;
+};
+
+inline constexpr strong_ordering strong_ordering::less(QtPrivate::Ordering::Less);
+inline constexpr strong_ordering strong_ordering::equivalent(QtPrivate::Ordering::Equivalent);
+inline constexpr strong_ordering strong_ordering::equal(QtPrivate::Ordering::Equal);
+inline constexpr strong_ordering strong_ordering::greater(QtPrivate::Ordering::Greater);
+
+} // namespace Qt
+
+QT_BEGIN_INCLUDE_NAMESPACE
+
+// This is intentionally included after Qt::*_ordering types and before
+// qCompareThreeWay. Do not change!
+#include <QtCore/qcomparehelpers.h>
+
+QT_END_INCLUDE_NAMESPACE
+
+namespace QtPrivate {
+
+namespace CompareThreeWayTester {
+
+ using Qt::compareThreeWay;
+
+ // Check if compareThreeWay is implemented for the (LT, RT) argument
+ // pair.
+ template <typename LT, typename RT, typename = void>
+ constexpr bool hasCompareThreeWay = false;
+
+ template <typename LT, typename RT>
+ constexpr bool hasCompareThreeWay<
+ LT, RT, std::void_t<decltype(compareThreeWay(std::declval<LT>(), std::declval<RT>()))>
+ > = true;
+
+ // Check if the operation is noexcept. We have two different overloads,
+ // depending on the available compareThreeWay() implementation.
+ // Both are declared, but not implemented. To be used only in unevaluated
+ // context.
+
+ template <typename LT, typename RT,
+ std::enable_if_t<hasCompareThreeWay<LT, RT>, bool> = true>
+ constexpr bool compareThreeWayNoexcept() noexcept
+ { return noexcept(compareThreeWay(std::declval<LT>(), std::declval<RT>())); }
+
+ template <typename LT, typename RT,
+ std::enable_if_t<!hasCompareThreeWay<LT, RT> && hasCompareThreeWay<RT, LT>,
+ bool> = true>
+ constexpr bool compareThreeWayNoexcept() noexcept
+ { return noexcept(compareThreeWay(std::declval<RT>(), std::declval<LT>())); }
+
+} // namespace CompareThreeWayTester
+
+} // namespace QtPrivate
+
+#if defined(Q_QDOC)
+
+template <typename LeftType, typename RightType>
+auto qCompareThreeWay(const LeftType &lhs, const RightType &rhs);
+
+#else
+
+template <typename LT, typename RT,
+ std::enable_if_t<QtPrivate::CompareThreeWayTester::hasCompareThreeWay<LT, RT>
+ || QtPrivate::CompareThreeWayTester::hasCompareThreeWay<RT, LT>,
+ bool> = true>
+auto qCompareThreeWay(const LT &lhs, const RT &rhs)
+ noexcept(QtPrivate::CompareThreeWayTester::compareThreeWayNoexcept<LT, RT>())
+{
+ using Qt::compareThreeWay;
+ if constexpr (QtPrivate::CompareThreeWayTester::hasCompareThreeWay<LT, RT>) {
+ return compareThreeWay(lhs, rhs);
+ } else {
+ const auto retval = compareThreeWay(rhs, lhs);
+ return QtOrderingPrivate::reversed(retval);
+ }
+}
+
+#endif // defined(Q_QDOC)
+
+//
+// Legacy QPartialOrdering
+//
+
+namespace QtPrivate {
+enum class LegacyUncomparable : CompareUnderlyingType
+{
+ Unordered = -127
+};
+}
+
// [cmp.partialord]
class QPartialOrdering
{
@@ -77,49 +683,195 @@ public:
static const QPartialOrdering Greater;
static const QPartialOrdering Unordered;
- friend constexpr bool operator==(QPartialOrdering p, QtPrivate::CompareAgainstLiteralZero) noexcept
- { return p.isOrdered() && p.m_order == 0; }
- friend constexpr bool operator!=(QPartialOrdering p, QtPrivate::CompareAgainstLiteralZero) noexcept
- { return p.isOrdered() && p.m_order != 0; }
- friend constexpr bool operator< (QPartialOrdering p, QtPrivate::CompareAgainstLiteralZero) noexcept
- { return p.isOrdered() && p.m_order < 0; }
- friend constexpr bool operator<=(QPartialOrdering p, QtPrivate::CompareAgainstLiteralZero) noexcept
- { return p.isOrdered() && p.m_order <= 0; }
- friend constexpr bool operator> (QPartialOrdering p, QtPrivate::CompareAgainstLiteralZero) noexcept
- { return p.isOrdered() && p.m_order > 0; }
- friend constexpr bool operator>=(QPartialOrdering p, QtPrivate::CompareAgainstLiteralZero) noexcept
- { return p.isOrdered() && p.m_order >= 0; }
-
- friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering p) noexcept
- { return p.isOrdered() && 0 == p.m_order; }
- friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering p) noexcept
- { return p.isOrdered() && 0 != p.m_order; }
- friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero, QPartialOrdering p) noexcept
- { return p.isOrdered() && 0 < p.m_order; }
- friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering p) noexcept
- { return p.isOrdered() && 0 <= p.m_order; }
- friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero, QPartialOrdering p) noexcept
- { return p.isOrdered() && 0 > p.m_order; }
- friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering p) noexcept
- { return p.isOrdered() && 0 >= p.m_order; }
-
- friend constexpr bool operator==(QPartialOrdering p1, QPartialOrdering p2) noexcept
- { return p1.m_order == p2.m_order; }
- friend constexpr bool operator!=(QPartialOrdering p1, QPartialOrdering p2) noexcept
- { return p1.m_order != p2.m_order; }
+ static const QPartialOrdering less;
+ static const QPartialOrdering equivalent;
+ static const QPartialOrdering greater;
+ static const QPartialOrdering unordered;
+
+ friend constexpr bool operator==(QPartialOrdering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order == 0; }
+
+ friend constexpr bool operator!=(QPartialOrdering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order != 0; }
+
+ friend constexpr bool operator< (QPartialOrdering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order < 0; }
+
+ friend constexpr bool operator<=(QPartialOrdering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order <= 0; }
+
+ friend constexpr bool operator> (QPartialOrdering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order > 0; }
+
+ friend constexpr bool operator>=(QPartialOrdering lhs,
+ QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs.isOrdered() && lhs.m_order >= 0; }
+
+
+ friend constexpr bool operator==(QtPrivate::CompareAgainstLiteralZero,
+ QPartialOrdering rhs) noexcept
+ { return rhs.isOrdered() && 0 == rhs.m_order; }
+
+ friend constexpr bool operator!=(QtPrivate::CompareAgainstLiteralZero,
+ QPartialOrdering rhs) noexcept
+ { return rhs.isOrdered() && 0 != rhs.m_order; }
+
+ friend constexpr bool operator< (QtPrivate::CompareAgainstLiteralZero,
+ QPartialOrdering rhs) noexcept
+ { return rhs.isOrdered() && 0 < rhs.m_order; }
+
+ friend constexpr bool operator<=(QtPrivate::CompareAgainstLiteralZero,
+ QPartialOrdering rhs) noexcept
+ { return rhs.isOrdered() && 0 <= rhs.m_order; }
+
+ friend constexpr bool operator> (QtPrivate::CompareAgainstLiteralZero,
+ QPartialOrdering rhs) noexcept
+ { return rhs.isOrdered() && 0 > rhs.m_order; }
+
+ friend constexpr bool operator>=(QtPrivate::CompareAgainstLiteralZero,
+ QPartialOrdering rhs) noexcept
+ { return rhs.isOrdered() && 0 >= rhs.m_order; }
+
+
+#ifdef __cpp_lib_three_way_comparison
+ friend constexpr std::partial_ordering
+ operator<=>(QPartialOrdering lhs, QtPrivate::CompareAgainstLiteralZero) noexcept
+ { return lhs; } // https://eel.is/c++draft/cmp.partialord#4
+
+ friend constexpr std::partial_ordering
+ operator<=>(QtPrivate::CompareAgainstLiteralZero, QPartialOrdering rhs) noexcept
+ { return QtOrderingPrivate::reversed(rhs); }
+#endif // __cpp_lib_three_way_comparison
+
+
+ friend constexpr bool operator==(QPartialOrdering lhs, QPartialOrdering rhs) noexcept
+ { return lhs.m_order == rhs.m_order; }
+
+ friend constexpr bool operator!=(QPartialOrdering lhs, QPartialOrdering rhs) noexcept
+ { return lhs.m_order != rhs.m_order; }
+
+ constexpr Q_IMPLICIT QPartialOrdering(Qt::partial_ordering order) noexcept
+ : m_order{} // == equivalent
+ {
+ if (order == Qt::partial_ordering::less)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
+ else if (order == Qt::partial_ordering::greater)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
+ else if (order == Qt::partial_ordering::unordered)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered);
+ }
+
+ constexpr Q_IMPLICIT QPartialOrdering(Qt::weak_ordering stdorder) noexcept
+ : QPartialOrdering(Qt::partial_ordering{stdorder}) {}
+
+ constexpr Q_IMPLICIT QPartialOrdering(Qt::strong_ordering stdorder) noexcept
+ : QPartialOrdering(Qt::partial_ordering{stdorder}) {}
+
+ constexpr Q_IMPLICIT operator Qt::partial_ordering() const noexcept
+ {
+ using O = QtPrivate::Ordering;
+ using U = QtPrivate::LegacyUncomparable;
+ using R = Qt::partial_ordering;
+ switch (m_order) {
+ case qToUnderlying(O::Less): return R::less;
+ case qToUnderlying(O::Greater): return R::greater;
+ case qToUnderlying(O::Equivalent): return R::equivalent;
+ case qToUnderlying(U::Unordered): return R::unordered;
+ }
+ // GCC 8.x does not treat __builtin_unreachable() as constexpr
+#if !defined(Q_CC_GNU_ONLY) || (Q_CC_GNU >= 900)
+ // NOLINTNEXTLINE(qt-use-unreachable-return): Triggers on Clang, breaking GCC 8
+ Q_UNREACHABLE();
+#endif
+ return R::unordered;
+ }
+
+ friend constexpr bool operator==(QPartialOrdering lhs, Qt::partial_ordering rhs) noexcept
+ { Qt::partial_ordering qt = lhs; return qt == rhs; }
+
+ friend constexpr bool operator!=(QPartialOrdering lhs, Qt::partial_ordering rhs) noexcept
+ { Qt::partial_ordering qt = lhs; return qt != rhs; }
+
+ friend constexpr bool operator==(Qt::partial_ordering lhs, QPartialOrdering rhs) noexcept
+ { Qt::partial_ordering qt = rhs; return lhs == qt; }
+
+ friend constexpr bool operator!=(Qt::partial_ordering lhs, QPartialOrdering rhs) noexcept
+ { Qt::partial_ordering qt = rhs; return lhs != qt; }
+
+#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::CompareUnderlyingType>(QtPrivate::Ordering::Less);
+ else if (stdorder == std::partial_ordering::equivalent)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Equivalent);
+ else if (stdorder == std::partial_ordering::greater)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
+ else if (stdorder == std::partial_ordering::unordered)
+ m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered);
+ }
+
+ constexpr Q_IMPLICIT QPartialOrdering(std::weak_ordering stdorder) noexcept
+ : QPartialOrdering(std::partial_ordering(stdorder)) {}
+
+ constexpr Q_IMPLICIT QPartialOrdering(std::strong_ordering stdorder) noexcept
+ : QPartialOrdering(std::partial_ordering(stdorder)) {}
+
+ constexpr Q_IMPLICIT operator std::partial_ordering() const noexcept
+ {
+ using O = QtPrivate::Ordering;
+ using U = QtPrivate::LegacyUncomparable;
+ using R = std::partial_ordering;
+ switch (m_order) {
+ case qToUnderlying(O::Less): return R::less;
+ case qToUnderlying(O::Greater): return R::greater;
+ case qToUnderlying(O::Equivalent): return R::equivalent;
+ case qToUnderlying(U::Unordered): return R::unordered;
+ }
+ Q_UNREACHABLE_RETURN(R::unordered);
+ }
+
+ friend constexpr bool operator==(QPartialOrdering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::partial_ordering>(lhs) == rhs; }
+
+ friend constexpr bool operator!=(QPartialOrdering lhs, std::partial_ordering rhs) noexcept
+ { return static_cast<std::partial_ordering>(lhs) != rhs; }
+
+ friend constexpr bool operator==(std::partial_ordering lhs, QPartialOrdering rhs) noexcept
+ { return lhs == static_cast<std::partial_ordering>(rhs); }
+
+ friend constexpr bool operator!=(std::partial_ordering lhs, QPartialOrdering rhs) noexcept
+ { return lhs != static_cast<std::partial_ordering>(rhs); }
+#endif // __cpp_lib_three_way_comparison
private:
constexpr explicit QPartialOrdering(QtPrivate::Ordering order) noexcept
: m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
{}
- constexpr explicit QPartialOrdering(QtPrivate::Uncomparable order) noexcept
+ constexpr explicit QPartialOrdering(QtPrivate::LegacyUncomparable order) noexcept
: m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
{}
+ QT_WARNING_PUSH
+ // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100903
+ QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
+ friend constexpr bool is_eq (QPartialOrdering o) noexcept { return o == 0; }
+ friend constexpr bool is_neq (QPartialOrdering o) noexcept { return o != 0; }
+ friend constexpr bool is_lt (QPartialOrdering o) noexcept { return o < 0; }
+ friend constexpr bool is_lteq(QPartialOrdering o) noexcept { return o <= 0; }
+ friend constexpr bool is_gt (QPartialOrdering o) noexcept { return o > 0; }
+ friend constexpr bool is_gteq(QPartialOrdering o) noexcept { return o >= 0; }
+ QT_WARNING_POP
+
// instead of the exposition only is_ordered member in [cmp.partialord],
// use a private function
- constexpr bool isOrdered() noexcept
- { return m_order != static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Uncomparable::Unordered); }
+ constexpr bool isOrdered() const noexcept
+ { return m_order != static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered); }
QtPrivate::CompareUnderlyingType m_order;
};
@@ -127,7 +879,12 @@ private:
inline constexpr QPartialOrdering QPartialOrdering::Less(QtPrivate::Ordering::Less);
inline constexpr QPartialOrdering QPartialOrdering::Equivalent(QtPrivate::Ordering::Equivalent);
inline constexpr QPartialOrdering QPartialOrdering::Greater(QtPrivate::Ordering::Greater);
-inline constexpr QPartialOrdering QPartialOrdering::Unordered(QtPrivate::Uncomparable::Unordered);
+inline constexpr QPartialOrdering QPartialOrdering::Unordered(QtPrivate::LegacyUncomparable::Unordered);
+
+inline constexpr QPartialOrdering QPartialOrdering::less(QtPrivate::Ordering::Less);
+inline constexpr QPartialOrdering QPartialOrdering::equivalent(QtPrivate::Ordering::Equivalent);
+inline constexpr QPartialOrdering QPartialOrdering::greater(QtPrivate::Ordering::Greater);
+inline constexpr QPartialOrdering QPartialOrdering::unordered(QtPrivate::LegacyUncomparable::Unordered);
QT_END_NAMESPACE