c – boost :: dynamic_properties和不可变图形对象
在使用BGL实现一些算法之后,我试图使用GraphML提供io功能.但是,我没有设法编译一个合适的运算符<<采用const Graph参考. 这是一个简单的例子:
// 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; } 编译失败:
据我所知,dynamic_properties文档,那些只读检查应该在运行时发生(这不是整个类型擦除的目标之一).当然,如果尝试修改不可变属性,它们应该会失败.但是对wirte write_graphml()的调用需要const参考动力学属性,并且不应该改变任何东西. 陈述问题: >为什么编译失败? 对于(不)运行的示例@coliru.stacked-crooked.com:See here! 问候, 解决方法
手头的真正问题是顶点属性映射的类别被推导为LvaluePropertyMap(它是).
但是,LvaluePropertyMap概念有望成为ReadablePropertyMap和WritablePropertyMap的超集.当使用图形属性的const_type时,这会产生问题:它们是左值,但它们是不可写的. 我想出的唯一可行解决方案是将属性映射类型包装为否决类别: namespace detail { template <typename Map> struct readable_only_pmap : Map { readable_only_pmap(Map map) : Map(map) { } // overrule the category tag typedef boost::readable_property_map_tag category; }; } 现在,您可以像这样使用它: using pmap_t = typename boost::property_map<Graph,double VertexProperty::*>::const_type; detail::readable_only_pmap<pmap_t> error_map = get(&VertexProperty::error,graph); 虽然它几乎相同,但现在dynamic_properties :: property检测到映射只是可读的,并且不会尝试生成put帮助程序(相反,如果尝试put,则会引发异常). 完整代码与演示图: Live On Coliru #include <iostream> #include <string> #include <vector> #include <functional> #include <iostream> #include <boost/graph/adjacency_list.hpp> #include <boost/graph/graphml.hpp> // #include <Eigen/Core> // use bundled properties for vertices and edges struct VertexProperty { double error; // Eigen::Matrix<real,dim,1> location; }; typedef boost::adjacency_list< boost::setS,VertexProperty> Graph; typedef typename boost::graph_traits<Graph>::edge_descriptor edge_descriptor; typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_descriptor; namespace detail { template <typename Map> struct readable_only_pmap : Map { readable_only_pmap(Map map) : Map(map) { } // overrule the category tag typedef boost::readable_property_map_tag category; }; } std::ostream& operator<<(std::ostream& os,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++; using pmap_t = typename boost::property_map<Graph,double VertexProperty::*>::const_type; detail::readable_only_pmap<pmap_t> error_map = get(&VertexProperty::error,graph); boost::dynamic_properties dp; dp.property("error",error_map); boost::write_graphml(os,dp); return os; } int main() { Graph g; auto v1 = boost::add_vertex(VertexProperty{0.1},g); auto v2 = boost::add_vertex(VertexProperty{0.2},g); auto v3 = boost::add_vertex(VertexProperty{0.3},g); auto v4 = boost::add_vertex(VertexProperty{0.4},g); auto v5 = boost::add_vertex(VertexProperty{0.5},g); add_edge(v1,v2,g); add_edge(v5,g); add_edge(v4,g); add_edge(v2,v3,g); add_edge(v3,v4,v1,g); std::cout << g <<std::endl; } 输出:(略微重新格式化) <?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="node" attr.name="error" attr.type="double" /> <graph id="G" edgedefault="undirected" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst"> <node id="n0"> <data key="key0">0.1</data> </node> <node id="n1"> <data key="key0">0.2</data> </node> <node id="n2"> <data key="key0">0.3</data> </node> <node id="n3"> <data key="key0">0.4</data> </node> <node id="n4"> <data key="key0">0.5</data> </node> <edge id="e0" source="n0" target="n1"> </edge> <edge id="e1" source="n4" target="n1"> </edge> <edge id="e2" source="n3" target="n1"> </edge> <edge id="e3" source="n1" target="n2"> </edge> <edge id="e4" source="n2" target="n3"> </edge> <edge id="e5" source="n3" target="n0"> </edge> </graph> </graphml> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |