diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index ec0e802d7c..827680cc4f 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -49,7 +49,7 @@ qt_internal_add_module(Core global/archdetect.cpp global/qassert.cpp global/qassert.h global/qcompare_impl.h - global/qcompare.h + global/qcompare.cpp global/qcompare.h global/qcompilerdetection.h global/qconstructormacros.h global/qcontainerinfo.h diff --git a/src/corelib/global/qcompare.qdoc b/src/corelib/global/qcompare.cpp similarity index 95% rename from src/corelib/global/qcompare.qdoc rename to src/corelib/global/qcompare.cpp index 48c2f05803..e02c78b6ae 100644 --- a/src/corelib/global/qcompare.qdoc +++ b/src/corelib/global/qcompare.cpp @@ -2,6 +2,41 @@ // Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only +#include "qcompare.h" + +#ifdef __cpp_lib_bit_cast +#include +#endif + +QT_BEGIN_NAMESPACE + +#ifdef __cpp_lib_three_way_comparison +static_assert(sizeof(std::partial_ordering) == sizeof(Qt::partial_ordering)); +static_assert(sizeof(std::weak_ordering) == sizeof(Qt::weak_ordering)); +static_assert(sizeof(std::strong_ordering) == sizeof(Qt::strong_ordering)); +#ifdef __cpp_lib_bit_cast +#define CHECK(type, flag) \ + static_assert(std::bit_cast(std:: type ## _ordering:: flag) \ + == Qt:: type ## _ordering :: flag); \ + static_assert(std::bit_cast(Qt:: type ## _ordering:: flag) \ + == std:: type ## _ordering :: flag) \ + /* end */ +CHECK(partial, unordered); +CHECK(partial, less); +CHECK(partial, greater); +CHECK(partial, equivalent); +CHECK(weak, less); +CHECK(weak, greater); +CHECK(weak, equivalent); +CHECK(strong, less); +CHECK(strong, greater); +CHECK(strong, equal); +CHECK(strong, equivalent); +#undef CHECK +#endif // __cpp_lib_bit_cast +#endif //__cpp_lib_three_way_comparison + + /*! \page comparison-types.html overview \title Comparison types overview @@ -398,7 +433,7 @@ \fn Qt::weak_ordering::is_gt (Qt::weak_ordering o) \fn Qt::weak_ordering::is_gteq(Qt::weak_ordering o) - \include qcompare.qdoc is_eq_table + \include qcompare.cpp is_eq_table These functions are provided for compatibility with \c{std::weak_ordering}. */ @@ -544,7 +579,7 @@ \fn Qt::partial_ordering::is_gt (Qt::partial_ordering o) \fn Qt::partial_ordering::is_gteq(Qt::partial_ordering o) - \include qcompare.qdoc is_eq_table + \include qcompare.cpp is_eq_table These functions are provided for compatibility with \c{std::partial_ordering}. */ @@ -697,7 +732,7 @@ \fn QPartialOrdering::is_gt (QPartialOrdering o) \fn QPartialOrdering::is_gteq(QPartialOrdering o) - \include qcompare.qdoc is_eq_table + \include qcompare.cpp is_eq_table These functions are provided for compatibility with \c{std::partial_ordering}. */ @@ -729,3 +764,5 @@ Represents the result of a comparison where the left operand is not ordered with respect to the right operand. */ + +QT_END_NAMESPACE diff --git a/src/corelib/global/qcompare.h b/src/corelib/global/qcompare.h index 1a9d53bc73..90341270d7 100644 --- a/src/corelib/global/qcompare.h +++ b/src/corelib/global/qcompare.h @@ -30,11 +30,23 @@ enum class Ordering : CompareUnderlyingType Greater = 1 }; -enum class Uncomparable : CompareUnderlyingType +enum class LegacyUncomparable : CompareUnderlyingType { Unordered = -127 }; +enum class Uncomparable : CompareUnderlyingType +{ + Unordered = + #if defined(_LIBCPP_VERSION) // libc++ + -127 + #elif defined(__GLIBCXX__) // libstd++ + 2 + #else // assume MSSTL + -128 + #endif +}; + } // namespace QtPrivate // [cmp.partialord] @@ -112,7 +124,7 @@ public: 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); + m_order = static_cast(QtPrivate::LegacyUncomparable::Unordered); } constexpr Q_IMPLICIT operator std::partial_ordering() const noexcept @@ -123,7 +135,7 @@ public: 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) + else if (static_cast(m_order) == QtPrivate::LegacyUncomparable::Unordered) return std::partial_ordering::unordered; return std::partial_ordering::unordered; } @@ -145,7 +157,7 @@ private: constexpr explicit QPartialOrdering(QtPrivate::Ordering order) noexcept : m_order(static_cast(order)) {} - constexpr explicit QPartialOrdering(QtPrivate::Uncomparable order) noexcept + constexpr explicit QPartialOrdering(QtPrivate::LegacyUncomparable order) noexcept : m_order(static_cast(order)) {} @@ -163,7 +175,7 @@ private: // 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::Uncomparable::Unordered); } + { return m_order != static_cast(QtPrivate::LegacyUncomparable::Unordered); } QtPrivate::CompareUnderlyingType m_order; }; @@ -171,7 +183,7 @@ 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); namespace Qt { diff --git a/tests/auto/corelib/global/qcompare/tst_qcompare.cpp b/tests/auto/corelib/global/qcompare/tst_qcompare.cpp index f0bba8b3ce..7561fbdc38 100644 --- a/tests/auto/corelib/global/qcompare/tst_qcompare.cpp +++ b/tests/auto/corelib/global/qcompare/tst_qcompare.cpp @@ -13,6 +13,7 @@ class tst_QCompare: public QObject Q_OBJECT private slots: void legacyPartialOrdering(); + void stdQtBinaryCompatibility(); void partialOrdering(); void weakOrdering(); void strongOrdering(); @@ -130,6 +131,44 @@ void tst_QCompare::legacyPartialOrdering() static_assert(!(0 >= QPartialOrdering::Greater)); } +void tst_QCompare::stdQtBinaryCompatibility() +{ +#ifndef __cpp_lib_three_way_comparison + QSKIP("This test requires C++20 three-way-comparison support enabled in the stdlib."); +#else + QCOMPARE_EQ(sizeof(std::partial_ordering), 1U); + QCOMPARE_EQ(sizeof( Qt::partial_ordering), 1U); + QCOMPARE_EQ(sizeof(std:: weak_ordering), 1U); + QCOMPARE_EQ(sizeof( Qt:: weak_ordering), 1U); + QCOMPARE_EQ(sizeof(std:: strong_ordering), 1U); + QCOMPARE_EQ(sizeof( Qt:: strong_ordering), 1U); + + auto valueOf = [](auto obj) { + typename QIntegerForSizeof::Unsigned value; + memcpy(&value, &obj, sizeof(obj)); + return value; + }; +#define CHECK(type, flag) \ + QCOMPARE_EQ(valueOf( Qt:: type ## _ordering :: flag), \ + valueOf(std:: type ## _ordering :: flag)) \ + /* end */ + CHECK(partial, unordered); + CHECK(partial, less); + CHECK(partial, greater); + CHECK(partial, equivalent); + + CHECK(weak, less); + CHECK(weak, greater); + CHECK(weak, equivalent); + + CHECK(strong, less); + CHECK(strong, greater); + CHECK(strong, equivalent); + CHECK(strong, equal); +#undef CHECK +#endif //__cpp_lib_three_way_comparison +} + void tst_QCompare::partialOrdering() { static_assert(Qt::partial_ordering::unordered == Qt::partial_ordering::unordered);