From a9fe57fefaac0cb047e4c02e0b8c8f8327e0a58c Mon Sep 17 00:00:00 2001 From: Dheerendra Purohit Date: Fri, 18 Oct 2024 18:34:42 +0530 Subject: [PATCH] QDebug: add streaming operators for std::unordered_map The stream insertion operator for QDebug is not overloaded to handle std::unordered_map Overload the stream insertion operator for QDebug to handle std::unordered_map [ChangeLog][QtCore][QDebug] Added support for std::unordered_map. Fixes: QTBUG-130290 Change-Id: I96e82f90c310dcac4a6e4d35651fb1adb6d6293a Reviewed-by: Thiago Macieira --- src/corelib/io/qdebug.cpp | 9 +++++ src/corelib/io/qdebug.h | 7 ++++ tests/auto/corelib/io/qdebug/tst_qdebug.cpp | 43 +++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index d4cc46dbe42..970fe15a776 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -1188,6 +1188,15 @@ QDebug &QDebug::putTupleLikeImplImpl(const char *ns, const char *what, \c T need to support streaming into QDebug. */ +/*! + \fn template QDebug operator<<(QDebug debug, const std::unordered_map &unordered_map) + \relates QDebug + \since 6.9 + + Writes the contents of \a map to \a debug. Both \c Key and + \c T need to support streaming into QDebug. +*/ + /*! \fn template QDebug operator<<(QDebug debug, const QHash &hash) \relates QDebug diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 41ada051d72..3fc63552953 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #if !defined(QT_LEAN_HEADERS) || QT_LEAN_HEADERS < 1 @@ -436,6 +437,12 @@ inline QDebugIfHasDebugStream operator<<(QDebug debug, const std::multim return QtPrivate::printSequentialContainer(std::move(debug), "std::multimap", map); // yes, sequential: *it is std::pair } +template +inline QDebug operator<<(QDebug debug, const std::unordered_map &unordered_map) +{ + return QtPrivate::printSequentialContainer(std::move(debug), "std::unordered_map", unordered_map); // yes, sequential: *it is std::pair +} + template inline QDebugIfHasDebugStreamContainer, Key, T> operator<<(QDebug debug, const QMap &map) { diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp index 6c6ab7aa87b..3d1617fff21 100644 --- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp +++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp @@ -26,6 +26,7 @@ namespace pmr = std::pmr; namespace pmr = std; #endif #include +#include using namespace std::chrono; using namespace q20::chrono; @@ -36,6 +37,7 @@ static_assert(QTypeTraits::has_ostream_operator_v); static_assert(QTypeTraits::has_ostream_operator_v>); static_assert(QTypeTraits::has_ostream_operator_v>); static_assert(QTypeTraits::has_ostream_operator_v>>); +static_assert(QTypeTraits::has_ostream_operator_v>); struct NonStreamable {}; static_assert(!QTypeTraits::has_ostream_operator_v); static_assert(!QTypeTraits::has_ostream_operator_v>); @@ -84,6 +86,7 @@ private slots: void qDebugQLatin1String() const; void qDebugStdPair() const; void qDebugStdTuple() const; + void qDebugStdUnorderedMap() const; void qDebugStdString() const; void qDebugStdStringView() const; void qDebugStdWString() const; @@ -770,6 +773,46 @@ void tst_QDebug::qDebugStdTuple() const } } +void tst_QDebug::qDebugStdUnorderedMap() const +{ + QByteArray file, function; + int line = 0; + MessageHandlerSetter mhs(myMessageHandler); + + { + QDebug d = qDebug(); + std::unordered_map unorderedMap{{1, "One"}, {2, "Two"}, {3, "Three"}}; + d.nospace().noquote() << unorderedMap; + } +#ifndef QT_NO_MESSAGELOGCONTEXT + file = __FILE__; line = __LINE__ - 5; function = Q_FUNC_INFO; +#endif + QCOMPARE(s_msgType, QtDebugMsg); + + QStringList expectedValues = {"std::unordered_map","std::pair(1, One)","std::pair(2, Two)","std::pair(3, Three)"}; + for (const QString &expextedValue : expectedValues) { + QVERIFY(s_msg.contains(expextedValue)); + } + QCOMPARE(s_file, file); + QCOMPARE(s_line, line); + QCOMPARE(s_function, function); + + { + qDebug() << std::unordered_map{{"quarter", 0.25f}, {"half", 0.5f}}; + } + + expectedValues= {"std::unordered_map","std::pair(\"quarter\", 0.25)","std::pair(\"half\", 0.5)"}; + for (const QString &expextedValue : expectedValues) { + QVERIFY(s_msg.contains(expextedValue)); + } + + { + qDebug()<< std::unordered_map {}; + } + + QCOMPARE(s_msg, "std::unordered_map()"_L1); +} + void tst_QDebug::qDebugStdString() const { QString file, function;