after implementing some algorithm using the BGL, im trying to provide io functions using GraphML. However, i dont manage to compile a suitable operator<< that takes a const Graph reference.
Here is a boiled down example:
// use bundled properties for vertices and edges
struct VertexProperty
{
double error;
};
typedef boost::adjacency_list< boost::setS, boost::setS, boost::undirectedS, VertexProperty> Graph;
typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor;
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor;
std::ostream& operator<<(std::ostream& os, const Graph& graph)
{
typedef std::map<vertex_descriptor, std::size_t> IndexMap;
IndexMap index_map;
boost::associative_property_map<IndexMap> index_properties(index_map);
std::size_t i = 0;
for (const vertex_descriptor& v : boost::make_iterator_range(boost::vertices(graph)))
index_properties[v] = i++;
boost::dynamic_properties dp;
typename boost::property_map<Graph, double VertexProperty::*>::const_type error_map = get(&VertexProperty::error, graph);
dp.property("error", error_map);
boost::write_graphml(os, graph,index_properties,dp);
return os;
}
int main()
{
Graph g;
std::cout << g <<std::endl;
}
Compilation fails with:
boost/property_map/property_map.hpp:309:44: error: assignment of read-only location '(&((const boost::adj_list_vertex_property_map, double, const double&, double VertexProperty::*>&)pa))->boost::adj_list_vertex_property_map::operator[], double, const double&, double VertexProperty::*>(k)' static_cast(pa)[k] = v;
As far as i understood the dynamic_properties documentation, those read only checks are supposed to happen at runtime (Isn't this one of the aims of the whole type erasure). And of course they should fail if one tries to modify a immutable property. But the call to wirte write_graphml() takes a const ref to the dynamics properties and is not supposed to change anything.
To state the question(s):
- Why does compilation fail?
- And how do i do it corretly?
- By using some other property_map (Yes/No/Which one)?
For a (not) running example @ coliru.stacked-crooked.com: See here!
Regards, Marti
The true issue at hand is that the category of the vertex property map is being deduced as
LvaluePropertyMap
(which it is).However, the
LvaluePropertyMap
concept promises to be a superset ofReadablePropertyMap
andWritablePropertyMap
. This poses problems when theconst_type
of the graph properties are used: they are lvalues, but they are not writable.The only working solution I came up with was to wrap the property map type to overrule the category:
Now, you can use it like so:
Although it's nearly the same, now
dynamic_properties::property
detects that the map is readable only, and doesn't attempt to generate the put helpers (instead, an exception will be raised if aput
is attempted).Full Code with demo graph:
Live On Coliru
Output: (slightly reformatted)