简体   繁体   中英

BGL: Unable to access bundled vertex properties

I have a dummy class defined as such:

class Graph
{
  friend std::ostream& operator<<(std::ostream&, const ArchGraph &);

  struct VertexProperty;
  struct EdgeProperty;

  typedef boost::vecS vertex_selector;
  typedef boost::vecS edge_selector;

  typedef boost::property<boost::vertex_name_t, VertexProperty> vertex_property;
  typedef boost::property<boost::edge_name_t, EdgeProperty> edge_property;

  typedef boost::adjacency_list<
    vertex_selector, edge_selector, boost::bidirectionalS,
    vertex_property, edge_property> adjacency_type;

  typedef size_t size_type;

  struct VertexProperty {
    size_type id;
  };

  struct EdgeProperty {
    adjacency_type::edges_size_type index;
    size_type id;
  };

public:
  void foo() const;

private:
  adjacency_type _adj;
};

And in it's foo method I try to iterate over all vertices in the adjacency list _adj and print the id member of each vertex property:

void Graph::foo() const
{
  for (auto v : boost::make_iterator_range(boost::vertices(_adj))) {
    std::cout << _adj[v].id;
  }
}

This does not compile, apparently _adj[v] has type const struct boost::no_property which is not what I expected.

This seems a little ridiculous to me, seeing as there seem to many examples floating around which seem take exactly this approach.

I'm using Boost 1.67.0, can anybody enlighten me as to what I'm doing wrong here? The documentation is not very helpful in this regard.

Using property<tag, type> is not a bundled property¹.

All those examples you are talking about will be using this style:

typedef boost::adjacency_list<
    edge_selector, vertex_selector, boost::bidirectionalS,
    VertexProperty, EdgeProperty> adjacency_type;

Note you had edge_selector and vertex_selector reversed.

Of course, now you can't forward-declare. So you need to find another way to acces the graph traits before you have defined the adjacency_list itself:'

typedef boost::adjacency_list_traits<edge_selector, vertex_selector, boost::bidirectionalS> traits;

So you can have the size types ahead of time:

typedef traits::vertices_size_type size_type;
typedef traits::edges_size_type    edges_size_type;

Demo

Live On Coliru

#include <boost/graph/adjacency_list.hpp>
#include <iostream>

struct ArchGraph;

class Graph
{
    friend std::ostream& operator<<(std::ostream&, const ArchGraph &);

    struct VertexProperty;
    struct EdgeProperty;

    typedef boost::vecS vertex_selector;
    typedef boost::vecS edge_selector;

    typedef boost::adjacency_list_traits<edge_selector, vertex_selector, boost::bidirectionalS> traits;

    typedef traits::vertices_size_type size_type;
    typedef traits::edges_size_type    edges_size_type;

    struct VertexProperty {
        size_type id;
    };

    struct EdgeProperty {
        edges_size_type index;
        size_type id;
    };

    typedef boost::adjacency_list<
        edge_selector, vertex_selector, boost::bidirectionalS,
        VertexProperty, EdgeProperty> adjacency_type;

  public:
    Graph() : _adj(3) {
        for (auto vd : boost::make_iterator_range(vertices(_adj)))
            _adj[vd].id = (vd+1)*10;
    }
    void foo() const;

  private:
    adjacency_type _adj;
};

void Graph::foo() const
{
    for (auto v : boost::make_iterator_range(boost::vertices(_adj))) {
        std::cout << _adj[v].id << " ";
    }
}

int main() {
    Graph g;

    g.foo();
}

Prints

10 20 30 

¹ (On the contrary, it's the old-style what's called "interior property" if I remember correctly)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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