BGL: невозможно получить доступ к связанным свойствам вершин - PullRequest
0 голосов
/ 04 июля 2018

У меня есть фиктивный класс, определенный так:

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

И в этом foo методе я пытаюсь перебрать все вершины в списке смежности _adj и распечатать id член каждого свойства вершины:

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

Это не компилируется, по-видимому, _adj[v] имеет тип const struct boost::no_property, что не соответствует ожиданиям.

Мне это кажется немного нелепым, поскольку, как представляется, существует множество примеров, которые, кажется, используют именно этот подход.

Я использую Boost 1.67.0, кто-нибудь может объяснить мне, что я здесь делаю неправильно? Документация не очень полезна в этом отношении.

1 Ответ

0 голосов
/ 05 июля 2018

Использование property<tag, type> означает , а не связанное свойство¹.

Все эти примеры, о которых вы говорите, будут использовать этот стиль:

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

Примечание у вас edge_selector и vertex_selector в обратном порядке.

Конечно, теперь вы не можете объявить форвард. Поэтому вам нужно найти другой способ получить доступ к признакам графа, прежде чем вы определите сам список adjacency_list: '

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;

Демо

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();
}

печать

10 20 30 

¹ (Напротив, это старый стиль, который называется "внутренняя собственность", если я правильно помню)

...