3

У меня возникла проблема с использованием списка смежности библиотеки графики Boost. Кажется, это проблема с круговой зависимостью: У меня есть typedef T шаблона, который использует некоторый класс A. Дополнительно A хранит указатель на объект типа T. Теперь компилятор говорит мне, что T не называет тип.Как решить Boost :: шаблон BGL <-> класс круговой зависимости?

Вот excerptions моих более конкретных файлов:

//graphdefinitions.hpp 
#include "lane.hpp" 
#include "tie.hpp" 

typedef boost::adjacency_list<boost::listS, boost::listS, 
           boost::directedS, Tie, Lane> Map; 
typedef boost::graph_traits<Map>::edge_descriptor edge_descriptor; 

//lane.hpp 
#include "graphdefinitions.hpp" 
class Lane { 
    ... 
    edge_descriptor *left, *right; 
}; 

//tie.hpp 
//no important includes here 
class Tie { 
    ... 
}; 

Как я могу решить эту проблему зависимость/включение порядка?

ДРУГОЙ РЕДАКТИРОВАНИЕ: Я просто подумал, что тип edge_descriptor может быть примитивным, как int. Это решило бы проблему, потому что я смог бы заменить edge_descriptors Lane на простые int-переменные и, таким образом, мог бы удалить включение graphdefinitions.hpp внутри tie.hpp. К сожалению, моя идея была сумасшедшей, и мне нужно найти другое решение. Типы Edge_descriptor, по-видимому, существуют по этой причине ...

ответ

0

У вас есть циркулярные заголовки. Lane включает в себя графические определения, которые включают в себя дорожку, которая включает в себя графические определения и т. Д. Это является причиной вашей проблемы.

Редактировать: Я понял, что это уже упоминалось в OP. Решение этой проблемы - PIMPL.

Редактировать: То, что я на самом деле делаю, это положить typedef внутри класса Lane. Это должно решить проблему самым тщательным образом.

+0

Ровно! Но возникает вопрос: что такое (рабочая!) Альтернатива этому подходу? Я также попытался просто отправить объявление Tie and Lane внутри файла graphdefinitions.hpp, которое также не было принято компилятором. – Bastian

+0

@Bastian: Используйте PIMPL для реализации Lane. – Puppy

+0

@DeadMG: Пожалуйста, взгляните на мое последнее сообщение. – Bastian

0

Я действительно не думаю, что вам нужно что-то особенное в этом коде. Вы должны убедиться, что определения типов, используемых на графике, объявлены (не только для прямого объявления).

+0

Итак, что вы предлагаете, я должен включать файлы заголовков используемых типов?Если я это сделаю, компилятор начнет жаловаться на карту: «не был объявлен» во всех файлах, которые используют Map. – Bastian

+0

Заказ таких зависимостей типов несколько сложнее. Вы должны указать, какие типы определены, в каких заголовочных файлах и как они включены для получения лучшего ответа. –

+0

Хорошо, сделано :-). Структура довольно проста, что не помогает ... – Bastian

0

@DeadMG: Теперь я использовал подход, подобный PIMPL, и я думаю, что это решило мою проблему.

Так что же я сделал? я изменил свой Lane-класс выглядеть так:

//lane.hpp 
#include "graphdefinitions.hpp" 

class LaneSide; 
class Lane { 
public: 
    const LaneSide getLeft() const; 
    const LaneSide getRight() const; 
    ... 
private: 
    LaneSide *left; 
    LaneSide *right; 
    ... 
}; 

И в LaneSide-класс, который практически лишь окольный и удерживающий тип значения, которое я не мог вперед объявить внутри lane.hpp, выглядит это путь:

//laneside.hpp 
class LaneSide 
{ 
    edge_descriptor* edge; 
}; 

Это похоже на трюк компилятора, как я намеревался. Так что спасибо за подсказку DeadMG. Что мне интересно: возможно ли также сохранить объект LaneSide внутри класса Lane не как указатель, а скорее как реальный объект? Я пробовал это первым, но компилятор жаловался на строительство. И мне также интересно, может ли быть способ избежать дополнительного потребления памяти. Когда мой график становится достаточно большим, это может со временем стать актуальным.

7

В BGL есть не-документированный класс признаков, который дает типы дескрипторов вершин и границ для графика adjacency_list, без необходимости знать типы свойств. Он разработан специально для вашего использования. Посмотрите раздел «Ассоциированные типы» http://www.boost.org/doc/libs/1_45_0/libs/graph/doc/adjacency_list.html и обратите внимание, что существует два определения для vertex_descriptor и edge_descriptor; вы можете использовать версии, которые исходят от adjacency_list_traits в определениях ваших пакетов свойств, не вызывая кругового определения.