我目前正在尝试在现有的c项目中使用boost图库 . 我想在boost图中存储自定义类的对象 . 下面是一个小示例,其中包含两个成员(字符串和int)的自定义类定义及其相应的getter方法 .
我有几个问题:
-
如何在Graphviz输出中包含string和int值?我使用
boost::make_label_writer
发现这个answer类似的问题,但我不确定我的例子是否可以被采用(我使用的是自定义类和共享指针) . -
不应该在图中多次存储相同的对象(相同的字符串和int值) . 因此我在自定义类中重载了两个比较运算符 . 我还读到我必须将图形类型定义的第二个模板参数更改为
boost::setS
,但这会导致编译器发出非常长的错误消息... -
假设我创建了自定义类的新对象:如何检查它是否已存储在图形中?
#include <iostream>
#include <boost/graph/graphviz.hpp>
class my_custom_class {
public:
my_custom_class(const std::string &my_string,
int my_int) : my_string(my_string),
my_int(my_int) {}
virtual ~my_custom_class() {
}
std::string get_my_string() const {
return my_string;
}
int get_int() const {
return my_int;
}
bool operator==(const my_custom_class &rhs) const {
return my_string == rhs.my_string &&
my_int == rhs.my_int;
}
bool operator!=(const my_custom_class &rhs) const {
return !(rhs == *this);
}
private:
std::string my_string;
int my_int;
};
namespace boost {
enum vertex_my_custom_class_t {
vertex_my_custom_class = 123
};
BOOST_INSTALL_PROPERTY(vertex,
my_custom_class);
}
int main() {
typedef boost::adjacency_list<boost::vecS,
boost::vecS,
boost::directedS,
boost::property<boost::vertex_my_custom_class_t,
std::shared_ptr<my_custom_class>>> graph_t;
typedef boost::graph_traits<graph_t>::vertex_descriptor vertex_t;
std::shared_ptr<my_custom_class> object_one = std::make_shared<my_custom_class>("Lorem", 123);
std::shared_ptr<my_custom_class> object_two = std::make_shared<my_custom_class>("ipsum", 456);
std::shared_ptr<my_custom_class> object_three = std::make_shared<my_custom_class>("Lorem", 123);
std::cout << "object one: " << object_one->get_int() << "; " << object_one->get_my_string() << std::endl;
std::cout << "object two: " << object_two->get_int() << "; " << object_two->get_my_string() << std::endl;
std::cout << "object three: " << object_three->get_int() << "; " << object_three->get_my_string() << std::endl;
std::cout << std::endl;
std::cout << "object one == object two: " << (*object_one == *object_two) << std::endl;
std::cout << "object one == object three: " << (*object_one == *object_three) << std::endl;
std::cout << std::endl;
graph_t graph;
vertex_t vertex_one = boost::add_vertex(object_one, graph);
vertex_t vertex_two = boost::add_vertex(object_two, graph);
vertex_t vertex_three = boost::add_vertex(object_three, graph);
boost::add_edge(vertex_one, vertex_two, graph);
boost::add_edge(vertex_one, vertex_three, graph);
boost::write_graphviz(std::cout, graph);
return 0;
}
节目输出:
object one: 123; Lorem
object two: 456; ipsum
object three: 123; Lorem
object one == object two: 0
object one == object three: 1
digraph G {
0;
1;
2;
0->1 ;
0->2 ;
}
1 回答
印刷: Live On Coliru
副作用从连续分配的顶点存储变为基于节点(pro:迭代器/参考稳定性,con:分配开销,减少的参考局部性,非隐式vertex_index) . 后者是罪魁祸首:BGL中的许多东西需要一个顶点索引,如果没有暗示(例如使用
vecS
),你必须传递一个 .有趣的是,由于我使用
write_graphviz_dp
具有特定的node_id
属性,因此现在不需要隐式顶点索引,因此您可以将vecS
更改为setS
并观察行为: Live On Coliru样式/简化
因为
std::shared_ptr
暗示你有c 11,所以让我们使用它 .此外,整个舞蹈与自定义属性大多是一种更笨拙的做属性包:这些在语法上更容易和更好的支持 .
看到不同:
Live On Coliru
比较:没有共享指针
我不是说你不能使用它,但我也不相信你需要它 . 所以,让我们删除它,以便您看到差异:
Live On Coliru
这大约是代码的一半 . 从这里我们可以探索如何添加所需的功能
唯一性:让我们试试我们的手
最简单的方法是在添加新节点之前检查现有节点:
Live On Coliru
注意
v3
现在等于v1
: