C++ Cereal: сериализовать массив в стиле C

Можно ли/как сериализовать массив с помощью библиотеки cereal.

I.e.

void save(Archive & ar, const unsigned int version) const
{
    unsigned int l  = g1_size_bin(g,POINT_COMPRESS);
    uint8_t data[l];
    memset(data, 0, l);
    g1_write_bin(data, l, g,POINT_COMPRESS);
    ar(l);
    ar(data); // what should be here
}

Это не работает (и я бы этого тоже не ожидал). И не

ar(cereal::binary_data(data,l)); 

(что, я думаю, сработает, так как это похоже на код повышения, который можно было бы использовать), что приводит к ошибке компиляции:

/usr/local/include/cereal/cereal.hpp:79:17: примечание: шаблон-кандидат игнорируется: ошибка замены: изменяемый тип 'unsigned char (&)[l]' не может использоваться в качестве аргумента шаблона BinaryData binary_data( T && данные, size_t размер )

И не

ar.saveBinaryValue(data,l);

Поскольку этот метод поддерживается только для XML/Json, и мне нужен двоичный архив.


person imichaelmiers    schedule 17.12.2014    source источник


Ответы (1)


cereal::binary_data — правильная конструкция для использования в этом случае, если вы хотите двоичное представление массива POD. Это будет работать только для архивов, поддерживающих binary_data (бинарные и переносимые_бинарные). binary_data не работает для текстовых архивов, потому что он рассматривается как оптимизация для более общего метода сериализации - посмотрите, как сериализуется вектор для примера.

В любом случае, вот рабочий пример сериализации массива в стиле C:

#include <cereal/archives/binary.hpp>
#include <iostream>

int main()
{
  std::stringstream ss;

  {
    cereal::BinaryOutputArchive ar(ss);
    std::uint8_t data[] = {1, 2, 3};
    ar( cereal::binary_data( data, sizeof(std::uint8_t) * 3 ) );
  }

  {
    cereal::BinaryInputArchive ar(ss);
    std::uint8_t data[3];
    ar( cereal::binary_data( data, sizeof(std::uint8_t) * 3 ) );

    for( int i : data )
      std::cout << i << " ";
  }

  return 0;
}

Если вы хотите сериализовать массив в стиле C в текстовый архив или если ваш массив не относится к типам POD, вам нужно будет выполнить итерацию по каждому объекту и сериализовать его по отдельности.

person Azoth    schedule 02.01.2015
comment
У меня есть массив (в куче), который содержит N структур 2x double внутри (x и y). Должен ли я повторять каждую для сериализации? - person ColdSteel; 22.10.2016
comment
Этот код будет выглядеть лучше, если вы переименуете ar в a. - person Hi-Angel; 02.12.2017
comment
Я искал другую вещь, связанную с сериализацией и cereal, и наткнулся на этот ответ. У меня есть вопрос. ss по умолчанию имеет только режим std::ios_base::in | std::ios_base::out. это не создаст проблем? разве он не должен иметь std::ios_base::binary открытый режим? - person Arda Aytekin; 25.04.2018
comment
@ArdaAytekin Вы правы - в целях безопасности (и, к сожалению, гораздо более подробно), std::ios_base::binary следует указывать вместе с соответствующими входными или выходными флагами. - person Azoth; 06.06.2018
comment
Зерновые отличные. Но как жаль, что разные архивы предоставляют разные интерфейсы. Теперь мой код должен знать тип архива. Есть ли единый интерфейс? - person Sergei; 17.11.2019