Chase R Lewis
Chase R Lewis

Reputation: 2307

Cereal serialization error

So i'm legit confused. It won't compile for an external serialization function. It gives the error

cereal could not find any output serialization functions for the provided type and archive combination.

So the code below doesn't compile

#include <fstream>
#include <glm/glm.hpp>
#include "SceneObject.h"
#include <cereal/cereal.hpp>
#include <cereal/archives/json.hpp>

template<typename Archive> void serialize(Archive& archive, glm::vec3& v3)
{
    archive(cereal::make_nvp("x", v3.x), cereal::make_nvp("y", v3.y), cereal::make_nvp("z", v3.z));
}

struct something
{
public:
    float x, y, z;
};
template<typename Archive> void serialize(Archive& archive, something& v3)
{
    archive(cereal::make_nvp("x", v3.x), cereal::make_nvp("y", v3.y), cereal::make_nvp("z", v3.z));
}

int main(int argc, char** argv)
{
    SceneObject test;
    test.transform().setPosition(1.0f,2.0f,3.0f);

    {
        std::ofstream file("TestPath.json");
        cereal::JSONOutputArchive output(file);
        glm::vec3 p = test.transform().getPosition();
        output(p);
    }

    return 0;
}

but this DOES compile

#include <fstream>
#include <glm/glm.hpp>
#include "SceneObject.h"
#include <cereal/cereal.hpp>
#include <cereal/archives/json.hpp>

template<typename Archive> void serialize(Archive& archive, glm::vec3& v3)
{
    archive(cereal::make_nvp("x", v3.x), cereal::make_nvp("y", v3.y), cereal::make_nvp("z", v3.z));
}

struct something
{
public:
    float x, y, z;
};
template<typename Archive> void serialize(Archive& archive, something& v3)
{
    archive(cereal::make_nvp("x", v3.x), cereal::make_nvp("y", v3.y), cereal::make_nvp("z", v3.z));
}

int main(int argc, char** argv)
{
    SceneObject test;
    test.transform().setPosition(1.0f,2.0f,3.0f);

    {
        std::ofstream file("TestPath.json");
        cereal::JSONOutputArchive output(file);
        glm::vec3 p = test.transform().getPosition();
        something s;
        s.x = p.x;
        s.y = p.y;
        s.z = p.z;
        output(s);
    }

    return 0;
}

I literally copy and pasted the save code from glm::vec3 to something and just changed glm::vec3 to 'something'. It makes NO sense to me why it would work for one and not the other. I think it might be a namespace thing, but I have no clue how to fix that.

Upvotes: 6

Views: 2679

Answers (2)

Croc Dialer
Croc Dialer

Reputation: 81

I can confirm your conclusion. in case of externally defined serialize-functions you would place them in the same namespace to enable cereal to see/use them.

a complete/templated set of serialization-functions for all flavors of vec2-4, mat2-4 and quat types can be achieved like this (requires glm-version >=0.9.6, https://www.g-truc.net/post-0693.html):

#include <glm/glm.hpp>
#include <cereal/cereal.hpp>

namespace glm
{

template<class Archive, class T>
void serialize(Archive &archive, glm::vec<2, T, glm::defaultp> &v)
{
    archive(cereal::make_nvp("x", v.x),
            cereal::make_nvp("y", v.y));
}

template<class Archive, class T>
void serialize(Archive &archive, glm::vec<3, T, glm::defaultp> &v)
{
    archive(cereal::make_nvp("x", v.x),
            cereal::make_nvp("y", v.y),
            cereal::make_nvp("z", v.z));
}

template<class Archive, class T>
void serialize(Archive &archive, glm::vec<4, T, glm::defaultp> &v)
{
    archive(cereal::make_nvp("x", v.x),
            cereal::make_nvp("y", v.y),
            cereal::make_nvp("z", v.z),
            cereal::make_nvp("w", v.w));
}

// glm matrices serialization
template<class Archive, class T>
void serialize(Archive &archive, glm::mat<2, 2, T, glm::defaultp> &m){ archive(m[0], m[1]); }

template<class Archive, class T>
void serialize(Archive &archive, glm::mat<3, 3, T, glm::defaultp> &m){ archive(m[0], m[1], m[2]); }

template<class Archive, class T>
void serialize(Archive &archive, glm::mat<4, 4, T, glm::defaultp> &m){ archive(m[0], m[1], m[2], m[3]); }

template<class Archive, class T>
void serialize(Archive &archive, glm::qua<T, glm::defaultp> &q)
{
    archive(cereal::make_nvp("x", q.x),
            cereal::make_nvp("y", q.y),
            cereal::make_nvp("z", q.z),
            cereal::make_nvp("w", q.w));
}

}// namespace glm

Upvotes: 0

Chase R Lewis
Chase R Lewis

Reputation: 2307

Well apparently posting made me find the solution.

You need to make sure the serialize functions share the same namespace so if I wrap them like

namespace glm
{
template<typename Archive> void serialize(Archive& archive, glm::vec3& v3)
{
    archive(cereal::make_nvp("x", v3.x), cereal::make_nvp("y", v3.y),    cereal::make_nvp("z", v3.z));
}
}

It works. Kinda odd, but it is what it is.

Upvotes: 12

Related Questions