QDebug: refactor streaming of sequential containers and add suppoprt for STL types

What triggered this change was the use of QVector::toList() in
op<<(QDebug, QVector).

Only added support for STL types of which we already include the
headers.

[ChangeLog][QtCore][QDebug] Can now output std::vector, std::list,
std::map, and std::multimap.

Change-Id: I49581e3038daa7626b00169430b72d3d5175eae7
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
Marc Mutz 2015-06-24 14:54:54 +02:00
parent bfdcbe8bfb
commit 88d7c8f963
2 changed files with 98 additions and 15 deletions

View File

@ -703,6 +703,15 @@ QDebug &QDebug::resetFormat()
support streaming into QDebug.
*/
/*!
\fn QDebug operator<<(QDebug stream, const std::list<T, Alloc> &list)
\relates QDebug
\since 5.7
Writes the contents of \a list to \a stream. \c T needs to
support streaming into QDebug.
*/
/*!
\fn QDebug operator<<(QDebug stream, const QVector<T> &vector)
\relates QDebug
@ -711,6 +720,15 @@ QDebug &QDebug::resetFormat()
support streaming into QDebug.
*/
/*!
\fn QDebug operator<<(QDebug stream, const std::vector<T, Alloc> &vector)
\relates QDebug
\since 5.7
Writes the contents of \a vector to \a stream. \c T needs to
support streaming into QDebug.
*/
/*!
\fn QDebug operator<<(QDebug stream, const QSet<T> &set)
\relates QDebug
@ -727,6 +745,24 @@ QDebug &QDebug::resetFormat()
\c T need to support streaming into QDebug.
*/
/*!
\fn QDebug operator<<(QDebug stream, const std::map<Key, T, Compare, Alloc> &map)
\relates QDebug
\since 5.7
Writes the contents of \a map to \a stream. Both \c Key and
\c T need to support streaming into QDebug.
*/
/*!
\fn QDebug operator<<(QDebug stream, const std::multimap<Key, T, Compare, Alloc> &map)
\relates QDebug
\since 5.7
Writes the contents of \a map to \a stream. Both \c Key and
\c T need to support streaming into QDebug.
*/
/*!
\fn QDebug operator<<(QDebug stream, const QHash<Key, T> &hash)
\relates QDebug

View File

@ -45,6 +45,12 @@
#include <QtCore/qset.h>
#include <QtCore/qcontiguouscache.h>
// all these have already been included by various headers above, but don't rely on indirect includes:
#include <vector>
#include <list>
#include <map>
#include <utility>
QT_BEGIN_NAMESPACE
@ -192,28 +198,63 @@ inline QDebug &QDebug::operator=(const QDebug &other)
return *this;
}
template <class T>
inline QDebug operator<<(QDebug debug, const QList<T> &list)
namespace QtPrivate {
template <typename SequentialContainer>
inline QDebug printSequentialContainer(QDebug debug, const char *which, const SequentialContainer &c)
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << '(';
for (typename QList<T>::size_type i = 0; i < list.count(); ++i) {
if (i)
debug << ", ";
debug << list.at(i);
debug.nospace() << which << '(';
typename SequentialContainer::const_iterator it = c.begin(), end = c.end();
if (it != end) {
debug << *it;
++it;
}
while (it != end) {
debug << ", " << *it;
++it;
}
debug << ')';
debug.setAutoInsertSpaces(oldSetting);
return debug.maybeSpace();
}
} // namespace QtPrivate
template <class T>
inline QDebug operator<<(QDebug debug, const QList<T> &list)
{
return QtPrivate::printSequentialContainer(debug, "" /*for historical reasons*/, list);
}
template <typename T>
inline QDebug operator<<(QDebug debug, const QVector<T> &vec)
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QVector";
debug.setAutoInsertSpaces(oldSetting);
return operator<<(debug, vec.toList());
return QtPrivate::printSequentialContainer(debug, "QVector", vec);
}
template <typename T, typename Alloc>
inline QDebug operator<<(QDebug debug, const std::vector<T, Alloc> &vec)
{
return QtPrivate::printSequentialContainer(debug, "std::vector", vec);
}
template <typename T, typename Alloc>
inline QDebug operator<<(QDebug debug, const std::list<T, Alloc> &vec)
{
return QtPrivate::printSequentialContainer(debug, "std::list", vec);
}
template <typename Key, typename T, typename Compare, typename Alloc>
inline QDebug operator<<(QDebug debug, const std::map<Key, T, Compare, Alloc> &map)
{
return QtPrivate::printSequentialContainer(debug, "std::map", map); // yes, sequential: *it is std::pair
}
template <typename Key, typename T, typename Compare, typename Alloc>
inline QDebug operator<<(QDebug debug, const std::multimap<Key, T, Compare, Alloc> &map)
{
return QtPrivate::printSequentialContainer(debug, "std::multimap", map); // yes, sequential: *it is std::pair
}
template <class Key, class T>
@ -252,13 +293,19 @@ inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair)
return debug.maybeSpace();
}
template <class T1, class T2>
inline QDebug operator<<(QDebug debug, const std::pair<T1, T2> &pair)
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "std::pair(" << pair.first << ',' << pair.second << ')';
debug.setAutoInsertSpaces(oldSetting);
return debug.maybeSpace();
}
template <typename T>
inline QDebug operator<<(QDebug debug, const QSet<T> &set)
{
const bool oldSetting = debug.autoInsertSpaces();
debug.nospace() << "QSet";
debug.setAutoInsertSpaces(oldSetting);
return operator<<(debug, set.toList());
return QtPrivate::printSequentialContainer(debug, "QSet", set);
}
template <class T>