(Де) сериализация класса enum - PullRequest
0 голосов
/ 05 января 2019

Я пытаюсь сериализовать и десериализовать (используя 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_cast через void* действительно недопустимым (не определенным стандартом) при приведении ссылки на переменную enum class к ссылке на ее базовый тип?

1 Ответ

0 голосов
/ 05 января 2019

Вы можете написать шаблонную функцию, которая позволит вам написать 1 строку для каждого operator>>, который вы определяете.

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 :: under_type (https://en.cppreference.com/w/cpp/types/underlying_type), так как это возможно получить во время компиляции.

Если вы воспользуетесь этим подходом, то вам также следует сделать нечто подобное для operator<<, чтобы упростить обслуживание.

...