diff --git a/src/corelib/serialization/qdatastream.h b/src/corelib/serialization/qdatastream.h index 2a5622f6030..71f2f4bbd9b 100644 --- a/src/corelib/serialization/qdatastream.h +++ b/src/corelib/serialization/qdatastream.h @@ -525,12 +525,21 @@ inline QDataStream &operator>>(QDataStream &s, QFlags &e) template typename std::enable_if_t::value, QDataStream &> operator<<(QDataStream &s, const T &t) -{ return s << static_cast::type>(t); } +{ + // std::underlying_type_t may be long or ulong, for which QDataStream + // provides no streaming operators. For those, cast to qint64 or quint64. + return s << typename QIntegerForSizeof::Unsigned(t); +} template typename std::enable_if_t::value, QDataStream &> operator>>(QDataStream &s, T &t) -{ return s >> reinterpret_cast::type &>(t); } +{ + typename QIntegerForSizeof::Unsigned i; + s >> i; + t = T(i); + return s; +} #ifndef Q_QDOC diff --git a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp index 9a227c782de..0ff70ffb29a 100644 --- a/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp +++ b/tests/auto/corelib/serialization/qdatastream/tst_qdatastream.cpp @@ -3697,6 +3697,41 @@ void tst_QDataStream::enumTest() } ba.clear(); + enum class E5 : qint64 + { + A, + B, + C + }; + { + QDataStream stream(&ba, QIODevice::WriteOnly); + stream << E5::C; + QCOMPARE(ba.size(), int(sizeof(E5))); + } + { + QDataStream stream(ba); + E5 e; + stream >> e; + QCOMPARE(e, E5::C); + } + ba.clear(); + + // unlike regular streaming operators, we accept long and ulong, because + // usually the only reason people see them is because they have + // std::(u)int64_t underlying types. + enum class ELong : long { A, B, C }; + { + QDataStream stream(&ba, QIODevice::WriteOnly); + stream << ELong::A; + QCOMPARE(ba.size(), sizeof(long)); + } + { + QDataStream stream(ba); + ELong e; + stream >> e; + QCOMPARE(e, ELong::A); + } + ba.clear(); } void tst_QDataStream::floatingPointPrecision()