我正在尝试创建
boost::subgraph
的 boost::adjacency_list
,但我在创建时遇到了一个我不明白的错误。专门使用 boost::adjacency_list
的类似代码可以构建并正常工作。
创建
base_graph
的行足以解决该错误,但其余部分演示了我如何单独使用 adjacency_list
,以及我期望如何使用 subgraph
。
示例代码:
struct Component { int vert_id; };
struct Connection { int edge_id; };
struct NetworkData { int graph_id; };
boost::subgraph<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, Component, Connection, NetworkData>> base_graph;
auto& sub_graph = base_graph.create_subgraph();
base_graph[boost::graph_bundle].graph_id;
sub_graph[boost::graph_bundle].graph_id;
const auto base_vert = boost::add_vertex(base_graph);
const auto sub_vert = boost::add_vertex(sub_graph);
base_graph[base_vert].vert_id;
base_graph[sub_vert].vert_id;
sub_graph[base_vert].vert_id;
sub_graph[sub_vert].vert_id;
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);
base_graph[base_edge].edge_id;
base_graph[sub_edge].edge_id;
sub_graph[base_edge].edge_id;
sub_graph[sub_edge].edge_id;
错误日志:
In file included from /.../include/boost/graph/adjacency_list.hpp:255,
from /.../main.cpp:1:
/.../include/boost/graph/detail/adjacency_list.hpp: In instantiation of ‘struct boost::detail::adj_list_any_edge_pmap::bind_<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, Component, Connection, NetworkData>, Connection, boost::edge_index_t>’:
/.../include/boost/graph/detail/adjacency_list.hpp:2801:12: required from ‘struct boost::detail::adj_list_choose_edge_pmap<boost::edge_index_t, boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, Component, Connection, NetworkData>, Connection>’
/.../include/boost/graph/detail/adjacency_list.hpp:2809:16: required from ‘struct boost::detail::adj_list_edge_property_selector::bind_<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, Component, Connection, NetworkData>, Connection, boost::edge_index_t>’
/.../include/boost/graph/properties.hpp:218:12: required from ‘struct boost::detail::edge_property_map<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, Component, Connection, NetworkData>, boost::edge_index_t>’
/.../include/boost/graph/properties.hpp:234:8: required from ‘struct boost::property_map<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, Component, Connection, NetworkData>, boost::edge_index_t, void>’
/.../include/boost/graph/subgraph.hpp:351:64: required from ‘class boost::subgraph<boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS, Component, Connection, NetworkData> >’
/.../main.cpp:46:122: required from here
/.../include/boost/graph/detail/adjacency_list.hpp:2764:33: error: forming reference to void
2764 | typedef value_type& reference;
| ^~~~~~~~~
/.../include/boost/graph/detail/adjacency_list.hpp:2765:39: error: forming reference to void
2765 | typedef const value_type& const_reference;
| ^~~~~~~~~~~~~~~
/.../include/boost/graph/detail/adjacency_list.hpp:2770:17: error: forming reference to void
2770 | type;
| ^~~~
/.../include/boost/graph/detail/adjacency_list.hpp:2774:17: error: forming reference to void
2774 | const_type;
| ^~~~~~~~~~
vert_id
、edge_id
和graph_id
都是概念性的,用于演示我预期如何访问节点/边缘数据。
我发现如果我将
Connection
更改为 boost::property<boost::edge_index_t, std::size_t>
它将构建。但这会阻止访问graph_bundle
,并且导致访问边缘属性不太方便,而且我不知道如何使用boost::property
。
subgraph
,我的问题似乎与subgraph
特别相关。
我使用 GCC13 和 MSVC 时遇到类似的错误。
子图需要vertex_index和edge_index:doc
图形类型建模
和VertexMutableGraph
。此外,该图必须具有内部EdgeMutableGraph
和vertex_index
属性。顶点索引必须由图自动维护,而边索引将由子图类实现分配。edge_index
自动宣传此属性的最简单方法是使用内部属性标签而不是您的捆绑包类型:
// struct Connection { int edge_id; };
using Connection = boost::property<boost::edge_index_t, int>;
确实,经过一些修改,效果如下:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/subgraph.hpp>
struct Component {
int vert_id;
};
#ifndef CUSTOM_PROPERTY_MAPS
using Connection = boost::property<boost::edge_index_t, int>;
#else
struct Connection {
int edge_id;
};
#endif
struct NetworkData {
int graph_id;
};
using G = boost::adjacency_list< //
boost::vecS, boost::vecS, boost::directedS, //
Component, //
Connection, //
NetworkData //
>;
using Sub = boost::subgraph<G>;
int main() {
Sub base_graph;
auto& sub_graph = base_graph.create_subgraph();
get_property(base_graph).graph_id;
get_property(sub_graph).graph_id;
auto const base_vert = add_vertex(base_graph);
auto const sub_vert = add_vertex(sub_graph);
base_graph[base_vert].vert_id;
base_graph[sub_vert].vert_id;
sub_graph[base_vert].vert_id;
sub_graph[sub_vert].vert_id;
auto const [base_edge, a1] = add_edge(base_vert, sub_vert, base_graph);
auto const [sub_edge, a2] = add_edge(base_vert, sub_vert, sub_graph);
#ifndef CUSTOM_PROPERTY_MAPS
auto bmi = get(boost::edge_index, base_graph);
auto smi = get(boost::edge_index, sub_graph);
bmi[base_edge];
smi[sub_edge];
#else
base_graph[base_edge].edge_id;
// base_graph[sub_edge].edge_id; // UB!?
// sub_graph[base_edge].edge_id; // UB!?
sub_graph[sub_edge].edge_id;
#endif
}
您可能会坚持捆绑属性。在这种情况下,您必须调整所需的特征来告诉
subgraph
有关边缘索引的信息:
namespace Lib {
struct Component { int vert_id; };
struct Connection { int edge_id = 0; };
struct NetworkData { int graph_id; };
using G = boost::adjacency_list< //
boost::vecS, boost::vecS, boost::directedS, //
Component, //
Connection, //
NetworkData //
>;
} // namespace Lib
template <>
struct boost::property_map<Lib::G, boost::edge_index_t>
: boost::property_map<Lib::G, decltype(&Lib::Connection::edge_id)> {};
namespace Lib {
// ADL accessible
static inline auto get(boost::edge_index_t, G const& g) { return boost::get(&Connection::edge_id, g); }
static inline auto get(boost::edge_index_t, G& g) { return boost::get(&Connection::edge_id, g); }
using Sub = boost::subgraph<G>;
} // namespace Lib
看到它也住在Coliru