Reputation:
I am using the cereal library to serialize stuff. I am trying to serialize a class member of type std::vector with struct{ some unsingned short ints }.
This fails with the compiler message /usr/include/cereal/cereal.hpp:543: error: static assertion failed: cereal could not find any output serialization functions for the provided type and archive combination.
Replacing the data to be archived with an std::vector of unsigned short ints directly works as expected. Can somebody tell what I am doing wrong or if cereal is even capable of doing this with structs? I don't get it, because int's of any kind are evidently supported and vectors are too after adding the appropriate include. Just wrapping the ints in a struct does not work?
Simplified data class with stuff to be serialized: 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
}
};
Definition header of the struct that I want to serialze: 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;
}
Serialization class: 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();
}
}
};
Precompiled headers file, containing relevant includes: x_precompiled_headers.h
#include <cereal/access.hpp>
#include <cereal/archives/binary.hpp>
#include <cereal/types/string.hpp>
#include <cereal/types/vector.hpp>
Update 1: Okay, I have now updated the code and provided my struct with serialization methods. I have updated the code in th OP to reflect the changes. I have also included the save and load functions that I use in the database.h in the OP. Sadly it sill gives me this compiler error (/usr/include/cereal/cereal.hpp:822: error: no matching function for call to ‘cereal::BinaryInputArchive::processImpl(const std::vectorDatamodel::model&)’).
Upvotes: 0
Views: 1023
Reputation:
Solution: the load function (when you split save and loads) cannot be const. When splitting save and load templated functions, this is the correct scheme, also specified in the serialization function specification on cereal's website (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_);
}
Upvotes: 0
Reputation: 539
Cereal knows how to serialize standard types such as vectors and ints out of the box, but not how to serialize Datamodel::model
.
It also does not know out of the box how to serialize Database
, but you told it how to with 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
}
You need to provide a similar implementation for Datamodel::model
.
// serialization
friend class cereal::access;
template<class Archive>
void save(Archive &ar) const {
ar(number1);
ar(number2);
}
Upvotes: 1