(反序列化一个枚举类

时间:2019-01-05 19:00:56

标签: c++ enum-class

我正在尝试对QDataStream变量进行序列化和反序列化(使用enum class,但这在这里无关紧要)

enum class Type : char
{
    Trivial,
    Complex
};

序列化很容易:

QDataStream &operator<<(QDataStream &stream, Type type)
{
    return stream << static_cast<char>(type);
}

但是反序列化不是:

QDataStream &operator>>(QDataStream &stream, Type &type)
{    
    return stream >> static_cast<char &>(type);
}

显然,不允许引用static_cast的{​​{1}}引用其基础类型。此外,“显而易见的”解决方案:

enum class

实际上可能是非法的,没有被标准according to the answer to this question定义,因为等效表达式QDataStream &operator>>(QDataStream &stream, Type &type) { return stream >> reinterpret_cast<char &>(type); } 在这里被声明为非法(或者不是由标准定义)。如果是这种情况,我需要这样做:

return stream >> (*static_cast<char *>(static_cast<void *>(&type)));

这不是很漂亮,是4行而不是1行,等等。对于这样的(看似)简单的事情,对我来说似乎没有必要。

我的问题:QDataStream &operator>>(QDataStream &stream, Type &type) { char c = 0; stream >> c; type = static_cast<Type>(c); return stream; } 变量的引用转换为引用时,通过reinterpret_cast的{​​{1}}或等效static_cast是否真的非法(标准未定义)?的基础类型?

2 个答案:

答案 0 :(得分:3)

您可以编写一个模板函数,该函数允许您为定义的每个operator>>写1行。

template <class UT, class S, class E> S& DeserializeEnumClassValue(S &s, E &e)
{
    UT temp;
    s >> temp;
    e = static_cast<E>(temp);
    return s;
}

并像这样使用它:

QDataStream &operator>>(QDataStream &stream, Type &type)
{    
    return DeserializeEnumClassValue<char>(stream, value);
}

但是可以使用std :: underlying_type(https://en.cppreference.com/w/cpp/types/underlying_type)进行改进,因为可以在编译时获取它。

如果采用这种方法,那么还应该对operator<<做类似的事情,以使维护更加容易。

答案 1 :(得分:0)

我得到以下解决方案:

template <typename T>
typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
operator<<(QDataStream &s, const T &t)
{ return s << static_cast<typename std::underlying_type<T>::type>(t); }

template <typename T>
typename std::enable_if<std::is_enum<T>::value, QDataStream &>::type&
operator>>(QDataStream &s, T &t)
{ return s >> reinterpret_cast<typename std::underlying_type<T>::type &>(t); }

来自github的人,并在src中得到验证。

我觉得人们经常陷入语言的陷阱而无法自拔,如果你用手工填写机器代码,那没问题,如果你没记错的话。提出一个反例,希望有些方便,并且可以容忍可能的错误,请执行此操作。否则,请使用最安全的方法。