From 08320bfe2b7387d6f488d405dddf9d3aba6434ec Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 21 Oct 2024 15:01:13 +0200 Subject: [PATCH] QDebug: make std::optional stream operator SCARY Piggy-back on the recently-added, type-erased, std::tuple stream operator to handle std::optional the same way. While std::optional doesn't support the Tuple Protocol, and we therefore can't use putTuple() directly, we can still use putTupleImplImpl() if we set up its arguments manually. [ChangeLog][Potentially Source-Incompatible Changes][QDebug] The std::optional streaming operator is now a member of QDebug, not a free function. This breaks users that rely on the exact definition of the operator (e.g. `operator<<(d, opt)`). A backwards-compatible fix is to call the operator with infix notation (d << opt) only, and to avoid const QDebug objects. Pick-to: 6.9 Change-Id: Ib040d65953ca9d3892aee5bdb597d6d30a9694b1 Reviewed-by: Ivan Solovev --- src/corelib/io/qdebug.cpp | 5 ++--- src/corelib/io/qdebug.h | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index 1fb2addc9ed..fc70e066f78 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -1258,10 +1258,9 @@ QDebug &QDebug::putTupleLikeImplImpl(const char *ns, const char *what, /*! \since 6.7 - \fn template QDebug operator<<(QDebug debug, const std::optional &opt) - \relates QDebug + \fn template > QDebug::operator<<(const std::optional &opt) - Writes the contents of \a opt (or \c nullopt if not set) to \a debug. + Writes the contents of \a opt (or \c nullopt if not set) to this stream. \c T needs to support streaming into QDebug. */ diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h index 7dc6155259e..02628bc5cd6 100644 --- a/src/corelib/io/qdebug.h +++ b/src/corelib/io/qdebug.h @@ -299,6 +299,16 @@ public: return putTupleLike("std", "tuple", t); } + template = true> + QDebug &operator<<(const std::optional &o) + { + if (!o) + return *this << std::nullopt; + StreamTypeErased s = &streamTypeErased>; + const void *d = std::addressof(*o); + return putTupleLikeImplImpl("std", "optional", 1, &s, &d); + } + private: template using if_ordering_type = std::enable_if_t, bool>; @@ -490,16 +500,6 @@ inline QDebugIfHasDebugStreamContainer, Key, T> operator<<(QD return QtPrivate::printAssociativeContainer(std::move(debug), "QMultiHash", hash); } -template -inline QDebugIfHasDebugStream operator<<(QDebug debug, const std::optional &opt) -{ - if (!opt) - return debug << std::nullopt; - const QDebugStateSaver saver(debug); - debug.nospace() << "std::optional(" << *opt << ')'; - return debug; -} - template inline QDebugIfHasDebugStream operator<<(QDebug debug, const std::pair &pair) {