问题描述
我正在使用谷物库来序列化内容。我正在尝试使用 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_);
}