I have a problem with using the adjacency-list of the Boost Graphics Library. It seems to be a circular dependency problem:
I have a typedef T of a template which uses some class A. Additionally A stores a pointer to an object of type T. Now the compiler tells me, that T does not name a type.
Here are excerptions of my more concrete files:
//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 {
...
};
How do I solve this dependency / inclusion-order problem?
ANOTHER EDIT:
I just had the idea that the type of an edge_descriptor might be a primitive one like int. That would have solved the problem because I would have been able to replace the edge_descriptors of Lane by plain int-variables and thus could have removed the inclusion of graphdefinitions.hpp inside tie.hpp. Unfortunately my idea was cra* and I have to find another solution. Edge_descriptor types seem to be there for a reason...
You have circularly included headers. Lane includes graphdefinitions, which includes lane, which includes graphdefinitions, etc. This is the cause of your problem.
Edit: I realized this was already mentioned in the OP. The solution to this problem is PIMPL.
Edit: What I would actually do is put the typedef inside the Lane class. That should solve the problem in the neatest way.
There is a not-well-documented traits class in BGL that gives the vertex and edge descriptor types for an adjacency_list
graph without needing to know the property types. It is designed for exactly the use case you have. Look in the "Associated Types" section of http://www.boost.org/doc/libs/1_45_0/libs/graph/doc/adjacency_list.html and notice that there are two definitions for vertex_descriptor
and edge_descriptor
; you can use the versions that come from adjacency_list_traits
in the definitions of your property bundles without causing a circular definition.
I really don't think you need anything special about this code. You have to make sure the definitions of the types used in the graph are declared (not only forward-declared).
@DeadMG: I used a PIMPL-like approach now and I think that this solved my problem.
So what did I do?
I changed my Lane-class to look this way:
//lane.hpp
#include "graphdefinitions.hpp"
class LaneSide;
class Lane {
public:
const LaneSide getLeft() const;
const LaneSide getRight() const;
...
private:
LaneSide *left;
LaneSide *right;
...
};
And the LaneSide-class which is practically just an indirection and holds the type of value that I could not forward declare inside of lane.hpp, looks this way:
//laneside.hpp
class LaneSide
{
edge_descriptor* edge;
};
This seems to trick the compiler as I intended to. So thank you for the hint DeadMG. What I was wondering: Is it also possible to store a LaneSide-object inside of the Lane-class not as a pointer but rather as a real object? I tried this first but the compiler complained about the construction. And I'm also wondering whether there might be a way to avoid the additional memory consumption. When my graph gets big enough this might eventually become relevant.