From 3ef8ec2ee187b949b3f6840ca03bcc0e814c00a9 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Mon, 6 Jul 2020 14:06:08 +0200 Subject: [PATCH] Constrain the data stream operators for containers Check that we can successfully instantiate the data stream operator for a container before we actually try. This is required so we can automate registration of debug stream operators with QMetaType. Change-Id: Ib100a5242470d7fc8067058cc4d81af2fa9354b0 Reviewed-by: Fabian Kosmale --- src/corelib/global/qtypeinfo.h | 11 ++++++ src/corelib/serialization/qdatastream.h | 35 +++++++++++-------- tests/auto/corelib/io/qdebug/tst_qdebug.cpp | 10 +++--- .../qdatastream/tst_qdatastream.cpp | 8 +++++ 4 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index 2f7bb414b54..e45347ee10f 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -464,6 +464,17 @@ struct has_ostream_operator constexpr bool has_ostream_operator_v = has_ostream_operator::value; +template +struct has_istream_operator : std::false_type {}; +template +struct has_istream_operator() >> detail::reference())>> + : std::true_type {}; +template +constexpr bool has_istream_operator_v = has_istream_operator::value; + +template +constexpr bool has_stream_operator_v = has_ostream_operator_v && has_istream_operator_v; + } diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h index d00fb5e7d86..48e96cb4c57 100644 --- a/src/corelib/serialization/qdatastream.h +++ b/src/corelib/serialization/qdatastream.h @@ -347,6 +347,13 @@ QDataStream &writeAssociativeMultiContainer(QDataStream &s, const Container &c) } // QtPrivate namespace +template +using QDataStreamIfHasOStreamOperators = + std::enable_if_t...>, QDataStream &>; +template +using QDataStreamIfHasIStreamOperators = + std::enable_if_t...>, QDataStream &>; + /***************************************************************************** QDataStream inline functions *****************************************************************************/ @@ -406,88 +413,88 @@ operator>>(QDataStream &s, T &t) { return s >> reinterpret_cast::type &>(t); } template -inline QDataStream &operator>>(QDataStream &s, QList &v) +inline QDataStreamIfHasIStreamOperators operator>>(QDataStream &s, QList &v) { return QtPrivate::readArrayBasedContainer(s, v); } template -inline QDataStream &operator<<(QDataStream &s, const QList &v) +inline QDataStreamIfHasOStreamOperators operator<<(QDataStream &s, const QList &v) { return QtPrivate::writeSequentialContainer(s, v); } template -inline QDataStream &operator>>(QDataStream &s, QSet &set) +inline QDataStreamIfHasIStreamOperators operator>>(QDataStream &s, QSet &set) { return QtPrivate::readListBasedContainer(s, set); } template -inline QDataStream &operator<<(QDataStream &s, const QSet &set) +inline QDataStreamIfHasOStreamOperators operator<<(QDataStream &s, const QSet &set) { return QtPrivate::writeSequentialContainer(s, set); } template -inline QDataStream &operator>>(QDataStream &s, QHash &hash) +inline QDataStreamIfHasIStreamOperators operator>>(QDataStream &s, QHash &hash) { return QtPrivate::readAssociativeContainer(s, hash); } template -inline QDataStream &operator<<(QDataStream &s, const QHash &hash) +inline QDataStreamIfHasOStreamOperators operator<<(QDataStream &s, const QHash &hash) { return QtPrivate::writeAssociativeContainer(s, hash); } template -inline QDataStream &operator>>(QDataStream &s, QMultiHash &hash) +inline QDataStreamIfHasIStreamOperators operator>>(QDataStream &s, QMultiHash &hash) { return QtPrivate::readAssociativeContainer(s, hash); } template -inline QDataStream &operator<<(QDataStream &s, const QMultiHash &hash) +inline QDataStreamIfHasOStreamOperators operator<<(QDataStream &s, const QMultiHash &hash) { return QtPrivate::writeAssociativeMultiContainer(s, hash); } template -inline QDataStream &operator>>(QDataStream &s, QMap &map) +inline QDataStreamIfHasIStreamOperators operator>>(QDataStream &s, QMap &map) { return QtPrivate::readAssociativeContainer(s, map); } template -inline QDataStream &operator<<(QDataStream &s, const QMap &map) +inline QDataStreamIfHasOStreamOperators operator<<(QDataStream &s, const QMap &map) { return QtPrivate::writeAssociativeContainer(s, map); } template -inline QDataStream &operator>>(QDataStream &s, QMultiMap &map) +inline QDataStreamIfHasIStreamOperators operator>>(QDataStream &s, QMultiMap &map) { return QtPrivate::readAssociativeContainer(s, map); } template -inline QDataStream &operator<<(QDataStream &s, const QMultiMap &map) +inline QDataStreamIfHasOStreamOperators operator<<(QDataStream &s, const QMultiMap &map) { return QtPrivate::writeAssociativeMultiContainer(s, map); } #ifndef QT_NO_DATASTREAM template -inline QDataStream& operator>>(QDataStream& s, std::pair &p) +inline QDataStreamIfHasIStreamOperators operator>>(QDataStream& s, std::pair &p) { s >> p.first >> p.second; return s; } template -inline QDataStream& operator<<(QDataStream& s, const std::pair &p) +inline QDataStreamIfHasOStreamOperators operator<<(QDataStream& s, const std::pair &p) { s << p.first << p.second; return s; diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp index 72412aa44d4..0b54f53517e 100644 --- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp +++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp @@ -35,11 +35,13 @@ #include #include -static_assert(QTypeTraits::has_ostream_v); -static_assert(QTypeTraits::has_ostream_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_v); -static_assert(!QTypeTraits::has_ostream_v>); +static_assert(!QTypeTraits::has_ostream_operator_v); +static_assert(!QTypeTraits::has_ostream_operator_v>); +static_assert(!QTypeTraits::has_ostream_operator_v>); class tst_QDebug: public QObject { diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp index 932c4d25d23..bd7100adec1 100644 --- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp +++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp @@ -36,6 +36,14 @@ #include #include +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>); +static_assert(!QTypeTraits::has_ostream_operator_v>); + class tst_QDataStream : public QObject { Q_OBJECT