0

I am trying to write an adjacency list to save the graph.
And here is my code, the class Graph has a member called Node. The Node can save any type of message, and many children with the cost to them.
After Node thers is a nodes member to save all of the node in graph.

template<typename T>
class Graph {
public:
    struct Node {
        using Ptr = std::shared_ptr<Node>;
        T val;
        std::vector<std::pair<Ptr, int>> children;
        Node() {}
        Node(T data) : val(data) , children() {}
    };

    typename std::vector<Graph<T>::Node::Ptr> nodes;
    Graph(){}
    Graph(size_t n) : nodes(n) {
        for(auto node : nodes)
            node = std::make_shared<Node>();
    }
};

Problem
typename std::vector<Graph<T>::Node::Ptr> nodes;
My compiler doesnot think Ptr is a valid type, here is the error

type/value mismatch at argument 1 in template parameter list for ‘template<class _Tp, class _Alloc> class std::vector’

I can put the declaration of Node out of the Graph and make it a template to solve this problem, but why cannot this?

System Info

  • Ubuntu 20.04 (WSL2)
  • g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0

Already read

  • 1
    `typename` at a wrong place. Try `std::vector::Node::Ptr>`. – n. 'pronouns' m. Sep 08 '20 at 07:30
  • aside: `auto node` is a *copy* of a `Node::Ptr`, and not a *reference*, so all your `Node`s will be destroyed as soon as they are constructed – Caleth Sep 08 '20 at 08:33
  • aside 2: Why not have `std::vector nodes` and have non owning pointers in `Node::children`? In either case you will have to clean up pointers to nodes that you remove from your graph. – Caleth Sep 08 '20 at 08:39

3 Answers3

1

use shared_ptr replace the using Ptr = std::shared_ptr;

template<typename T>
class Graph {
public:

    struct Node {
        T val;
        std::vector<std::pair<std::shared_ptr<Node>, int>> children;
        Node() {}
        Node(T data) : val(data), children() {}
    };

    typename std::vector<std::shared_ptr<Node>> nodes;

    Graph() {}
    Graph(size_t n) : nodes(n) {
        for (auto node : nodes)
            node = std::make_shared<Node>();
    }
};

or

template<typename T>
class Graph {
public:
    struct Node {
        using Ptr = std::shared_ptr<Node>;

        T val;
        std::vector<std::pair<Ptr, int>> children;
        Node() {}
        Node(T data) : val(data), children() {}
    };
    std::vector<typename Graph<T>::Node::Ptr> nodes;
    Graph() {}
    Graph(size_t n) : nodes(n) {
        for (auto node : nodes)
            node = std::make_shared<Node>();
    }
};

harkhuang
  • 34
  • 5
0

As suggested by n-pronouns-m, replace typename std::vector<Graph<T>::Node::Ptr> nodes; with std::vector<typename Graph<T>::Node::Ptr> nodes;

SCCC
  • 303
  • 2
  • 13
0

The problem is that in std::vector<Graph<T>::Node::Ptr>, it is not known that Graph<T>::Node::Ptr is a type, so the assumption is that it is a value.

That's the part that needs typename, but since it's defined within Graph<T>, you don't need all those qualifications:

std::vector<typename Node::Ptr> nodes;

(Note that typename std::vector<int> vi; is valid even though the typename is pointless.)

molbdnilo
  • 55,783
  • 3
  • 31
  • 71