Linker error: Undefined reference to member function for class with template parameter

Hi everyone,

I have a small implementation for a doubly linked list. The linked list class takes a template parameter. I'm hitting the following linker error when building my programs:


/tmp/cc1tFbiv.o: In function `main':
main.cpp:(.text+0x42): undefined reference to `DoublyLinkedList<int>::addToDLLTail(int const&)'
collect2: ld returned 1 exit status


Could someone let me know what did I go wrong and how to fix the error? Thanks a lot!



Here's my implementation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135

[dList.h]

#ifndef __DOUBLY_LINKED_LIST__
#define __DOUBLY_LINKED_LIST__

#include <iostream>
using namespace std;

template<class T>
class ListNode {
public:
  ListNode() : prev(0), next(0) {}
  ListNode(const T& el, ListNode *p = 0, ListNode *n = 0) : 
          info(el), prev(p), next(n)  {}
  ~ListNode();
  T info; 
  ListNode *prev, *next;
};

template<class T>
class DoublyLinkedList {
public:
  DoublyLinkedList() : head(0), tail(0) , nodeCount(0) {}
  ~DoublyLinkedList(); 

  bool isEmpty() const { return nodeCount == 0; }
  void addToDLLTail (const T&);
  void addToDLLHead (const T&);
  T deleteFromDLLTail();
//  T deleteFromDLLHead();
protected:
  ListNode<T> *head, *tail;
  long nodeCount;
  friend ostream& operator<< (ostream& os, const DoublyLinkedList<T>& dll) {
    for (ListNode<T> *tmp = dll.head; tmp != 0; tmp = tmp->next)
      os << tmp->info << ' ';
    return os; 
  } 
};

#endif

[dList.cpp]

#include "dList.h"

template<class T>
DoublyLinkedList<T>::~DoublyLinkedList() {
  ListNode<T> *tmp;
  while (nodeCount--) {
    tmp = head->next;
    tmp->prev = 0;
    delete head;
    head = tmp;
  }
  head = tail = 0;
}

template<class T>
void DoublyLinkedList<T>::addToDLLTail(const T& el) {
  ListNode<T> *tmp; 
  
  tmp = new ListNode<T>(el, tail, 0);
  if (nodeCount > 0) {
    tail->next = tmp;
    tail = tmp;
  }  
  else { 
    head = tail = tmp; 
    head->prev = 0;
    head->next = 0;
    tail->prev = 0;
    tail->next = 0;
  }
  nodeCount++;
}

template<class T>
void DoublyLinkedList<T>::addToDLLHead(const T& el) {
  ListNode<T> *tmp;
  tmp = new ListNode<T>(el, 0, head);

  if (nodeCount >0) {
    head->prev = tmp;
    head = tmp;
  }
  else {
    head = tail = tmp;
    head->prev = 0;
    head->next = 0;
    tail->prev = 0;
    tail->next = 0;
  }
  nodeCount++;
}

template<class T>
T DoublyLinkedList<T>::deleteFromDLLTail() {
  ListNode<T> *tmp;
  
  T el = tail->info; 
  tmp = tail->prev;
  delete tail;
  if (nodeCount == 1) {
    head = tail = 0;
  }
  else { 
    tmp->next = 0;
    tail = tmp; 
  } 
  nodeCount--;
  return el;
}

[main.cpp]

#include <iostream>
using namespace std;
#include "dList.h"

#define LISTSIZE 100

int main(int argc, char *argv[]) {
  DoublyLinkedList<int> *dll;

  dll = new DoublyLinkedList<int>;

  for (int i = 1; i <= LISTSIZE; i++) 
    dll->addToDLLTail(i);
  cout << &dll; 

  return 0;
}


[compiler]
gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)

[command]
g++ main.cpp dList.cpp
Template function declarations and implementations must appear in the same file.
Or add #include "dList.cpp" in main cpp, it may be work.
Why would you need to implement your own doubly linked list? Is this for testing / learning?
Thanks all. Your solutions fix my issue. I tried helios's suggestion by putting the class template declaration and implementation in the same file. The linker error is resolved. I also tried melan's suggestion by including dList.cpp in the main file. The linker error no longer exists. Thanks for your expert suggestion.

I found the following description on the template on this website:

From the point of view of the compiler, templates are not normal functions or classes. They are compiled on demand, meaning that the code of a template function is not compiled until an instantiation with specific template arguments is required... Because templates are compiled when required, this forces a restriction for multi-file projects: the implementation (definition) of a template class or function must be in the same file as its declaration. That means that we cannot separate the interface in a separate header file, and that we must include both interface and implementation in any file that uses the templates.
Topic archived. No new replies allowed.