inconnu26
inconnu26

Reputation: 45

Class with vector of struct, which contains the same class

I have a class Node, and a struct Edge. But when the struct is written before the class, the struct complains for no knowing what is distance. It is the same for the the way around, when the struct is define after, the classe complain for not knowing what is a Edge (the type of the vector).

//This is my header file

typedef struct Edge Edge;
struct Edge{

   Node node;
   int distance;

};

class Node
{

  private:

  std::vector<Edge> vectorOfEdges;

};

How do I get around this error? Thank you.

Upvotes: 1

Views: 2062

Answers (2)

Kerrek SB
Kerrek SB

Reputation: 477010

There is no way around this if you literally want to keep the code as it is: As far as the standard is concerned, std::vector<T> might as well literally contain elements of type T, and thus you have a cyclic mutual dependence whereby Edge contains a Node and Node contains an Edge, which does not make sense.

(The actual wording is that a instantiating a standard library container template on an incomplete type is undefined behaviour.)

The typical way around this is the PIMPL idiom, by which you only provide a pointer to the element:

struct Edge;

class Node
{
    std::unique_ptr<std::vector<Edge>> pVecImpl;
public:
    Node() : pVecImpl(::new std::vector<Edge>) { }
    // ...
};

struct Edge
{
    // as before
};

Herb Sutter's GotW #101 describes a neat solution to abstract this pattern in a clean and attractive fashion.

(Alternatively you can also make Edge::node into a pointer.)

Upvotes: 2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726539

Your definition is circular: it tries to put a Node inside an Edge, and a vector of edges inside a Node. You need to make one of these a pointer, for example, like this:

class Node;
struct Edge{
    Node *node;
    int distance;
};
class Node {
private:
    std::vector<Edge> vectorOfEdges;
};

P.S. You were missing a semicolon after the struct.

Upvotes: 1

Related Questions