C ++谷类保存/ load_and_construct无法正常工作

时间:2018-07-26 03:26:51

标签: c++ cereal

因此,我正在尝试使用Cereal库,但遇到了一个我似乎无法克服的问题。从本质上说,文档称可以对Types with no default constructor进行反序列化。但是在实现说明中,它说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 个答案:

答案 0 :(得分:1)

来自this page

  

当前仅支持非默认构造函数来序列化指针

这里的问题是您尝试在此处使用默认构造函数序列化非指针值

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;
}