Search code examples
c++serializationboostboost-graph

Serialization of a graph with specific vertex type


I want to do disk I/O of a graph stored using BGL. I am using boost::serialization.

First, some code that compiles:

typedef boost::adjacency_list<
    boost::vecS
    ,boost::vecS
    ,boost::undirectedS
    > graph_t;

int main()
{
    graph_t g;

    std::ifstream ifs( "file_in" );          // read from file
    boost::archive::text_iarchive ia( ifs );
    ia >> g;    

    std::ofstream ofs( "file_out" );        // save to file
    boost::archive::text_oarchive oa( ofs );
    oa << g;
}

Now, I need to store data into my vertices. So I redefine my graph:

struct myVertex
{
    int a;
    float b;
};

typedef boost::adjacency_list<
    boost::vecS,
    boost::vecS,
    boost::undirectedS,
    myVertex
    > graph_t;

Of course, I need to define how to serialize myVertex. As I don't want to obfuscate that data structure, I want to use the non-intrusive way, as it is described in the manual.

So, as told in the manual, I add the needed function:

namespace boost {
namespace serialization {

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

} // namespace serialization
} // namespace boost

Unfortunately, this does not compile: the compiler complains about a missing serializing function:

error: ‘struct myVertex’ has no member named ‘serialize’

Live code on Coliru

My understanding of this is that the inner BGL data structures provide a serializing function, that itself relies on a class member serializing function of vertices (and edges, obviously). And that it cannot use an external serializing function.

Note that it does build fine if I use the so-called "intrusive" way (adding the serialize function as class member), but I wanted to know if it can be done as explained above.


Solution

  • You should declare the argument non-const:

    template <class Archive> void serialize(Archive &ar, myVertex &mv, unsigned /*version*/) {
    

    Live Demo

    Live On Coliru

    #include <boost/archive/text_iarchive.hpp>
    #include <boost/archive/text_oarchive.hpp>
    #include <boost/graph/adj_list_serialize.hpp>
    #include <boost/graph/adjacency_list.hpp>
    #include <fstream>
    
    struct myVertex {
        int a;
        float b;
    };
    
    namespace boost {
        namespace serialization {
            template <class Archive> void serialize(Archive &ar, myVertex &mv, unsigned /*version*/) {
                ar & mv.a & mv.b;
            }
        } // namespace serialization
    } // namespace boost
    
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, myVertex> graph_t;
    
    #include <iostream>
    int main(int argc, char**) {
    
        if (argc>1) {
            graph_t g;
            std::ifstream ifs("file_out"); // read from file
            boost::archive::text_iarchive ia(ifs);
            ia >> g;
    
            std::cout << "Read " << num_vertices(g) << " vertices\n";
        }
    
        {
            graph_t g(100);
            std::ofstream ofs("file_out"); // save to file
            boost::archive::text_oarchive oa(ofs);
            oa << g;
        }
    }
    

    Prints:

    ./a.out
    ./a.out read_as_well
    Read 100 vertices