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>
This commit is contained in:
Tatiana Borisova 2024-07-11 12:20:26 +02:00 committed by Marc Mutz
parent 1442a9ea47
commit 2aa39be4c2
5 changed files with 184 additions and 2 deletions

View File

@ -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
/*

View File

@ -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)
@ -948,6 +988,15 @@ QDebug &QDebug::resetFormat()
\internal
*/
/*!
\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)

View File

@ -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)

View File

@ -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;

View File

@ -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"