user11931376
user11931376

Reputation:

I want to serialize a vector of structs containing ints and it does not work (cereal library)

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

Answers (2)

user11931376
user11931376

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

Jan15
Jan15

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

Related Questions