Boost Graph Library无法存储对其他顶点的引用?

时间:2019-05-02 18:35:39

标签: c++ boost graph boost-graph

我正在使用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**

1 个答案:

答案 0 :(得分:1)

如果您将引用存储在类中,则该引用将不再可分配,也不能默认构造。

BGL在这里具有描述符的概念,它是对数组索引之类的东西的抽象,但是与图形表示无关。所以你可以使用它们。

但是请注意失效规则:取决于图形模型[1]。见

PS。如果您知道图形对顶点具有参考稳定性,则可以做您想用原始指针或std::reference_Wrapper<>

替换参考的操作

[1]对于adjacency_list<>,取决于顶点/边缘容器选择器模板参数

演示代码

此代码演示

  • 定义图(具有自引用描述符类型)的机制
  • 如何不填充(请参见// BUG
  • 如何安全地填充/使用属性。

Live On Coliru

#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;
    }
}