2

因此,我正在尝试使用Cereal库,但遇到了一个似乎无法克服的问题。基本上,文档说可以反序列化没有默认构造函数的类型。然而在实现说明中它说Define a serialize or save/load pair as you normally would如果没有默认构造函数,则无法以有效方式定义序列化/加载选项。我的意思是,该load_and_construct函数取代了load. 然而,当实现下面看到的一个相对简单的例子时。

“主.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;
}

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

4

1 回答 1

2

这个页面

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

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

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

要解决您的问题,您需要为string_wrapperwith save/loadpair 创建默认构造函数或string_wrapperwrapper_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;
} 
于 2018-07-27T03:21:25.680 回答