我使用带有自定义类的boost有向图作为顶点的捆绑属性,并希望使用graphviz以DOT格式打印它 . 该类有一个私有变量,其值我想在DOT文件中出现 .
用于演示我的问题的示例代码:
#include <iostream>
#include <boost/graph/directed_graph.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
class VertexClass
{
public:
VertexClass() { id = 12; }
VertexClass( int newId ) { id = newId; }
int get_id() { return id; }
void set_id( int newId ) { id = newId; }
private:
int id;
};
typedef boost::directed_graph<VertexClass, boost::no_property> Graph;
int main(int,char*[])
{
Graph g;
Graph::vertex_descriptor v0 = g.add_vertex(3);
Graph::vertex_descriptor v1 = g.add_vertex(5);
Graph::vertex_descriptor v2 = g.add_vertex(6);
boost::add_edge(v0,v1,g);
boost::add_edge(v1,v2,g);
//boost::write_graphviz(std::cout, g, ...);
return 0;
}
期望的输出:
digraph G {
0[label=3];
1[label=5];
2[label=6];
0->1 ;
1->2 ;
}
(通过将“id”公开并在代码下运行获得) .
现在,“id”是私有的,所以在代码下面(我发现阅读其他类似问题)对我不起作用:
boost::write_graphviz(std::cout, g, boost::make_label_writer(boost::get(&VertexClass::id, g)));
我想我必须使用访问器来获取id . 经过一些搜索,我发现有人建议使用值转换属性映射(make_transform_value_property_map) .
然后我找到this answer . 但问题是,在这种情况下,属性未定义为捆绑,而是使用枚举和BOOST_INSTALL_PROPERTY . 所以,因为我没有为我工作(或者至少我不知道如何让它这样做) .
接下来,在阅读this answer后,我尝试了以下方法:
boost::write_graphviz(std::cout, g, boost::make_label_writer(boost::make_transform_value_property_map(&VertexClass::get_id, boost::get(boost::vertex_bundle, g))));
但我得到以下错误(下面的完整输出):
$ g++ -Wall -std=c++11 main.cpp
In file included from /usr/local/include/boost/graph/directed_graph.hpp:13:0,
from main.cpp:2:
/usr/local/include/boost/property_map/transform_value_property_map.hpp: In instantiation of ‘boost::transform_value_property_map<Func, PM, Ret>::reference boost::transform_value_property_map<Func, PM, Ret>::operator[](const key_type&) const [with Func = int (VertexClass::*)(); PM = boost::adj_list_vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, boost::property<boost::vertex_index_t, unsigned int, VertexClass>, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS>, VertexClass, VertexClass&, boost::vertex_bundle_t>; Ret = int; boost::transform_value_property_map<Func, PM, Ret>::reference = int; boost::transform_value_property_map<Func, PM, Ret>::key_type = void*]’:
/usr/local/include/boost/property_map/property_map.hpp:303:54: required from ‘Reference boost::get(const boost::put_get_helper<Reference, PropertyMap>&, const K&) [with PropertyMap = boost::transform_value_property_map<int (VertexClass::*)(), boost::adj_list_vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, boost::property<boost::vertex_index_t, unsigned int, VertexClass>, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS>, VertexClass, VertexClass&, boost::vertex_bundle_t>, int>; Reference = int; K = void*]’
/usr/local/include/boost/graph/graphviz.hpp:85:56: required from ‘void boost::label_writer<Name>::operator()(std::ostream&, const VertexOrEdge&) const [with VertexOrEdge = void*; Name = boost::transform_value_property_map<int (VertexClass::*)(), boost::adj_list_vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, boost::property<boost::vertex_index_t, unsigned int, VertexClass>, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS>, VertexClass, VertexClass&, boost::vertex_bundle_t>, int>; std::ostream = std::basic_ostream<char>]’
/usr/local/include/boost/graph/graphviz.hpp:270:18: required from ‘void boost::write_graphviz(std::ostream&, const Graph&, VertexPropertiesWriter, EdgePropertiesWriter, GraphPropertiesWriter, VertexID, typename boost::enable_if_c<boost::is_base_and_derived<boost::vertex_list_graph_tag, typename boost::graph_traits<Graph>::traversal_category>::value, boost::graph::detail::no_parameter>::type) [with Graph = boost::directed_graph<VertexClass, boost::no_property>; VertexPropertiesWriter = boost::label_writer<boost::transform_value_property_map<int (VertexClass::*)(), boost::adj_list_vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, boost::property<boost::vertex_index_t, unsigned int, VertexClass>, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS>, VertexClass, VertexClass&, boost::vertex_bundle_t>, int> >; EdgePropertiesWriter = boost::default_writer; GraphPropertiesWriter = boost::default_writer; VertexID = boost::adj_list_vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, boost::property<boost::vertex_index_t, unsigned int, VertexClass>, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS>, unsigned int, const unsigned int&, boost::vertex_index_t>; std::ostream = std::basic_ostream<char>; typename boost::enable_if_c<boost::is_base_and_derived<boost::vertex_list_graph_tag, typename boost::graph_traits<Graph>::traversal_category>::value, boost::graph::detail::no_parameter>::type = boost::graph::detail::no_parameter]’
/usr/local/include/boost/graph/graphviz.hpp:290:63: required from ‘void boost::write_graphviz(std::ostream&, const Graph&, VertexPropertiesWriter, EdgePropertiesWriter, GraphPropertiesWriter, typename boost::enable_if_c<boost::is_base_and_derived<boost::vertex_list_graph_tag, typename boost::graph_traits<Graph>::traversal_category>::value, boost::graph::detail::no_parameter>::type) [with Graph = boost::directed_graph<VertexClass, boost::no_property>; VertexPropertiesWriter = boost::label_writer<boost::transform_value_property_map<int (VertexClass::*)(), boost::adj_list_vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, boost::property<boost::vertex_index_t, unsigned int, VertexClass>, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS>, VertexClass, VertexClass&, boost::vertex_bundle_t>, int> >; EdgePropertiesWriter = boost::default_writer; GraphPropertiesWriter = boost::default_writer; std::ostream = std::basic_ostream<char>; typename boost::enable_if_c<boost::is_base_and_derived<boost::vertex_list_graph_tag, typename boost::graph_traits<Graph>::traversal_category>::value, boost::graph::detail::no_parameter>::type = boost::graph::detail::no_parameter]’
/usr/local/include/boost/graph/graphviz.hpp:309:38: required from ‘void boost::write_graphviz(std::ostream&, const Graph&, VertexWriter, typename boost::enable_if_c<boost::is_base_and_derived<boost::vertex_list_graph_tag, typename boost::graph_traits<Graph>::traversal_category>::value, boost::graph::detail::no_parameter>::type) [with Graph = boost::directed_graph<VertexClass, boost::no_property>; VertexWriter = boost::label_writer<boost::transform_value_property_map<int (VertexClass::*)(), boost::adj_list_vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, boost::property<boost::vertex_index_t, unsigned int, VertexClass>, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS>, VertexClass, VertexClass&, boost::vertex_bundle_t>, int> >; std::ostream = std::basic_ostream<char>; typename boost::enable_if_c<boost::is_base_and_derived<boost::vertex_list_graph_tag, typename boost::graph_traits<Graph>::traversal_category>::value, boost::graph::detail::no_parameter>::type = boost::graph::detail::no_parameter]’
main.cpp:30:166: required from here
/usr/local/include/boost/property_map/transform_value_property_map.hpp:45:24: error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘((const boost::transform_value_property_map<int (VertexClass::*)(), boost::adj_list_vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, boost::property<boost::vertex_index_t, unsigned int, VertexClass>, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS>, VertexClass, VertexClass&, boost::vertex_bundle_t>, int>*)this)->boost::transform_value_property_map<int (VertexClass::*)(), boost::adj_list_vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, boost::property<boost::vertex_index_t, unsigned int, VertexClass>, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS>, VertexClass, VertexClass&, boost::vertex_bundle_t>, int>::f (...)’, e.g. ‘(... ->* ((const boost::transform_value_property_map<int (VertexClass::*)(), boost::adj_list_vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, boost::property<boost::vertex_index_t, unsigned int, VertexClass>, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS>, VertexClass, VertexClass&, boost::vertex_bundle_t>, int>*)this)->boost::transform_value_property_map<int (VertexClass::*)(), boost::adj_list_vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, boost::property<boost::vertex_index_t, unsigned int, VertexClass>, boost::property<boost::edge_index_t, unsigned int, boost::no_property>, boost::no_property, boost::listS>, VertexClass, VertexClass&, boost::vertex_bundle_t>, int>::f) (...)’
return f(get(pm, k));
我看到的每个问题/答案都是关于上面提到的两种情况之一(带有公共变量的捆绑属性(例如结构)或老式的属性声明) .
我是boost图库中的新手,所以我想我可能错过了一些东西 . 但我无法找到解决方案(并且在boost的文档中真的丢失了),所以任何帮助都会非常感激 .
1 回答
transform_value_property_map
的包含向我表明您已接近解决方案 . 这里是:首先,让我们声明你想要graphviz节点id的de intrinsic vertex索引:
现在我们想要使用bundle做一些事情,所以让我们 grab 整个bundle的属性映射:
但是我们不能直接使用它 . 我们需要改变它:
现在写:
结果:
Live On Coliru
备选方案#1
在这种情况下,你 could 更简单:
Live On Coliru
而是更灵活的lambda
备选方案#2:没有准类
你似乎陷入了要求准类(PDF)的陷阱,它们没有增加任何 Value . 简化:
Live On Coliru
正如您现在所看到的,整个事物缩小到20行代码,并为您的顶点属性提供一流的支持 .