Зерновые: десериализовать вектор объектов без конструктора по умолчанию

Я пытаюсь использовать Cereal для сериализации объекта без конструктора по умолчанию. Хранение таких объектов напрямую или через интеллектуальный указатель работает. Однако, когда я помещаю объект в контейнер, он больше не компилируется:

error: no matching function for call to ‘Node::Node()’

Есть ли способ заставить хлопья хранить/восстанавливать векторы объектов без конструктора по умолчанию?

Мой тестовый код:

#include <fstream>
#include <cereal/archives/json.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/types/vector.hpp>


class Node {
public:
    Node(int* parent) {};

    int value_1;

    template<class Archive>
    void serialize(Archive& archive) {
        archive(
                CEREAL_NVP(value_1)
        );
    }

    template<class Archive>
    static void load_and_construct(Archive& archive, cereal::construct<Node>& construct) {
        construct(nullptr);
        construct->serialize(archive);
    }
};

int main() {
    std::string file_path = "../data/nodes.json";
    Node node_1{nullptr};  // this would serialize

    std::vector<Node> nodes;  // this does not
    nodes.push_back(Node{nullptr});
    nodes.push_back(Node{nullptr});

    std::vector<std::unique_ptr<Node>> node_ptrs;  // this would serialize
    node_ptrs.push_back(std::make_unique<Node>(nullptr));
    node_ptrs.push_back(std::make_unique<Node>(nullptr));

    {  //store vector
        std::ofstream out_file(file_path);
        cereal::JSONOutputArchive out_archive(out_file);
        out_archive(CEREAL_NVP(nodes));
    }

    {  // load vector
        std::ifstream in_file(file_path);
        cereal::JSONInputArchive in_archive(in_file);
        in_archive(nodes);
    }

    return 0;
}

person BoshWash    schedule 07.05.2017    source источник


Ответы (1)


Насколько я понимаю, как работает эта библиотека, невозможно десериализовать то, что не имеет конструктора по умолчанию, по крайней мере, для динамически размещаемых объектов.

Логика при этом следующая:

  1. Вам нужно десериализовать vector<Node>
  2. Для этого вам нужно выделить соответствующий объем памяти
  3. хлопья не знают о конструкторе и не могут самостоятельно правильно выделить память объекта
  4. Чтобы обеспечить правильное построение объекта, требуется конструктор по умолчанию.
person Alex    schedule 07.05.2017
comment
Представьте себе сценарий загрузки типа, у которого нет конструктора по умолчанию. Интерфейс сериализации хлопьев требует, чтобы вы передали ссылку на объект, который будет создан с сериализованными данными. В случае отсутствия конструктора по умолчанию вы (пользователь) должны уже инициализировать такой объект еще до того, как злак его увидит. Альтернативой является то, что хлопья выполняют фактическое построение объекта, что может произойти только с динамически созданными объектами (т. е. указателями), так что хлопья могут предварительно загружать аргументы для передачи конструктору, как в load_and_construct. - person Azoth; 17.05.2017