Source code
Revision control
Copy as Markdown
// 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
// Qt-Security score:significant reason:default
#ifndef QCOMPARE_H
#define QCOMPARE_H
#if 0
#pragma qt_class(QtCompare)
#endif
#include <QtCore/qglobal.h>
#include <QtCore/qcompare_impl.h>
#include <QtCore/qstdlibdetection.h>
#ifdef __cpp_lib_bit_cast
#include <bit>
#endif
#ifdef __cpp_lib_three_way_comparison
#include <compare>
#endif
QT_BEGIN_NAMESPACE
namespace QtPrivate {
using CompareUnderlyingType = qint8;
constexpr CompareUnderlyingType LegacyUncomparableValue = -127; // historic Qt value
// [cmp.categories.pre] / 1
enum class Ordering : CompareUnderlyingType
{
Equal = 0,
Equivalent = Equal,
Less = -1,
Greater = 1
};
enum class Uncomparable : CompareUnderlyingType
{
// We choose the value of our Uncomparable to be the same that the C++
// Standard Library chooses for its own std::partial_ordering::unordered,
// so we can convert from their type to ours via simple std::bit_cast.
#if 0
// GCC 16 broke ABI, so we cannot use the std::*_ordering types
// in our ABI until we drop support for GCC 15 and earlier. When that
// happens and std::bit_cast is guaranteed, this can be simplified to:
Unordered = std::bit_cast<CompareUnderlyingType>(std::partial_ordering::unordered);
#else
Unordered =
#if defined(Q_STL_LIBCPP)
-127
#elif defined(Q_STL_LIBSTDCPP) && QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
// GCC 10 to 15 ABI
2
#elif defined(Q_STL_LIBSTDCPP)
-128
#elif defined(Q_STL_MSSTL)
-128
#elif defined(Q_STL_DINKUMWARE) || \
defined(Q_STL_ROGUEWAVE) || \
defined(Q_STL_STLPORT) || \
defined(Q_STL_SGI)
QtPrivate::LegacyUncomparableValue
// We haven't seen C++20 of these libraries, so we haven't chosen a value yet.
# ifdef __cpp_lib_three_way_comparison
# error Please report the numeric value of std::partial_ordering::unordered in your STL in a bug report.
# endif
#else
# error Please handle any newly-added Q_STL_ checks in the above ifdef-ery.
#endif
#endif // future Qt
};
} // namespace QtPrivate
namespace QtOrderingPrivate {
using QtPrivate::Ordering;
using QtPrivate::Uncomparable;
#if defined(__cpp_lib_bit_cast) && defined(__cpp_lib_three_way_comparison)
inline constexpr bool OrderingValuesAreEqual =
std::bit_cast<Ordering>(std::weak_ordering::equivalent) == Ordering::Equivalent &&
std::bit_cast<Ordering>(std::strong_ordering::equal) == Ordering::Equal &&
std::bit_cast<Ordering>(std::strong_ordering::less) == Ordering::Less &&
std::bit_cast<Ordering>(std::strong_ordering::greater) == Ordering::Greater;
inline constexpr bool UnorderedValueIsEqual =
std::bit_cast<Uncomparable>(std::partial_ordering::unordered) == Uncomparable::Unordered;
#endif
template <typename O>
constexpr O reversed(O o) noexcept
{
return is_lt(o) ? O::greater :
is_gt(o) ? O::less :
/*else*/ o ;
}
template <typename O> constexpr auto toUnderlying(O o) noexcept;
} // namespace QtOrderingPrivate
QT_WARNING_PUSH
QT_WARNING_DISABLE_MSVC(4702) // unreachable code
QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
QT_WARNING_DISABLE_CLANG("-Wzero-as-null-pointer-constant")
namespace Qt {
class weak_ordering;
class strong_ordering;
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
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
: m_order{} // == equivalent
{
#ifdef __cpp_lib_bit_cast
if constexpr (QtOrderingPrivate::OrderingValuesAreEqual) {
m_order = std::bit_cast<QtPrivate::CompareUnderlyingType>(stdorder);
if constexpr (!QtOrderingPrivate::UnorderedValueIsEqual) {
if (stdorder == std::partial_ordering::unordered)
m_order = qToUnderlying(QtPrivate::Uncomparable::Unordered);
}
return;
}
#endif // __cpp_lib_bit_cast
if (stdorder < 0)
m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
else if (stdorder > 0)
m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Greater);
else if (stdorder != 0)
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));
using O = QtPrivate::Ordering;
using U = QtPrivate::Uncomparable;
using R = std::partial_ordering;
#ifdef __cpp_lib_bit_cast
if constexpr (QtOrderingPrivate::OrderingValuesAreEqual) {
if constexpr (!QtOrderingPrivate::UnorderedValueIsEqual) {
if (m_order == qToUnderlying(U::Unordered))
return R::unordered;
}
return std::bit_cast<R>(*this);
}
#endif // __cpp_lib_bit_cast
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==(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); }
friend constexpr bool operator==(partial_ordering lhs, std::strong_ordering rhs) noexcept
{ return static_cast<std::partial_ordering>(lhs) == rhs; }
friend constexpr bool operator!=(partial_ordering lhs, std::strong_ordering rhs) noexcept
{ return static_cast<std::partial_ordering>(lhs) != rhs; }
friend constexpr bool operator==(std::strong_ordering lhs, partial_ordering rhs) noexcept
{ return lhs == static_cast<std::partial_ordering>(rhs); }
friend constexpr bool operator!=(std::strong_ordering lhs, partial_ordering rhs) noexcept
{ return lhs != static_cast<std::partial_ordering>(rhs); }
friend constexpr bool operator==(partial_ordering lhs, std::weak_ordering rhs) noexcept
{ return static_cast<std::partial_ordering>(lhs) == rhs; }
friend constexpr bool operator!=(partial_ordering lhs, std::weak_ordering rhs) noexcept
{ return static_cast<std::partial_ordering>(lhs) != rhs; }
friend constexpr bool operator==(std::weak_ordering lhs, partial_ordering rhs) noexcept
{ return lhs == static_cast<std::partial_ordering>(rhs); }
friend constexpr bool operator!=(std::weak_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;
template <typename O> friend constexpr auto QtOrderingPrivate::toUnderlying(O o) noexcept;
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))
{}
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; }
// 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
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
: m_order{} // == equivalent
{
#ifdef __cpp_lib_bit_cast
if constexpr (QtOrderingPrivate::OrderingValuesAreEqual) {
m_order = std::bit_cast<QtPrivate::CompareUnderlyingType>(stdorder);
return;
}
#endif // __cpp_lib_bit_cast
if (stdorder < 0)
m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
else if (stdorder > 0)
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));
using O = QtPrivate::Ordering;
using R = std::weak_ordering;
#ifdef __cpp_lib_bit_cast
if constexpr (QtOrderingPrivate::OrderingValuesAreEqual)
return std::bit_cast<R>(*this);
#endif // __cpp_lib_bit_cast
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);
}
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;
template <typename O> friend constexpr auto QtOrderingPrivate::toUnderlying(O o) noexcept;
constexpr explicit weak_ordering(QtPrivate::Ordering order) noexcept
: m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
{}
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; }
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
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
: m_order{} // == equivalent
{
#ifdef __cpp_lib_bit_cast
if constexpr (QtOrderingPrivate::OrderingValuesAreEqual) {
m_order = std::bit_cast<QtPrivate::CompareUnderlyingType>(stdorder);
return;
}
#endif // __cpp_lib_bit_cast
if (stdorder < 0)
m_order = static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::Ordering::Less);
else if (stdorder > 0)
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));
using O = QtPrivate::Ordering;
using R = std::strong_ordering;
#ifdef __cpp_lib_bit_cast
if constexpr (QtOrderingPrivate::OrderingValuesAreEqual)
return std::bit_cast<R>(*this);
#endif // __cpp_lib_bit_cast
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);
}
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:
template <typename O> friend constexpr auto QtOrderingPrivate::toUnderlying(O o) noexcept;
constexpr explicit strong_ordering(QtPrivate::Ordering order) noexcept
: m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
{}
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; }
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_WARNING_POP
namespace QtOrderingPrivate {
template<> constexpr auto toUnderlying<Qt::partial_ordering>(Qt::partial_ordering o) noexcept
{ return o.m_order; }
template<> constexpr auto toUnderlying<Qt::weak_ordering>(Qt::weak_ordering o) noexcept
{ return o.m_order; }
template<> constexpr auto toUnderlying<Qt::strong_ordering>(Qt::strong_ordering o) noexcept
{ return o.m_order; }
}
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
#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<
std::disjunction_v<
QtOrderingPrivate::CompareThreeWayTester::HasCompareThreeWay<LT, RT>,
QtOrderingPrivate::CompareThreeWayTester::HasCompareThreeWay<RT, LT>>,
bool> = true>
auto qCompareThreeWay(const LT &lhs, const RT &rhs)
noexcept(QtOrderingPrivate::CompareThreeWayTester::compareThreeWayNoexcept<LT, RT>())
{
using Qt::compareThreeWay;
if constexpr (QtOrderingPrivate::CompareThreeWayTester::hasCompareThreeWay_v<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 = QtPrivate::LegacyUncomparableValue
};
}
// [cmp.partialord]
class QPartialOrdering
{
public:
static const QPartialOrdering Less;
static const QPartialOrdering Equivalent;
static const QPartialOrdering Greater;
static const QPartialOrdering Unordered;
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
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
: QPartialOrdering(Qt::partial_ordering(stdorder)) {}
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::LegacyUncomparable order) noexcept
: m_order(static_cast<QtPrivate::CompareUnderlyingType>(order))
{}
QT_WARNING_PUSH
QT_WARNING_DISABLE_GCC("-Wzero-as-null-pointer-constant")
QT_WARNING_DISABLE_CLANG("-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() const noexcept
{ return m_order != static_cast<QtPrivate::CompareUnderlyingType>(QtPrivate::LegacyUncomparable::Unordered); }
QtPrivate::CompareUnderlyingType m_order;
};
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);
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
#endif // QCOMPARE_H