Avinash
Avinash

Reputation: 13257

Graph Template Class

I am working on Graph Template Class. Here is what I written till now.

#ifndef __GRAPH_H__
#define __GRAPH_H__

#include <map>
#include <list>

template <typename _Ty>
class Graph {
private:
    template <typename _Ty>
    class Vertex {
    public:
        Vertex(_Ty in) : m_Label(in) {
        }
        ~Vertex() {
        }
    private:
        _Ty m_Label;
    protected:
    };

public:
    typedef Vertex<_Ty>                       VertexType;
    typedef std::list<VertexType>             AdjListType;
    typedef std::map<VertexType,AdjListType>  GraphType;

public:
    Graph(bool bType = false) : m_Type(bType) {
    }
    ~Graph() {
    }
    void AddEdge(VertexType vLevt, VertexType vRight) {
    }
private:
    // true if bidirectional
    // false if unidirectional.
    bool m_Type; 
    GraphType m_Graph;
protected:
};

#endif

Here is how I am using this class.

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

int main(int argc, char **argv) {
    Graph<int> myGraph;
    myGraph.AddEdge(1,2);

    Graph<char *> myGraph2;
    myGraph2.AddEdge("A","B");

    Graph<std::string> myGraph3;
    myGraph3.AddEdge("A","B");

}

myGraph3 is giving me compilation error. error C2664: 'Graph<_Ty>::AddEdge' : cannot convert parameter 1 from 'const char [2]' to 'Graph<_Ty>::Vertex<_Ty>'

Why this is error , if std::string test = "ABC"; works.

Upvotes: 0

Views: 4369

Answers (2)

highBandWidth
highBandWidth

Reputation: 17321

std::string test = "ABC"; does implicit casting, but it is not happening while calling the function. Try myGraph3.AddEdge(std::string("A"),std::string("B"));.

Function call overloading by defining another function as in

void AddEdge(_Ty vLevt, _Ty vRight) {
        this->AddEdge((VertexType) vLevt, (VertexType) vRight);
    }

helps.

The other issue with your code (at least for gcc) is that you are using the same parameter _Ty in two nested template declarations. The complete, correct code, that works for me is:

#include <map>
#include <list>

template <typename _Ty>
class Graph {
private:
    template <typename _Tyv>
    class Vertex {
    public:
        Vertex(_Tyv in) : m_Label(in) {
        }
        ~Vertex() {
        }
    private:
        _Tyv m_Label;
    protected:
    };

public:
    typedef Vertex<_Ty>                       VertexType;
    typedef std::list<VertexType>             AdjListType;
    typedef std::map<VertexType,AdjListType>  GraphType;

public:
    Graph(bool bType = false) : m_Type(bType) {
    }
    ~Graph() {
    }
    void AddEdge(VertexType vLevt, VertexType vRight) {
    }
    void AddEdge(_Ty vLevt, _Ty vRight) {
        this->AddEdge((VertexType) vLevt, (VertexType) vRight);
    }
private:
    // true if bidirectional
    // false if unidirectional.
    bool m_Type;
    GraphType m_Graph;
protected:
};

Upvotes: 1

Sarfaraz Nawaz
Sarfaraz Nawaz

Reputation: 361352

That requires two implicit conversions

  • First "A" needs to convert into std::string
  • Then std::string needs to convert into Vertex<std::string> (the nested type).

That is chained-implicit-conversion which is not allowed.

But when you write std::string test = "ABC", then only one conversion happens: char[4] to std::string. That is it.

So the solution is, do one conversion yourself by explicitly passing std::string, and let the compiler do the other conversion:

 Graph<std::string> myGraph3;
 myGraph3.AddEdge(std::string("A"),std::string("B"));

Now only one conversion is needed : std::string to Vertex<std::string>. Therefore, it will compile.

Upvotes: 1

Related Questions