Boost反向邻接表图的边遍历问题求助
我来帮你搞定这个问题!你遇到的错误本质是旧版本Boost(比如你用的1.67)的reverse_graph在处理边bundle属性访问时,operator[]没有正确维护const限定符,导致你用const引用的边描述符访问属性时出现类型不匹配。
错误根源
当你通过reversed_graph[item]访问边的index时,reverse_graph的operator[]返回的是非const引用,但你的lambda参数const auto& item是const的,这就触发了编译器报错——因为不能把const类型绑定到非const引用上。这个是Boost 1.67的已知bug,在后续版本(比如1.70+)已经修复了。
三种可行解决方案
方案1:用Boost的get函数访问属性(推荐)
Boost提供了属性映射的方式来安全访问图的顶点/边属性,完全绕开operator[]的问题。把你的遍历代码改成这样:
// 先获取边index的属性映射 auto edge_index_map = get(&edgeinfo::index, reversed_graph); std::for_each(range.first, range.second, [&](const auto& item){ std::cout << get(edge_index_map, item) << '\n'; });
这种方式最通用,不管Boost版本新旧都能正常工作,而且是Boost官方推荐的属性访问方式。
方案2:显式指定reverse_graph的const模板参数
如果你不想改遍历逻辑,可以在定义ReversedGraph时,显式指定底层图为const引用:
// 修改ReversedGraph的定义 using ReversedGraph = reverse_graph<const Graph, const Graph&>;
这样reverse_graph的operator[]会返回const引用,和你的const边描述符匹配。不过这个方法只适用于只读遍历的场景,如果之后要修改反向图就不行了。
方案3:升级Boost版本
如果条件允许,直接把Boost升级到1.70或更高版本,原代码就能直接编译通过,因为这个const限定符的bug已经被官方修复了。
完整可运行代码(方案1实现)
下面是修改后的完整代码,替换了原有的遍历部分:
#include <boost/config.hpp> #include <algorithm> #include <vector> #include <utility> #include <iostream> #include <boost/graph/adjacency_list.hpp> #include <boost/graph/reverse_graph.hpp> #include <boost/graph/graph_utility.hpp> using namespace boost; struct vertexinfo { int index{12}; }; struct edgeinfo { int index{10}; }; using Graph = adjacency_list < vecS, vecS, bidirectionalS ,vertexinfo,edgeinfo>; using ReversedGraph = reverse_graph<Graph>; int main(){ Graph graph(5); auto e1 = add_edge(0, 2, graph); graph[e1.first].index = 1; auto e2 = add_edge(1, 1, graph); graph[e2.first].index = 2; auto e3 = add_edge(1, 3, graph); graph[e3.first].index = 3; auto e4 = add_edge(1, 4, graph); graph[e4.first].index = 4; auto e5 = add_edge(2, 1, graph); graph[e5.first].index = 5; auto e6 = add_edge(2, 3, graph); graph[e6.first].index = 6; auto e7 = add_edge(2, 4, graph); graph[e7.first].index = 7; auto e8 = add_edge(3, 1, graph); graph[e8.first].index = 8; auto e9 = add_edge(3, 4, graph); graph[e9.first].index = 9; auto e10 = add_edge(4, 0, graph); graph[e10.first].index = 10; auto e11 = add_edge(4, 1, graph); graph[e11.first].index = 11; ReversedGraph reversed_graph(graph); std::cout << "original graph:" << std::endl; print_graph(graph, get(vertex_index, graph)); std::cout << std::endl << "reversed graph:" << std::endl; print_graph(reversed_graph, get(vertex_index, graph)); auto range = edges(reversed_graph); // 使用属性映射访问边的index auto edge_index_map = get(&edgeinfo::index, reversed_graph); std::for_each(range.first,range.second,[&](const auto& item){ std::cout << get(edge_index_map, item) << '\n'; }); return EXIT_SUCCESS; }
这个代码在Boost 1.67下可以正常编译运行,输出所有反向图边的index值,完全符合你的需求。
内容的提问来源于stack exchange,提问作者AfricAnand

