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>
|
template <typename T>
|
||||||
typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
|
typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
|
||||||
operator<<(QDataStream &s, const T &t)
|
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>
|
template <typename T>
|
||||||
typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
|
typename std::enable_if_t<std::is_enum<T>::value, QDataStream &>
|
||||||
operator>>(QDataStream &s, T &t)
|
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
|
#ifndef Q_QDOC
|
||||||
|
|
||||||
|
@ -3697,6 +3697,41 @@ void tst_QDataStream::enumTest()
|
|||||||
}
|
}
|
||||||
ba.clear();
|
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()
|
void tst_QDataStream::floatingPointPrecision()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user