QDataStream: allow streaming of enums backed by long and unsigned long
On Unix 64-bit platforms (LP64), compilers will use long and unsigned long as the underlying type of 64-bit enumerations without explicit type, such as: enum E { V = 0x1'0000'0000 }; User code may also explicitly choose std::int64_t or std::uint64_t, which on those platforms map to long and unsigned long, respectively. Likewise std::ptrdiff_t and std::size_t, which are the same. This means we do allow streaming of enums with explicit long and unsigned long types, such as: enum ELong : long { A, B, C }; which change sizes between platforms. [ChangeLog][QtCore][QDataStream] QDataStream now supports streaming enumerations whose underlying type is long or unsigned long (like std::int64_t, std::uint64_t, ptrdiff_t, size_t on 64-bit Unix platforms). Fixes: QTBUG-86424 Change-Id: I34ef9422a252ce3df468fffd4ba074cddea20005 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
b387537d3e
commit
0c010cd9c7
@ -525,12 +525,21 @@ inline QDataStream &operator>>(QDataStream &s, QFlags<Enum> &e)
|
||||
template <typename T>
|
||||
typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
|
||||
operator<<(QDataStream &s, const T &t)
|
||||
{ return s << static_cast<typename std::underlying_type<T>::type>(t); }
|
||||
{
|
||||
// std::underlying_type_t<T> may be long or ulong, for which QDataStream
|
||||
// provides no streaming operators. For those, cast to qint64 or quint64.
|
||||
return s << typename QIntegerForSizeof<T>::Unsigned(t);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
|
||||
operator>>(QDataStream &s, T &t)
|
||||
{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }
|
||||
{
|
||||
typename QIntegerForSizeof<T>::Unsigned i;
|
||||
s >> i;
|
||||
t = T(i);
|
||||
return s;
|
||||
}
|
||||
|
||||
#ifndef Q_QDOC
|
||||
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user