0

This is my first time coding in C++ and I'm new to the generics in C++. I'm trying to make a little program that basically represents a graph and then traverse that graph using Breadth-First Search. I have made what I think is a generic graph and a generic BFS method. I have included all the code in case there is something I missed.

Here is the exact error:

no matching function for call to 'bfs(const char [4], Graph<std::__cxx11::basic_string<char> >&)
  bfs("One", graph2);

Here is the code:

Graph.h :

#ifndef GRAPH_H
#define GRAPH_H

#include <map>
#include <iostream>
#include <list>
#include <set>

using namespace std;

template <class T>
class Graph{

    private:
        map<T, set<T>> adj_list;

    public:
        Graph();
        void addVertex(T val, set<T> edges);
        set<T> getNeighbours(T vertex);
};

#endif

Graph.cpp :

#include <iostream>
#include "Graph.h"

#include <string>

using namespace std;

template <class T>
Graph<T>:: Graph(){
    ;
}

// add vertex method
template <class T>
void Graph<T>:: addVertex(T val, set<T> edges){
    //if the vertex is already created, the add the list of connections
    //to that vertex, otherwise create a new vertex and create a new set
    //of connections for the vertex
    class map<T, set<T>> :: iterator it = adj_list.find(val);
    if (it != adj_list.end()){
        it->second.insert(edges.begin(), edges.end());
    }
    else{
        adj_list.insert({val, edges});
    }

    // for all the connections, add the vertex to their corresponding
    // connection set
    for (T elem: edges){
        class map<T, set<T>> :: iterator it1 = adj_list.find(elem);
        if (it1 != adj_list.end()){
            it1->second.insert(val);
        }
        else{
            adj_list.insert({elem, {val}});
        }
    }
}

//get neighbours of given vertex
template <class T>
set<T> Graph<T>:: getNeighbours(T vertex){
    return adj_list[vertex];
}

//override << operator. Display the adjacency list
template <class T>
inline ostream& operator<<(ostream& out, const Graph<T>& H){
    out << "{\n";
    for (class map<T, set<T>>::const_iterator it = H.adj_list.begin(), end = H.adj_list.end(); it != end;++it){
        out << to_string(it->first) + " : ";
        for (class set<T>::const_iterator lit = it->second.begin(), lend = it->second.end(); lit!= lend; ++lit){
                if (distance(next(lit), lend) == 0){
                    out << to_string(*lit);
                }
                else{
                    out << to_string(*lit) + ", ";
                }
        }
        out << "\n";
    }

    out << "}" << endl;
    return out;
}

main.cpp :

#include <iostream>
#include "Graph.h"
#include "Graph.cpp"
#include <queue>

using namespace std;

template <class T> 
void bfs(T vertex, Graph<T> graph){
    // queue for bfs and set for checking if nodes have been visited
    queue<T> myQueue; 
    set<T> visited;

    //enqueue the vertex
    myQueue.push(vertex);

    //while there are still nodes to be visited
    while (!myQueue.empty()){

        //get the node to be searched next and add it to visited
        T curr = myQueue.front();
        myQueue.pop();
        visited.insert(curr);
        cout << "Visiting node:" << curr << endl;

        //add all the nodes neighbours to the queue
        for (T elem: graph.getNeighbours(curr)){
            class set<T> :: iterator it = visited.find(elem);

            //if the neighbours of the current node have been visitted then dont add to queue
            if (it == visited.end()){
                myQueue.push(elem);
            }
        }
    }
}


int main(){
    //initialize graph
    Graph<int> graph1;

    //create simple tree
    //          1
    //        /   \
    //       2     3
    //      / \   / \
    //     4   5 6   7
    set<int> connections1 = {2, 3};
    set<int> connections2 = {4, 5};
    set<int> connections3 = {6, 7};

    graph1.addVertex(1, connections1);
    graph1.addVertex(2, connections2);
    graph1.addVertex(3, connections3);

    // perfrom BFS
    bfs(1, graph1);

    Graph<string> graph2;
    set<string> connectionsS1 = {"Two", "Three"};
    set<string> connectionsS2 = {"Four", "Five"};
    set<string> connectionsS3 = {"Six", "Seven"};

    graph2.addVertex("One", connectionsS1);
    graph2.addVertex("Two", connectionsS2);
    graph2.addVertex("Three", connectionsS3);

    bfs("One", graph2);

    return 0;
}
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
Alex
  • 151
  • 8
  • @nick thank you for the suggestion. I removed the namespace part. However im slightly confused as to what code you suggested to transfer. Sorry im kinda new to c++ – Alex Mar 07 '20 at 06:05

1 Answers1

0

The compiler is deducing the template type for bfs from the arguments you pass it. As the first argument is of type const char[4] it chooses that as the template type, this then fails as Graph<string> is not convertible to Graph<const char[4]>.

You can either pass a string as the first argument:

bfs(string("One"), graph2);

Or explicitly tell the compiler the template type:

bfs<string>("One", graph2);

I presume that bfs should also be taking the graphs by reference rather than copying them?

void bfs(T vertex, const Graph<T>& graph)

You shouldn't include .cpp files, I guess you're doing so to avoid linker errors due to Why can templates only be implemented in the header file?

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
  • He actually won't see those linker errors, notice `#include ` – nick Mar 07 '20 at 06:18
  • Hey thanks a lot, I simply needed to add ```bfs(...)``` and it was fixed. Thank you so much. I will also the function to take in the graphs reference instead of a copy. Thanks again – Alex Mar 07 '20 at 16:39