由于我在尝试将enum Type : quint8 {...} 流式传输到QSettings 和从QSettings 流式传输时发现了这一点,所以这里有两种方式来确保完整性。
template<class T, typename std::enable_if<std::is_enum<T>::value, T>::type* = nullptr>
QDataStream &operator<<(QDataStream& stream, const T &enumValue)
{
return stream << static_cast<std::underlying_type_t<T>>(enumValue);
}
template<class T, typename std::enable_if<std::is_enum<T>::value, T>::type* = nullptr>
QDataStream &operator>>(QDataStream& stream, T &enumValue)
{
std::underlying_type_t<T> val;
stream >> val;
enumValue = static_cast<T>(val);
return stream;
}
对于QSettings,enum 类型也必须在 Qt 元对象系统中注册流操作符。枚举使用Q_ENUM()(在QObject 或Q_GADGET)或Q_ENUM_NS()(在命名空间中)注册,或者在其他情况下使用QT_DECLARE_METATYPE() 注册。流操作符需要单独注册qRegisterMetaTypeStreamOperators<Type>("Type")。另请注意,对于 QFlags,已经定义了流式操作符,但 AFAIK 仍然需要向 qRegisterMetaTypeStreamOperators 注册才能自动进行流式传输。
更新:
带有 C++14 的 MSVC17 不喜欢我上面的代码,所以根据@DrumM 的回答,这就是现在对我有用的方法,MinGW 7.3、gcc 6.3 和 7.3:
template <typename T>
typename std::enable_if<std::is_enum<T>::value, QDataStream&>::type
operator<<(QDataStream& stream, const T &enumValue)
{
return stream << static_cast<std::underlying_type_t<T>>(enumValue);
}
template <typename T>
typename std::enable_if<std::is_enum<T>::value, QDataStream&>::type
operator>>(QDataStream& stream, T &enumValue)
{
std::underlying_type_t<T> val;
stream >> val;
enumValue = static_cast<T>(val);
return stream;
}
// ... later
qRegisterMetaTypeStreamOperators<MyScope::MyEnum>("MyScope::MyEnum");