我想序列化一个包含整数的结构向量,但它不起作用谷物库

问题描述

我正在使用谷物库来序列化内容。我正在尝试使用 struct{ some unsingned short ints } 序列化 std::vector 类型的类成员

这会失败并显示编译器消息 /usr/include/cereal/cereal.hpp:543: 错误:静态断言失败:谷类食品找不到提供的类型和存档组合的任何输出序列化函数

用 std::vector 的无符号短整型替换要存档的数据直接按预期工作。有人能告诉我我做错了什么,或者谷物是否能够用结构做到这一点? 我不明白,因为在添加适当的包含之后,显然支持任何类型的 int 并且向量也是如此。仅将整数包装在结构中不起作用?

带有要序列化的内容的简化数据类:database.h

#include <utils/x_precompiled_headers.h>
#include <utils/serialize.h>
#include <database/datamodel.h>

class Database : public QObject
{
    Q_OBJECT

private:
    std::vector<Datamodel::model> models_;
    // std::vector<unsigned short int> test = {1,2,3};

void Database::Savetodisk(){
    Serialize::ExportData(*this,"database");
}

void Database::LoadFromdisk(){
    Serialize::ImportData(*this,"database");
}

    // serialization
    friend class cereal::access;
    template<class Archive>
    void save(Archive &ar) const {
//                                   ar(test); // this does not complain
                                   ar(models_); //this gives the compiler error
                                 }
};

我要序列化的结构体的定义头:database/datamodel.h

namespace Datamodel
{
    typedef struct{
        unsigned short int number1;
        unsigned short int number2;

        template<class Archive>
        void save(Archive &ar) const{
            ar(number1,number2);
        }

        template<class Archive>
        void load(Archive &ar) const{
            ar(number1,number2);
        }
    } model;
}

序列化类:utils/serialize.h

class Serialize
{
public:
    template<typename T>
    static void ExportData(T &object,const std::string &filename)
    {
        std::string path = std::filesystem::current_path() /= filename;
        std::ofstream ofs(path);

        if(ofs.is_open()){
            cereal::BinaryOutputArchive oarchive(ofs);
            oarchive(object);
            ofs.close();
        }
    }

    template <typename T>
    static void ImportData(T &object,const std::string &filename)
    {
        std::string path = std::filesystem::current_path() /= filename;

        if(!std::filesystem::exists(path))
            return;

        std::ifstream ifs(path);

        if(ifs.is_open())
        {
            cereal::BinaryInputArchive iarchive(ifs);
            iarchive(object);
            ifs.close();
        }
    }
};

预编译头文件,包含相关的include:x_precompiled_headers.h

#include <cereal/access.hpp>
#include <cereal/archives/binary.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>

更新 1:好的,我现在更新了代码并为我的结构提供了序列化方法。我已经更新了 OP 中的代码以反映更改。我还包括了我在 OP 的 database.h 中使用的保存和加载函数。可悲的是,它仍然给我这个编译器错误(/usr/include/cereal/cereal.hpp:822: error: no matching function for call to 'cereal::BinaryInputArchive::processImpl(const std::vectorDatamodel::model&)') .

解决方法

Cereal 知道如何序列化标准类型,例如开箱即用的向量和整数,但不知道如何序列化 Datamodel::model

它也不知道如何立即序列化 Database,但是您告诉它如何使用 save

// serialization
    friend class cereal::access;
    template<class Archive>
    void save(Archive &ar) const {
//                                   ar(test); // this does not complain
                                   ar(models_); //this gives the compiler error
                                 }

您需要为 Datamodel::model 提供类似的实现。

// serialization
friend class cereal::access;
template<class Archive>
void save(Archive &ar) const {
    ar(number1); 
    ar(number2); 
}
,

解决方案:加载函数(当你拆分保存和加载时)不能是const。 拆分保存和加载模板化函数时,这是正确的方案,也在谷类网站(https://uscilab.github.io/cereal/serialization_functions.html)上的序列化函数规范中指定:

template<class Archive>
void save(Archive &ar) const{
    ar(models_);
}
template<class Archive>
void load(Archive &ar){
    ar(models_);
}