How do I create an interface for serialization in Boost Serialization?

I'm a newbie and I want to implement an interface to force users to implement a serialization method. This method is a template and I cannot define it as virtual.

I would like the user to only implement a function like this:

template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
  ...
};

      

I am trying to create this interface:

  class interface_serializing
  {
  public:
    virtual ~interface_serializing(void)
    { }

    friend class boost::serialization::access;

    virtual void serialize(boost::archive::polymorphic_iarchive & ar, 
                   const unsigned int version) = 0;
    virtual void serialize(boost::archive::polymorphic_oarchive & ar, 
                   const unsigned int version)  = 0;
  };

      

But it forces the user to implement these two methods and not what I want.

Is there a way to do what I want?

thank

+3


source to share


1 answer


There is no built-in way, but you can of course always abstract whatever interface you wish with the right set of tradeoffs.

Here's one imaginary solution that uses a custom one PolyArchive

, which can be a link to polymorphic_oarchive

or polymorphic_iarchive

:

#include <boost/serialization/serialization.hpp>
#include <boost/archive/polymorphic_oarchive.hpp>
#include <boost/archive/polymorphic_iarchive.hpp>
#include <boost/archive/polymorphic_text_oarchive.hpp>
#include <boost/archive/polymorphic_text_iarchive.hpp>
#include <boost/variant.hpp>
#include <sstream>

using PolyArchive = boost::variant<
            boost::archive::polymorphic_oarchive&,
            boost::archive::polymorphic_iarchive&
        >;

struct /*abstract*/ ISerializable {
    virtual void serialize(PolyArchive, unsigned) = 0;
};

struct MyClass : ISerializable {
    std::string data_member = "Morgana"; // something to serialize

    // the one method we need to implement
    virtual void serialize(PolyArchive ar, unsigned) override;
};

      

Now, do the implementation a bit with a bit of C ++ 14 fairy dust:

void MyClass::serialize(PolyArchive ar, unsigned) {
    boost::apply_visitor(make_visitor([=](auto& ar) { 
            ar & data_member;
        }), ar);
}

      

The astute reader will find that the user still supplies the template method, but hides it inside the virtual method that it actually accepts PolyArchive

at compile time.



Full demo

Watch Live On Coliru , print:

Serialized: 22 serialization::archive 11 0 0 7 Morgana
Roundtripped: 22 serialization::archive 11 0 0 7 Morgana

      

code:

#include <boost/serialization/serialization.hpp>
#include <boost/archive/polymorphic_oarchive.hpp>
#include <boost/archive/polymorphic_iarchive.hpp>
#include <boost/archive/polymorphic_text_oarchive.hpp>
#include <boost/archive/polymorphic_text_iarchive.hpp>
#include <boost/variant.hpp>
#include <sstream>

using PolyArchive = boost::variant<
            boost::archive::polymorphic_oarchive&,
            boost::archive::polymorphic_iarchive&
        >;

struct /*abstract*/ ISerializable {
    virtual void serialize(PolyArchive, unsigned) = 0;
};

struct MyClass : ISerializable {
    std::string data_member = "Morgana"; // something to serialize

    // the one method we need to implement
    virtual void serialize(PolyArchive ar, unsigned) override;
};

int main()
{
    std::stringstream ss;
    {
        // serialize:
        boost::archive::polymorphic_text_oarchive output(ss);

        MyClass object;
        output << object;
    }

    // Debug dump;
    std::cout << "Serialized: " << ss.str();

    {
        // read back:
        boost::archive::polymorphic_text_iarchive input(ss);

        MyClass cloned;
        input >> cloned;

        std::cout << "Roundtripped: ";
        boost::archive::polymorphic_text_oarchive pta(std::cout);
        pta << cloned;
    }
}

////////////////////////////////
// implementation:

namespace /*detail*/ {
    template <typename F> struct wrap_visitor : boost::static_visitor<> {

        wrap_visitor(F const& f) : f_(f) { }
        wrap_visitor(F&& f)      : f_(std::move(f)) { }

        template<typename... T> void operator()(T&&... t) const {
            f_(std::forward<T>(t)...);
        }

    private:
        F f_;
    };

    template <typename F> 
    wrap_visitor<F> make_visitor(F&& f) {
        return std::forward<F>(f);
    }
}

void MyClass::serialize(PolyArchive ar, unsigned) {

    boost::apply_visitor(make_visitor([=](auto& ar) { 
            ar & data_member;
        }), ar);
}

      

+2


source







All Articles