使用boost::subgraph时出现‘forming reference to void’错误求解决
Boost Subgraph 编译错误:无法形成void引用的解决方法
问题原因
Boost Subgraph对底层图有强制要求:必须支持edge_index属性,用于维护子图边与父图边的映射关系。你的自定义Connection结构体未包含该属性,导致Boost内部尝试生成指向void的引用,触发编译错误。单独使用adjacency_list时不需要这个属性,所以代码可以正常编译。
解决方案
有两种方式可以解决这个问题,既满足Subgraph的要求,又保留自定义的边属性:
方案1:用boost::property组合自定义属性与edge_index
将自定义边属性包装在boost::property中,同时包含edge_index属性:
#include <boost/graph/subgraph.hpp> #include <boost/graph/adjacency_list.hpp> struct Component { int vert_id; }; struct Connection { int edge_id; }; struct NetworkData { int graph_id; }; // 用property组合edge_index和自定义Connection属性 using EdgeProp = boost::property<boost::edge_index_t, std::size_t, Connection>; using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, Component, EdgeProp, NetworkData>; boost::subgraph<Graph> base_graph; int main() { auto& sub_graph = base_graph.create_subgraph(); // 访问图bundle属性 base_graph[boost::graph_bundle].graph_id = 1; sub_graph[boost::graph_bundle].graph_id = 2; // 添加顶点并访问属性 const auto base_vert = boost::add_vertex(base_graph); const auto sub_vert = boost::add_vertex(sub_graph); base_graph[base_vert].vert_id = 10; base_graph[sub_vert].vert_id = 20; sub_graph[base_vert].vert_id = 10; // 子图访问父图顶点属性 sub_graph[sub_vert].vert_id = 20; // 添加边并访问属性 const auto [base_edge, a1] = boost::add_edge(base_vert, sub_vert, base_graph); const auto [sub_edge, a2] = boost::add_edge(base_vert, sub_vert, sub_graph); // 访问自定义edge_id属性 boost::get<Connection>(base_graph, base_edge).edge_id = 100; boost::get<Connection>(base_graph, sub_edge).edge_id = 200; boost::get<Connection>(sub_graph, base_edge).edge_id = 100; boost::get<Connection>(sub_graph, sub_edge).edge_id = 200; // 访问edge_index属性(Subgraph内部需要) boost::get<boost::edge_index_t>(base_graph, base_edge); return 0; }
方案2:在自定义结构体中添加edge_index成员
直接在Connection结构体中添加edge_index成员,让Subgraph可以直接识别该属性:
#include <boost/graph/subgraph.hpp> #include <boost/graph/adjacency_list.hpp> struct Component { int vert_id; }; // 自定义结构体包含edge_index成员 struct Connection { int edge_id; std::size_t edge_index; // 必须添加,用于Subgraph的边映射 }; struct NetworkData { int graph_id; }; using Graph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, Component, Connection, NetworkData>; boost::subgraph<Graph> base_graph; int main() { auto& sub_graph = base_graph.create_subgraph(); base_graph[boost::graph_bundle].graph_id = 1; sub_graph[boost::graph_bundle].graph_id = 2; const auto base_vert = boost::add_vertex(base_graph); const auto sub_vert = boost::add_vertex(sub_graph); base_graph[base_vert].vert_id = 10; base_graph[sub_vert].vert_id = 20; const auto [base_edge, a1] = boost::add_edge(base_vert, sub_vert, base_graph); const auto [sub_edge, a2] = boost::add_edge(base_vert, sub_vert, sub_graph); // 直接访问自定义属性,包括edge_index base_graph[base_edge].edge_id = 100; base_graph[base_edge].edge_index = 0; sub_graph[sub_edge].edge_id = 200; return 0; }
说明
- 方案1更符合Boost属性系统的设计,适合需要组合多个属性的场景;方案2更直观,适合简单的自定义属性结构。
- 两种方案都能保留对
graph_bundle的访问权限,同时满足Subgraph的编译要求。 - 不需要放弃自定义属性,只需确保底层图提供
edge_index属性即可。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

