Cereal Add Serialize to Existing Library Class

124 Views Asked by At

I am trying to add serial support for an existing class in SFML library. I am trying to save colors to be loaded later. From the documents, it says that Cereal is easily extensible to other types, but I have no clue how to do so. Barring creating a SerialColor class and reimplementing sf::Color inside it, and adding a serialize member in there, is there a way to do this? I would really like to not rewrite the 5 classes I need from SFML to be serializeable.

I am part way through converting Color to SerialColor, and so far have achieved the following:

SerialColor.hpp

#pragma once
#include <SFML/Graphics.hpp>
#include <SFML/Config.hpp>


class SerialColor: sf::Color
{
public:

    static const SerialColor Black;       ///< Black predefined color
    static const SerialColor White;       ///< White predefined color
    static const SerialColor Red;         ///< Red predefined color
    static const SerialColor Green;       ///< Green predefined color
    static const SerialColor Blue;        ///< Blue predefined color
    static const SerialColor Yellow;      ///< Yellow predefined color
    static const SerialColor Magenta;     ///< Magenta predefined color
    static const SerialColor Cyan;        ///< Cyan predefined color
    static const SerialColor Transparent; ///< Transparent (black) predefined color

    SerialColor(sf::Uint8 red, sf::Uint8 green, sf::Uint8 blue, sf::Uint8 alpha = 255);

private:

    SerialColor(sf::Color c);
    
    sf::Color color;

    template<class Archive>
    void serialize(Archive& archive, std::uint32_t const version) {
        archive(CEREAL_NVP(this->color.r),
                CEREAL_NVP(this->color.g),
                CEREAL_NVP(this->color.b)
        );
    }
};




SerialColor.cpp

#include "SerialColor.h"




SerialColor::SerialColor(sf::Uint8 red, sf::Uint8 green, sf::Uint8 blue, sf::Uint8 alpha = 255) {
    this->color = sf::Color(red, green, blue, alpha);
}


SerialColor::SerialColor(sf::Color c) {
    this->color = sf::Color(c);
}

This is currently not completely implemented, so it does not work. However this feels like overkill to add 1 function to a class. If extending is the correct way, could you provide what is considered the normal way to add this capability? This just feels wrong.

1

There are 1 best solutions below

0
On

Instead of trying to extend the class directly, you can provide cereal with a function that tells it how to serialise your custom data types, e.g:

namespace cereal {
    template<class Archive>
    void serialize(Archive& archive, sf::Color c) {
        archive(CEREAL_NVP(c.r),
                CEREAL_NVP(c.g),
                CEREAL_NVP(c.b)
    );
}

You can choose to add something like the code above to your own header file (something like 'Serialize.hpp') and include that instead of cereal.hpp, or you can extend your cereal headers directly (i.e. something like cereal/types/sf_color.hpp).

It's really up to you where you put this code but as long as it is visible, cereal will automatically be able to serialise the sf::Color type.