C++ Cereal save/load_and_construct не работает
Поэтому я пытаюсь использовать библиотеку Cereal и столкнулся с проблемой, которую, похоже, не могу решить. По сути, в документе говорится, что можно десериализовать типы без конструктора по умолчанию. Тем не менее, в заметках по реализации говорится Define a serialize or save/load pair as you normally would
все же параметры сериализации / загрузки не могут быть определены корректным образом, если нет конструктора по умолчанию. Я так понимаю, что load_and_construct
функция занимает место load
, Еще при реализации сравнительно простого примера видно ниже.
"Main.cpp"
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <memory>
#include <cereal/access.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/archives/portable_binary.hpp>
struct string_wrapper {
const std::string str;
string_wrapper(const std::string& _a) : str{_a} {}
template <class Archive>
void save(Archive& _archive) const {
_archive(str);
}
template <class Archive>
static void load_and_construct(Archive& _archive,
cereal::construct<string_wrapper>& _construct) {
std::string a;
_archive(a);
_construct(a);
}
};
struct wrapper_of_string_wrappers {
const std::vector<string_wrapper> strs;
wrapper_of_string_wrappers(
const std::vector<string_wrapper>& _a
) : strs{_a} { }
template <class Archive>
void save(Archive& _archive) const {
_archive(strs);
}
template <class Archive>
static void load_and_construct(Archive& _archive,
cereal::construct<wrapper_of_string_wrappers>& _construct) {
std::vector<string_wrapper> strs;
_archive(strs);
_construct(strs);
}
};
int main() {
auto file = "test.bin";
{ // save
std::ofstream os(file, std::ios::binary);
cereal::PortableBinaryOutputArchive archiveSave(os);
std::vector<string_wrapper> as;
as.push_back({"Hello"});
as.push_back({"World"});
wrapper_of_string_wrappers test(as);
auto test_ptr = std::make_unique<wrapper_of_string_wrappers>(test);
archiveSave(test_ptr);
}
{ // load
std::ifstream is(file, std::ios::binary);
cereal::PortableBinaryInputArchive archiveLoad(is);
std::unique_ptr<wrapper_of_string_wrappers> test = nullptr;
archiveLoad(test);
std::cout << (*test).strs[0].str << " " << (*test).strs[1].str << std::endl;
}
std::cin.get();
return 0;
}
Этот код явно бессмысленен, это лишь минимальный пример, иллюстрирующий проблему, с которой я сталкиваюсь.
1 ответ
Нестандартные конструкторы в настоящее время поддерживаются только для сериализации указателей
Ваша проблема здесь в том, что вы пытаетесь сериализовать не указатель значения без конструктора по умолчанию здесь
std::vector<string_wrapper> strs;
_archive(strs);
Чтобы решить вашу проблему, вам нужно сделать конструктор по умолчанию для string_wrapper
с save/load
пара или использование string_wrapper
как указатель в wrapper_of_string_wrappers
,
Вот рабочий код для второго варианта (string_wrapper
остается таким же)
struct wrapper_of_string_wrappers {
//const std::vector<std::unique_ptr<string_wrapper>> strs;
//const string_wrapper strs;
const std::unique_ptr<string_wrapper> strs;
wrapper_of_string_wrappers(
//const std::vector<std::unique_ptr<string_wrapper>>& _a
const string_wrapper _a
) : strs{ new string_wrapper(_a) } { }
wrapper_of_string_wrappers(
const wrapper_of_string_wrappers& w
) : strs{ new string_wrapper(*w.strs) } { }
template <class Archive>
void save(Archive& _archive) const {
_archive(strs);
}
template <class Archive>
static void load_and_construct(Archive& _archive,
cereal::construct<wrapper_of_string_wrappers>& _construct) {
//std::vector<std::unique_ptr<string_wrapper>> strs;
std::unique_ptr<string_wrapper> strs;
_archive(strs);
_construct(*strs);
}
};
int main() {
auto file = "test.bin";
{ // save
std::ofstream os(file, std::ios::binary);
cereal::PortableBinaryOutputArchive archiveSave(os);
string_wrapper as("Hello");
wrapper_of_string_wrappers test(as);
auto test_ptr = std::make_unique<wrapper_of_string_wrappers>(test);
archiveSave(test_ptr);
}
{ // load
std::ifstream is(file, std::ios::binary);
cereal::PortableBinaryInputArchive archiveLoad(is);
std::unique_ptr<wrapper_of_string_wrappers> test = nullptr;
archiveLoad(test);
std::cout << (*test).strs->str << std::endl;
}
std::cin.get();
return 0;
}