简体   繁体   English

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

[英]Boost Graph Library cannot store references to other vertices?

I'm using BGL to build a graph storing bundled vertices where one type of vertex stores a reference to the other vertex type.我正在使用 BGL 构建一个存储捆绑顶点的图形,其中一种类型的顶点存储对另一种顶点类型的引用。 Both types are handled using std::variant:这两种类型都使用 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>;

Vertices of type complex_node_t are created and stored like this: 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);

Now the problem:现在的问题:

auto pVal = std::get_if<complex_node_t>(&mGraph[vertex]);

assert(pVal->foo1 == true); //OK
assert(pVal->foo2 == 0xDEADBEEF); //OK

But accessing the reference fails (invalid object)!但是访问引用失败(无效对象)!

**pVal->control.enabled -> GARBAGE**

Storing the data by value works - but storing by reference does not.按值存储数据有效 - 但按引用存储则不行。

What am I doing wrong?我究竟做错了什么?

PS: My example is very reduced of course... that means the vertices I want to store via reference are much bigger. PS:我的例子当然非常少......这意味着我想通过引用存储的顶点要大得多。

EDIT编辑

I now changed my code:我现在改变了我的代码:

struct complex_node_t {
    bool foo1;
    size_t foo2;
    std::reference_wrapper<simple_node_t> control;
};

and try to access elements:并尝试访问元素:

if (pVal->control.get().enabled) -> **STILL GARBAGE**

If you store a reference inside a class, it is no longer assignable nor default-constructible.如果您将引用存储在类中,则它不再是可分配的,也不再是默认构造的。

BGL Has the concept of a descriptor here, it's an abstraction of something like an array index, but independent of the graph representation. BGL 这里有描述符的概念,它是对数组索引之类的东西的抽象,但独立于图形表示。 So you could use those.所以你可以使用这些。

Beware of invalidation rules though: depending on the graph model[1].不过要注意失效规则:取决于图模型[1]。 See

PS.附注。 if you know your graph has reference stability for vertices you could do what you want replacing the reference with raw pointers or std::reference_Wrapper<>如果您知道您的图形具有顶点的引用稳定性,您可以做您想做的事情,用原始指针或std::reference_Wrapper<>替换引用


[1] in the case of adjacency_list<> it depends on the vertex/edge container selector template arguments [1] 在adjacency_list<>的情况下,它取决于顶点/边容器选择器模板参数

Demo Code演示代码

This code demonstrates这段代码演示了

  • the mechanics of defining the graph (with self-referential descriptor types)定义图的机制(使用自引用描述符类型)
  • how NOT to populate (see // BUG )如何不填充(见// BUG
  • how to safely populate/use the attributes instead.如何安全地填充/使用属性。

Live On Coliru 住在 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;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM