summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTatiana Borisova <tatiana.borisova@qt.io>2024-07-11 12:20:26 +0200
committerMarc Mutz <marc.mutz@qt.io>2024-08-01 11:04:23 +0000
commit2aa39be4c23ad837c6a09b5cf74c74da670d7ebf (patch)
tree84aeb31ac26249e8011f3644f556a0769a4d9af5
parent1442a9ea479d197ed338f440d5106a7e195c4ee2 (diff)
Add QDebug printing for the std/Qt::<name>_ordering types
[ChangeLog][QtCore][QDebug] Added possibility to print {std/Qt} weak/partial/strong_ordering values with QDebug << operator. Change-Id: Ie880cb34c19f79a404c692c2322b3460d72bfde4 Reviewed-by: Marc Mutz <marc.mutz@qt.io>
-rw-r--r--src/corelib/global/qcomparehelpers.h54
-rw-r--r--src/corelib/io/qdebug.cpp49
-rw-r--r--src/corelib/io/qdebug.h14
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp32
-rw-r--r--tests/auto/testlib/tostring/tst_tostring.cpp37
5 files changed, 184 insertions, 2 deletions
diff --git a/src/corelib/global/qcomparehelpers.h b/src/corelib/global/qcomparehelpers.h
index 5f946dddd3c..922c62fbe21 100644
--- a/src/corelib/global/qcomparehelpers.h
+++ b/src/corelib/global/qcomparehelpers.h
@@ -14,6 +14,7 @@
#pragma qt_sync_stop_processing
#endif
+#include <QtCore/qflags.h>
#include <QtCore/qoverload.h>
#include <QtCore/qttypetraits.h>
#include <QtCore/qtypeinfo.h>
@@ -31,16 +32,34 @@ QT_BEGIN_NAMESPACE
class QPartialOrdering;
namespace QtOrderingPrivate {
-#ifdef __cpp_lib_three_way_comparison
+template <typename T> struct is_std_ordering_type : std::false_type {};
+template <typename T> struct is_qt_ordering_type : std::false_type {};
+
+template <typename T> constexpr bool is_std_ordering_type_v = is_std_ordering_type<T>::value;
+template <typename T> constexpr bool is_qt_ordering_type_v = is_qt_ordering_type<T>::value;
+
+enum class QtOrderingType {
+ QtOrder = 0x00,
+ StdOrder = 0x01,
+ Partial = 0x00,
+ Weak = 0x20,
+ Strong = 0x40,
+ StrengthMask = Weak|Strong,
+};
+Q_DECLARE_FLAGS(QtOrderingTypeFlag, QtOrderingType)
+Q_DECLARE_OPERATORS_FOR_FLAGS(QtOrderingPrivate::QtOrderingTypeFlag)
template <typename QtOrdering> struct StdOrdering;
template <typename StdOrdering> struct QtOrdering;
+#ifdef __cpp_lib_three_way_comparison
#define QT_STD_MAP(x) \
template <> struct StdOrdering< Qt::x##_ordering> : q20::type_identity<std::x##_ordering> {};\
template <> struct StdOrdering<std::x##_ordering> : q20::type_identity<std::x##_ordering> {};\
template <> struct QtOrdering<std::x##_ordering> : q20::type_identity< Qt::x##_ordering> {};\
template <> struct QtOrdering< Qt::x##_ordering> : q20::type_identity< Qt::x##_ordering> {};\
+ template <> struct is_std_ordering_type<std::x##_ordering> : std::true_type {};\
+ template <> struct is_qt_ordering_type< Qt::x##_ordering> : std::true_type {};\
/* end */
QT_STD_MAP(partial)
QT_STD_MAP(weak)
@@ -49,6 +68,11 @@ QT_STD_MAP(strong)
template <> struct StdOrdering<QPartialOrdering> : q20::type_identity<std::partial_ordering> {};
template <> struct QtOrdering<QPartialOrdering> : q20::type_identity< Qt::partial_ordering> {};
+#else
+template <> struct is_qt_ordering_type< Qt::partial_ordering> : std::true_type {};
+template <> struct is_qt_ordering_type< Qt::weak_ordering> : std::true_type {};
+template <> struct is_qt_ordering_type< Qt::strong_ordering> : std::true_type {};
+#endif // __cpp_lib_three_way_comparison
template <typename In> constexpr auto to_std(In in) noexcept
-> typename QtOrderingPrivate::StdOrdering<In>::type
@@ -58,7 +82,33 @@ template <typename In> constexpr auto to_Qt(In in) noexcept
-> typename QtOrderingPrivate::QtOrdering<In>::type
{ return in; }
-#endif // __cpp_lib_three_way_comparison
+template <typename T>
+constexpr bool is_ordering_type_v
+ = std::disjunction_v<is_qt_ordering_type<T>, is_std_ordering_type<T>>;
+
+template <typename T>
+constexpr std::enable_if_t<is_qt_ordering_type_v<T>, QtOrderingTypeFlag>
+orderingFlagsFor(T t) noexcept
+{
+ QtOrderingTypeFlag flags = QtOrderingType::QtOrder;
+ Qt::partial_ordering convertedOrder(t);
+ if constexpr (std::is_same_v<T, Qt::strong_ordering>)
+ flags = flags | QtOrderingType::Strong;
+ else if constexpr (std::is_same_v<T, Qt::partial_ordering>)
+ flags = flags | QtOrderingType::Partial;
+ else if constexpr (std::is_same_v<T, Qt::weak_ordering>)
+ flags = flags | QtOrderingType::Weak;
+ return flags;
+}
+
+template <typename T>
+constexpr std::enable_if_t<is_std_ordering_type_v<T>, QtOrderingTypeFlag>
+orderingFlagsFor(T t) noexcept
+{
+ QtOrderingPrivate::QtOrderingTypeFlag flags = QtOrderingPrivate::QtOrderingType::StdOrder;
+ return QtOrderingTypeFlag(flags
+ | QtOrderingPrivate::orderingFlagsFor(QtOrderingPrivate::to_Qt(t)));
+}
} // namespace QtOrderingPrivate
/*
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index 9a00b0b2006..cd835f548c0 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -511,6 +511,46 @@ void QDebug::putUInt128([[maybe_unused]] const void *p)
stream->ts << int128Warning();
}
+/*!
+ \since 6.9
+ \internal
+ Helper to the <Std/Qt>::<>_ordering debug output.
+ It generates the string in following format:
+ <Qt/Std>::<weak/partial/strong>_ordering::<less/equal/greater/unordered>
+ */
+void QDebug::putQtOrdering(QtOrderingPrivate::QtOrderingTypeFlag flags, Qt::partial_ordering order)
+{
+ using QtOrderingPrivate::QtOrderingType;
+ std::string result;
+ if ((flags & QtOrderingType::StdOrder) == QtOrderingType::StdOrder)
+ result += "std";
+ else if ((flags & QtOrderingType::QtOrder) == QtOrderingType::QtOrder)
+ result += "Qt";
+
+ result += "::";
+ const bool isStrong = ((flags & QtOrderingType::Strong) == QtOrderingType::Strong);
+ if (isStrong)
+ result += "strong";
+ else if ((flags & QtOrderingType::Weak) == QtOrderingType::Weak)
+ result += "weak";
+ else if ((flags & QtOrderingType::Partial) == QtOrderingType::Partial)
+ result += "partial";
+ result += "_ordering::";
+
+ if (order == Qt::partial_ordering::equivalent) {
+ if (isStrong)
+ result += "equal";
+ else
+ result += "equivalent";
+ } else if (order == Qt::partial_ordering::greater) {
+ result += "greater";
+ } else if (order == Qt::partial_ordering::less) {
+ result += "less";
+ } else {
+ result += "unordered";
+ }
+ stream->ts << result.data();
+}
/*!
\fn QDebug::swap(QDebug &other)
@@ -949,6 +989,15 @@ QDebug &QDebug::resetFormat()
*/
/*!
+ \fn template <typename T, QDebug::if_ordering_type<T>> QDebug::operator<<(QDebug debug, T t)
+ \since 6.9
+ Prints the Qt or std ordering value \a t to the \a debug object.
+
+ \note This function only participates in overload resolution if \c T
+ is one of <Qt/Std>::<weak/partial/strong>_ordering.
+*/
+
+/*!
\since 6.5
\fn template <typename Char, typename...Args> QDebug &QDebug::operator<<(const std::basic_string<Char, Args...> &s)
\fn template <typename Char, typename...Args> QDebug &QDebug::operator<<(std::basic_string_view<Char, Args...> s)
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 03f0886304a..f941bf40cb0 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -9,6 +9,7 @@
#pragma qt_class(QtDebug)
#endif
+#include <QtCore/qcompare.h>
#include <QtCore/qcontainerfwd.h>
#include <QtCore/qtextstream.h>
#include <QtCore/qttypetraits.h>
@@ -79,6 +80,8 @@ class QT6_ONLY(Q_CORE_EXPORT) QDebug : public QIODeviceBase
QT7_ONLY(Q_CORE_EXPORT) void putTimeUnit(qint64 num, qint64 den);
QT7_ONLY(Q_CORE_EXPORT) void putInt128(const void *i);
QT7_ONLY(Q_CORE_EXPORT) void putUInt128(const void *i);
+ QT7_ONLY(Q_CORE_EXPORT) void putQtOrdering(QtOrderingPrivate::QtOrderingTypeFlag flags,
+ Qt::partial_ordering order);
public:
explicit QDebug(QIODevice *device) : stream(new Stream(device)) {}
explicit QDebug(QString *string) : stream(new Stream(string)) {}
@@ -250,6 +253,17 @@ public:
{
return toBytesImpl(&streamTypeErased<T>, std::addressof(object));
}
+
+private:
+ template <typename T>
+ using if_ordering_type = std::enable_if_t<QtOrderingPrivate::is_ordering_type_v<T>, bool>;
+
+ template <typename T, if_ordering_type<T> = true>
+ friend QDebug operator<<(QDebug debug, T t)
+ {
+ debug.putQtOrdering(QtOrderingPrivate::orderingFlagsFor(t), Qt::partial_ordering(t));
+ return debug;
+ }
};
Q_DECLARE_SHARED(QDebug)
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
index 9d9fc853ddf..8bc2985a46d 100644
--- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
+++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
@@ -4,6 +4,7 @@
#include <QtCore/QCoreApplication>
+#include <QtCore/QtCompare>
#include <QtCore/QtDebug>
#include <QTest>
@@ -90,6 +91,7 @@ private slots:
void qDebugStdChrono_data() const;
void qDebugStdChrono() const;
void qDebugStdOptional() const;
+ void qDebugStdOrdering() const;
void textStreamModifiers() const;
void resetFormat() const;
void defaultMessagehandler() const;
@@ -1239,6 +1241,36 @@ void tst_QDebug::qDebugStdOptional() const
QCOMPARE(QString::fromLatin1(s_function), function);
}
+void tst_QDebug::qDebugStdOrdering() const
+{
+ QLatin1StringView file, function;
+ MessageHandlerSetter mhs(myMessageHandler);
+ {
+ QDebug d = qDebug();
+ d << Qt::partial_ordering::less
+ << Qt::partial_ordering::unordered
+ << Qt::weak_ordering::greater
+ << Qt::strong_ordering::equal;
+ }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = QLatin1StringView(__FILE__);
+ function = QLatin1StringView(Q_FUNC_INFO);
+#endif
+ const auto cmpStr = "Qt::partial_ordering::lessQt::partial_ordering::unorderedQt::weak_ordering::greaterQt::strong_ordering::equal"_L1;
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, cmpStr);
+#ifdef __cpp_lib_three_way_comparison
+ qDebug() << std::partial_ordering::less
+ << std::partial_ordering::unordered
+ << std::weak_ordering::greater
+ << std::strong_ordering::equal;
+ const auto stdStr = "std::partial_ordering::lessstd::partial_ordering::unorderedstd::weak_ordering::greaterstd::strong_ordering::equal"_L1;
+ QCOMPARE(s_msg, stdStr);
+#endif
+ QCOMPARE(QLatin1StringView(s_file), file);
+ QCOMPARE(QLatin1StringView(s_function), function);
+}
+
void tst_QDebug::textStreamModifiers() const
{
QString file, function;
diff --git a/tests/auto/testlib/tostring/tst_tostring.cpp b/tests/auto/testlib/tostring/tst_tostring.cpp
index 8d3c59f2578..df99f96f458 100644
--- a/tests/auto/testlib/tostring/tst_tostring.cpp
+++ b/tests/auto/testlib/tostring/tst_tostring.cpp
@@ -4,6 +4,7 @@
#include <QTest>
#include <QtCore/qtypes.h>
+#include <QtCore/qcompare.h>
#include <memory>
@@ -21,6 +22,9 @@ private slots:
void chrono_duration_data();
void chrono_duration() { testRows(); }
+
+ void orderingTypeValue_data();
+ void orderingTypeValue() { testRows(); }
};
void tst_toString::addColumns()
@@ -211,5 +215,38 @@ void tst_toString::chrono_duration_data()
#endif
}
+void tst_toString::orderingTypeValue_data()
+{
+ addColumns();
+#define CHECK(x) ADD_ROW(#x, x, #x)
+ CHECK(Qt::strong_ordering::equal);
+ CHECK(Qt::strong_ordering::less);
+ CHECK(Qt::strong_ordering::greater);
+
+ CHECK(Qt::partial_ordering::equivalent);
+ CHECK(Qt::partial_ordering::less);
+ CHECK(Qt::partial_ordering::greater);
+ CHECK(Qt::partial_ordering::unordered);
+
+ CHECK(Qt::weak_ordering::equivalent);
+ CHECK(Qt::weak_ordering::less);
+ CHECK(Qt::weak_ordering::greater);
+#ifdef __cpp_lib_three_way_comparison
+ CHECK(std::strong_ordering::equal);
+ CHECK(std::strong_ordering::less);
+ CHECK(std::strong_ordering::greater);
+
+ CHECK(std::partial_ordering::equivalent);
+ CHECK(std::partial_ordering::less);
+ CHECK(std::partial_ordering::greater);
+ CHECK(std::partial_ordering::unordered);
+
+ CHECK(std::weak_ordering::equivalent);
+ CHECK(std::weak_ordering::less);
+ CHECK(std::weak_ordering::greater);
+#endif // __cpp_lib_three_way_comparison
+#undef CHECK
+}
+
QTEST_APPLESS_MAIN(tst_toString)
#include "tst_tostring.moc"