Boost Graph Library 无法存储对其他顶点的引用?
Boost Graph Library cannot store references to other vertices?
我正在使用 BGL 构建一个图来存储捆绑的顶点,其中
一种类型的顶点存储对另一种顶点类型的引用。两种类型都使用 std::variant:
处理
struct simple_node_t {
size_t enabled;
};
struct complex_node_t {
bool foo1;
size_t foo2;
simple_node_t& control;
};
using vertex_t = std::variant<simple_node_t, complex_node_t>;
using netListGraph_t = boost::adjacency_list<
boost::vecS,
boost::vecS,
boost::undirectedS,
vertex_t>;
complex_node_t 类型的顶点是这样创建和存储的:
// Create node
complex_node_t cpx = {
true,
0xDEADBEEF,
std::get<simple_node_t>(mGraph[desc_to_simple_vertex])
};
// Add complex_node_t to graph
vertex_t vtx(cpx);
auto vertex = boost::add_vertex(vtx, mGraph);
现在的问题:
auto pVal = std::get_if<complex_node_t>(&mGraph[vertex]);
assert(pVal->foo1 == true); //OK
assert(pVal->foo2 == 0xDEADBEEF); //OK
但是访问引用失败(无效对象)!
**pVal->control.enabled -> GARBAGE**
按值存储数据有效 - 但按引用存储无效。
我做错了什么?
PS:我的示例当然非常精简...这意味着我想通过引用存储的顶点要大得多。
编辑
我现在更改了我的代码:
struct complex_node_t {
bool foo1;
size_t foo2;
std::reference_wrapper<simple_node_t> control;
};
并尝试访问元素:
if (pVal->control.get().enabled) -> **STILL GARBAGE**
如果您将引用存储在 class 中,则它不再可赋值也不可默认构造。
BGL 这里有描述符的概念,它是类似于数组索引的抽象,但独立于图形表示。所以你可以使用那些。
注意无效规则:取决于图形模型[1]。参见
- Should I use iterators or descriptors to keep a reference on an edge or vertex?
PS。如果你知道你的图对顶点有参考稳定性,你可以可以做你想做的用原始指针或std::reference_Wrapper<>
替换参考
[1] 在 adjacency_list<>
的情况下,它取决于 vertex/edge 容器选择器模板参数
演示代码
此代码演示
- 定义图形的机制(使用自引用描述符类型)
- 如何不填充(参见
// BUG
)
- 如何安全地 populate/use 属性。
#include <boost/graph/adjacency_list.hpp>
#include <variant>
using base_traits = boost::graph_traits<boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS> >;
struct simple_node_t {
size_t enabled = 0;
};
struct complex_node_t {
bool foo1 = false;
size_t foo2 = 0;
base_traits::vertex_descriptor control {};
};
using vertex_t = std::variant<simple_node_t, complex_node_t>;
using netListGraph_t = boost::adjacency_list<
boost::vecS,
boost::vecS,
boost::undirectedS,
vertex_t>;
int main() {
{
netListGraph_t g;
auto control = add_vertex(simple_node_t{12}, g);
// BUG HERE:
add_vertex(complex_node_t{ true, 42, control }, g); // whoops, might invalidate `control`
}
{
netListGraph_t g(10);
auto control = vertex(6, g);
g[control] = simple_node_t{12};
auto other = vertex(4, g);
g[other] = complex_node_t{ true, 42, control }; // fine
// also fine:
std::get<complex_node_t>(g[other]).control = control;
}
}
我正在使用 BGL 构建一个图来存储捆绑的顶点,其中 一种类型的顶点存储对另一种顶点类型的引用。两种类型都使用 std::variant:
处理struct simple_node_t {
size_t enabled;
};
struct complex_node_t {
bool foo1;
size_t foo2;
simple_node_t& control;
};
using vertex_t = std::variant<simple_node_t, complex_node_t>;
using netListGraph_t = boost::adjacency_list<
boost::vecS,
boost::vecS,
boost::undirectedS,
vertex_t>;
complex_node_t 类型的顶点是这样创建和存储的:
// Create node
complex_node_t cpx = {
true,
0xDEADBEEF,
std::get<simple_node_t>(mGraph[desc_to_simple_vertex])
};
// Add complex_node_t to graph
vertex_t vtx(cpx);
auto vertex = boost::add_vertex(vtx, mGraph);
现在的问题:
auto pVal = std::get_if<complex_node_t>(&mGraph[vertex]);
assert(pVal->foo1 == true); //OK
assert(pVal->foo2 == 0xDEADBEEF); //OK
但是访问引用失败(无效对象)!
**pVal->control.enabled -> GARBAGE**
按值存储数据有效 - 但按引用存储无效。
我做错了什么?
PS:我的示例当然非常精简...这意味着我想通过引用存储的顶点要大得多。
编辑
我现在更改了我的代码:
struct complex_node_t {
bool foo1;
size_t foo2;
std::reference_wrapper<simple_node_t> control;
};
并尝试访问元素:
if (pVal->control.get().enabled) -> **STILL GARBAGE**
如果您将引用存储在 class 中,则它不再可赋值也不可默认构造。
BGL 这里有描述符的概念,它是类似于数组索引的抽象,但独立于图形表示。所以你可以使用那些。
注意无效规则:取决于图形模型[1]。参见
- Should I use iterators or descriptors to keep a reference on an edge or vertex?
PS。如果你知道你的图对顶点有参考稳定性,你可以可以做你想做的用原始指针或std::reference_Wrapper<>
[1] 在 adjacency_list<>
的情况下,它取决于 vertex/edge 容器选择器模板参数
演示代码
此代码演示
- 定义图形的机制(使用自引用描述符类型)
- 如何不填充(参见
// BUG
) - 如何安全地 populate/use 属性。
#include <boost/graph/adjacency_list.hpp>
#include <variant>
using base_traits = boost::graph_traits<boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS> >;
struct simple_node_t {
size_t enabled = 0;
};
struct complex_node_t {
bool foo1 = false;
size_t foo2 = 0;
base_traits::vertex_descriptor control {};
};
using vertex_t = std::variant<simple_node_t, complex_node_t>;
using netListGraph_t = boost::adjacency_list<
boost::vecS,
boost::vecS,
boost::undirectedS,
vertex_t>;
int main() {
{
netListGraph_t g;
auto control = add_vertex(simple_node_t{12}, g);
// BUG HERE:
add_vertex(complex_node_t{ true, 42, control }, g); // whoops, might invalidate `control`
}
{
netListGraph_t g(10);
auto control = vertex(6, g);
g[control] = simple_node_t{12};
auto other = vertex(4, g);
g[other] = complex_node_t{ true, 42, control }; // fine
// also fine:
std::get<complex_node_t>(g[other]).control = control;
}
}