Есть ли способ сериализации автоматически перечисления как int? - PullRequest
2 голосов
/ 15 апреля 2010

Есть ли способ автоматически сериализовать перечисления как int? Каждый раз, когда я определяю новое перечисление и пишу

std::stringstream stream;
stream << myenum1;
stream >> myenum2;

компилятор жалуется, что операторы << и >> не определены. Знаете ли вы, как сказать компилятору обрабатывать перечисления как простые int?

Проблема осложняется тем, что сериализация внутри шаблона. Как то так:

template <typename T>
void serialize(const T& value)
{
    std::stringstream stream;
    stream << value;
}

Так что я не могу добавить любые приведения :( Может быть, я могу как-то это специализировать?

Спасибо.

Ответы [ 5 ]

4 голосов
/ 15 апреля 2010

Вы можете узнать, является ли тип enum с помощью TypeTraits Boost ( is_enum ).

Затем вы можете объединить это с enable_if / disable_if:

template <class T>
typename boost::disable_if<boost::is_enum<T> >::type serialize(const T&);

template <class T>
typename boost::enable_if<boost::is_enum<T> >::type serialize(const T&); //use casts here

Однако невозможно будет проверить, является ли данное значение допустимым для данного перечисления (если вы не напишите конкретную перегрузку для данного типа перечисления).

3 голосов
/ 15 апреля 2010

Для вывода оператор << переведет любой тип перечисления в ближайшее соответствие int или long. (§5.8 / 1, 4.5 / 2) У вас не должно быть никаких проблем, и я не смог бы создать ни одного с GCC или Comeau. Поправь меня, если я ошибаюсь.

Для ввода вы можете написать шаблонную функцию и отключить неявное создание экземпляров, скрыв ее внутри только явно созданного класса.

template< class E >
struct enum_traits {
    friend std::istream &operator>> ( std::istream &is, E &e ) {
        long i; // or intmax_t, whatever
        std::istream &r = is >> i;
        e = E( i );
        return r;
    }
};

enum my_enum { a, b, c };
template class enum_traits< my_enum >; // explicit instantiation
   // "matching declaration" per 7.3.1.2/3:
std::istream &operator>> ( std::istream &, my_enum & );

Это проходит GCC и Comeau. Я не могу найти способ обернуть пространства имен и ADL, чтобы сделать его более удобным. (Единственное альтернативное решение предполагает использование объявления для каждого перечислителя.)

Но два шаблонных объявления можно заключить в макрос, или в любом случае они лучше, чем переписать всю функцию заново!

1 голос
/ 15 апреля 2010

Знаете ли вы, как сказать компилятору обрабатывать перечисления как простые int?

Это невозможно (по крайней мере, для >>), так как это было бы небезопасно (присвоение int для enum небезопасно).

Одна вещь, которую вы можете сделать, это предоставить ваши перегрузки операторов >> и << для каждого перечисления, которое будет выполнять приведение за вас. Это то, что вы будете делать для каждого перечисления один раз, что звучит намного лучше, чем при приведении к каждому месту, где вы используете >> / << (что здесь особенно удобно, поскольку вы не можете редактировать места, где используются эти операторы) . </p>

1 голос
/ 15 апреля 2010

Вы пытались привести перечисления к целым числам, например, static_cast<int>(enumX)?

0 голосов
/ 15 апреля 2010

Будет лучше с C ++ 0x, так как вы сможете указать базовый тип (например, unsigned short).

Пока вы должны использовать соглашение, например, предполагая, что все ваши значения перечисления могут быть сохранены в int, вы можете сериализовать и десериализовать его как int, а затем преобразовать обратно.

Другой проблемой, конечно же, является ваша процедура сериализации:

std::stringstream stream;
stream << 1 << 2;
int a;
stream >> a;
assert(a == 12);

Обычно сериализация включает в себя некоторое двоичное представление известного размера (или сериализацию размера вдоль него). Если вы не хотите заниматься этим самостоятельно, есть библиотеки:

  • Boost.Serialization
  • Google.ProtocolBuffers

И у обоих есть простой текст и двоичное представление (и простой текст намного легче отлаживать).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...