How to write GraphML file to Boost Graph with custom graph_bundle Property?

97 Views Asked by At

I am not able to compile below , where I want to use graph_bundle property of boost graph.

struct VertexProps
{
    std::string VertexName;
};

struct EdgeProps 
{
    std::string edgeName;
};

struct GraphProps
{
    std::string name;
};

boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, VertexProps, EdgeProps, GraphProps> g;
g[boost::graph_bundle].name = "myGraphName";
boost::dynamic_properties dp;
dp.property("name", get(&GraphProps::name, g)); //compile error on this line
std::ofstream xmlFile("output.graphml");
boost::write_graphml(xmlFile, g, dp, true);
xmlFile.close();

I am getting beloe compile error:

<>/boost/graph/detail/adjacency_list.hpp:2646:29: error: forming reference to void
 2646 |         typedef value_type& reference;
      |                             ^~~~~~~~~
<>/boost/graph/detail/adjacency_list.hpp:2647:35: error: forming reference to void
 2647 |         typedef const value_type& const_reference;
      |                                   ^~~~~~~~~~~~~~~
<>/boost/graph/detail/adjacency_list.hpp:2651:13: error: forming reference to void
 2651 |             type;
      |             ^~~~
<>/boost/graph/detail/adjacency_list.hpp:2654:13: error: forming reference to void
 2654 |             const_type;
      |             ^~~~~~~~~~
test.cpp: In function ‘void writeGraph()’:
test.cpp:310:49: error: no matching function for call to ‘get(std::string GraphProps::*, Graph&)’
  310 |     dp.property("name", get(&GraphProps::name, g));
      |                                                 ^

It seems , boost graph library can't support custom property name , which can be used dynamic_properties for writing in graphml.

1

There are 1 best solutions below

0
On BEST ANSWER

Graph properties in property maps are poorly documented. In fairness, they're also of limited use.

You need to make an associative property map with key type G* (where G denotes your graph type).

The simplest way would be to use make_constant_property_map:

dp.property("name", boost::make_constant_property<G*>(get_property(g).name));

See it Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
struct VertexProps { std::string VertexName; };
struct EdgeProps   { std::string edgeName;   };
struct GraphProps  { std::string name;       };

int main() {
    using G = boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, VertexProps,
                                    EdgeProps, GraphProps>;
    G g;

    auto& gp = get_property(g);
    g[boost::graph_bundle].name = "myGraphName"; // or gp.name = "myGraphName"

    boost::dynamic_properties dp;
    dp.property("name", boost::make_constant_property<G*>(get_property(g).name));

    boost::write_graphml(std::cout, g, dp, true);
}

Printing

<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
  <key id="key0" for="graph" attr.name="name" attr.type="string" />
  <graph id="G" edgedefault="directed" parse.nodeids="canonical" parse.edgeids="canonical" parse.order="nodesfirst">
   <data key="key0">myGraphName</data>
  </graph>
</graphml>