2

Edit 1: This question what closed as a duplicate. While the suggested duplicate What is an undefined reference/unresolved external symbol error and how do I fix it? addresses the possible causes of such "undefined symbol errors" in a general, and very comprehensive, manner it does not address the exact cause of the error in my sitution. While it may be possible to reason based on the information provided in the linked post in a way that hones in on my problem, it is beyond me to do so and I would require further assistance. For these reasons, I believe that it is inaccurate to treat this is a duplicate question.

Edit 2: Reading Kerndog73's comment about putting all template functions into header files the following accepted answer to the following question Why can templates only be implemented in the header file? answers my question.

I am implementing a graph based on adjaency sets and have run into the following compiler error:

Undefined symbols for architecture x86_64:

"Vertex<int, int>::addEdge(Edge<int>)", referenced from:
      HashGraph<int, int>::addEdge(int, int) in hash-graph-test-99739e.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

and I cannot manage to figure out why Vertex<int, int>::addEdge(Edge<int>) would be undefined.

Below is the code that I believe to be relevent for this error:

hash-graph.cpp

/**
 * Adds a non-existent, directed, edge from a "tail vertex" to a 
 * "head vertex" by modifying the adjacency set of the "tail vertex".
 * If the passed in edge already exists, the method instead returns
 * false.
 * 
 * @param   tail  the vertex at which the edge starts
 * @param   head  the vertex at which the edge ends
 * @return  false if edge already exists, else true
*/ 
template <class K, class V>
bool HashGraph<K, V>::addEdge(K tail, K head)
{
   Vertex<K, V> vTail = getVertex(tail);
   Edge<K> edge(head);
   return vTail.addEdge(edge);
}

template <class K, class V>
Vertex<K, V> HashGraph<K, V>::getVertex(K key)
{
   auto searchResult = graph.find(key);
   if (searchResult != graph.end())
      return searchResult->second;
   throw "Vertex not found.";
}

edge.hpp

template <class K>
class Edge
{
   private:
      static const int NO_COST = -1;
      K head;
      double cost;

   public:
      Edge(K head);
      Edge(K head, double cost);

      K getHead() const {return head;}
      double getCost() const {return cost;}

      bool operator==(const Edge<K> &other) const
      {
         return (head == other.head && cost == other.cost);
      }
};

template <class K>
Edge<K>::Edge(K head)
{
   this->head = head;
   cost = NO_COST;
}

vertex.hpp

template <class K, class V>
class Vertex
{
    private:
        K key;
        V value;
        std::unordered_set<Edge<K>> adjacencySet;

    public:
        Vertex(K key, V value);
        K getKey() const {return key;} // TODO: what does const do here exaclty>
        V getValue() const {return value;}
        bool addEdge(Edge<K> edge);

        // TODO: what does const do here exactly
        bool operator==(const Vertex<K, V> &anotherVertex) const
        {
            return key == anotherVertex.key;
        }
};

vertex.cpp

template <class K, class V>
bool Vertex<K, V>::addEdge(Edge<K> edge)
{
   if (adjacencySet.find(edge) != adjacencySet.end())
   {
      adjacencySet.insert(edge);
      return true;
   }
   return false;
}

Note that a lot of code has been omitted that exists in the various files. Personally, I am a bit suspicious of the getVertex method, but have not been able to find anything concrete yet.

Could someone help me understand why this error is being thrown?

mooncow
  • 413
  • 4
  • 11
  • First they close my question as a duplicate of an unrelated question, then they close this question as a duplicate of an unrelated question. For heaven's sake, would you read the question before you close it! – Indiana Kernick Feb 21 '19 at 07:32
  • Since I am unable to write an answer I will answer your question in a comment. Put all of your template functions in header files. Delete vertex.cpp and hash-graph.cpp and move all of the code into the header files. I don't really have enough room to tell you why this solves the problem. – Indiana Kernick Feb 21 '19 at 07:36
  • @Kerndog73, Unrelated? [I beg to differ.](https://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix/12574417#12574417) – chris Feb 21 '19 at 07:39
  • @chris I only read the first couple of answers. Didn't see that one! – Indiana Kernick Feb 21 '19 at 07:40
  • 1
    @Kerndog73, For reference, the accepted answer includes a nice table of contents along with its explanation of what the error message means. – chris Feb 21 '19 at 07:41
  • Perhaps a better duplicate would be [this question about templates](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file?rq=1) – Angew is no longer proud of SO Feb 21 '19 at 07:48
  • 2
    @Kerndog73 Deleting ``vertex.cpp`` and ``hash-graph.cpp`` and putting the code from them into the header files did indeed fix the problem. – mooncow Feb 21 '19 at 07:59
  • @Angew Yes, https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file?rq=1 is a better duplicate. I believe that Kerndog73's comment in combination with the linked question answers my question. – mooncow Feb 21 '19 at 08:02
  • @mooncow Are you sure you get the same error message (the `Undefined symbols for architecture x86_64`) after you moved the definition to the headers? I'm pretty sure that you now have other errors, like **duplicate** symbols, but not **undefined** symbols . – t.niese Feb 21 '19 at 08:54
  • @t.niese I got no error messages after moving the definition into the headers. – mooncow Feb 21 '19 at 15:05

0 Answers0