首页 > 解决方案 > (反)序列化枚举类

问题描述

我正在尝试序列化和反序列化(使用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不允许enum class引用对其基础类型的引用。此外,“明显”的解决方案:

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

根据这个问题的答案,实际上可能是非法的并且没有由标准定义,因为等效的表达式return stream >> (*static_cast<char *>(static_cast<void *>(&type)));在那里被声明为非法(或者更确切地说不是由标准定义)。如果是这种情况,我需要这样做:

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

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

我的问题:当将对变量的引用转换为其基础类型的引用时,通过reinterpret_cast或等价的方式是否真的非法(标准未定义) ?static_castvoid*enum class

标签: c++qt5enum-classqdatastream

解决方案


您可以编写一个模板函数,允许您为每个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<<来使维护更容易。


推荐阅读