C++ 谷物 save/load_and_construct 不工作

C++ Cereal save/load_and_construct not working

所以我正在尝试使用 Cereal library and I've come to an issue I can't seem to overcome. Essentially the doc's say it is possible to deserialize Types with no default constructor。然而在实现说明中它说 Define a serialize or save/load pair as you normally would 但是如果没有默认构造函数,则 serialize/load 选项不能以有效的方式定义。我的意思是,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;
}

这段代码显然有点毫无意义,它只是一个最小的例子来说明我 运行 遇到的问题。

来自this page

Non-default constructors are currently only supported for serializing pointers

你的问题是你试图在没有默认构造函数的情况下序列化非指针值

std::vector<string_wrapper> strs;
_archive(strs);

要解决您的问题,您需要使用 save/load 对为 string_wrapper 创建默认构造函数,或者使用 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;
}