问题
I am trying to create a tree graph using boost::adjacency list
and bundled properties to store the parent for every vertex, I want to store vertex descriptors in a way that they wont invalidate in case I remove a vertex, so I use boost::listS
, the code should look something like this
// custom vertex for tree graphs
struct tree_vertex_info{
// descriptor of parent vertex
boost::graph_traits<Tree>::vertex_descriptor parent_in_tree;
};
// the tree graph type
typedef boost::adjacency_list<boost::listS, boost::listS, boost::directedS
tree_vertex_info, boost::no_property, graph_info> Tree;
But this would not work since Tree must be defined after the struct definition. Is there any other way to do it with bundled properties? I thought I could use an int variable instead of vertex_descriptor type to store vertex_descriptors but since I use boost::listS
to store them I am not sure if can.
回答1:
Theoretically, you could have something like this:
struct tree_vertex_info; // forward-declaration
typedef boost::adjacency_list<
boost::listS, boost::listS, boost::directedS,
tree_vertex_info, boost::no_property, graph_info> Tree;
struct tree_vertex_info {
boost::graph_traits<Tree>::vertex_descriptor parent_in_tree;
};
However, this would require the boost::adjacency_list
class template to support incomplete types (which is what tree_vertex_info
is while there is only a forward-declaration, until the compiler reaches the complete declaration of it). As far as I know, the boost::adjacency_list
class does not support incomplete types (and I know that implementation quite a bit, and I don't think it would work) and it is certainly not guaranteed to support them.
I am actually working on a new version of boost::adjacency_list
which I call boost::adjacency_list_BC
because it's based on Boost.Container containers, and it will support incomplete types. However, it is still kind at a beta stage (follow here or here), and the latest versions of Boost.Container seem to have broken something that I still need to figure out. By the way, I also have a number of BGL tree data-structures as well as new BGL concepts and traits for trees (since you seem to be implementing a kind of tree).
Also, if your motivation for this is really what you have there (the "parent-in-tree"), then you should be using boost::bidirectionalS
in your adjacency_list
to be able to get from a child vertex to its parent (that's what boost::bidirectionalS
means, you get a BidirectionalGraph).
Finally, to actually solve this situation you are in, you'll have to use a type-erasure technique. A simple off-the-shelf way to do it is to use boost::any
to erase the type of the vertex_descriptor, like so:
struct tree_vertex_info{
// descriptor of parent vertex
boost::any parent_in_tree;
};
// the tree graph type
typedef boost::adjacency_list<boost::listS, boost::listS, boost::directedS
tree_vertex_info, boost::no_property, graph_info> Tree;
Just look up Boost.Any for instructions on using it.
I thought I could use an int variable instead of vertex_descriptor type to store vertex_descriptors but since I use listS to store them I am not sure if can.
No, you cannot. You cannot depend on the vertex_descriptor type being anything in particular (e.g., you cannot assume it is an integer type, let alone "int"). I happen to know that vertex_descriptor is usually either an iterator type (such as std::list<T>::iterator
) or a size-type (like std::size_t
or std::vector<T>::size_type
), but that's an implementation detail that you should not and cannot rely on.
来源:https://stackoverflow.com/questions/25985929/bgl-using-bundled-properties-to-store-vertex-descriptor-of-another-vertex