Reputation:
I'm getting a really frustrating error that I've been struggling with for some time now.
I had the program working fine before I started changing the data type from int to use templates. This is the error I get:
g++ -c UseList.cpp
g++ -c List.cpp
g++ UseList.o List.o -o UseList
UseList.o: In function `main':
UseList.cpp:(.text+0xee): undefined reference to `List<int>::addtofront(int)'
UseList.cpp:(.text+0x10b): undefined reference to `List<int>::show()'
collect2: ld returned 1 exit status
make: *** [UseList] Error 1
The relevant parts of my code are below. Please let me know what this could be. I'm totally clueless. Thanks!
UseList.cpp:
#include <iostream>
#include <cstdlib>
#include "List.h"
using namespace std;
int main (int argc, char *argv[]) {
cout << "-----------------------------------------" << endl;
cout << "----------------LIST ONE-----------------" << endl;
cout << "-----------------------------------------" << endl;
List<int> *list1;
srand(time(NULL));
cout << "# Add 3 random ints to the front:" << endl;
for(int i=0;i<3;i++){
list1->addtofront(rand() % 10000);
}
list1->show();
}
List.h
#include <iostream>
using namespace std;
#ifndef LIST
#define LIST
template <class L>
class Node {
public:
// constructors and destructors
Node<L>(L data);
Node();
Node<L>(const Node<L> &n);
// components of a node
L data;
Node *next;
Node *prev;
};
template <class L>
class List
{
private:
Node<L> *first;
Node<L> *last;
int num_elements;
public:
// constructors and destructors
List();
~List();
List<L>(const List<L> &l);
List *addtofront(L);
void show();
[...] // unnecessary code removed
};
// #include "List.cpp"
#endif
List.cpp
#include "List.h"
using namespace std;
// -------------------------------------
// ------------Node class---------------
// -------------------------------------
template <class L>
Node<L>::Node(L data_input) {
data = data_input;
next = 0;
prev = 0;
}
template <class L>
Node<L>::Node() {}
template <class L>
Node<L>::Node(const Node<L> &n) {
data = n.data;
next = n.next;
prev = n.prev;
}
// -------------------------------------
// ------------List class---------------
// -------------------------------------
template <class L>
List<L>::List() {
first = NULL;
last = NULL;
num_elements = 0;
}
template <class L>
// Appends data to the front of the list.
List<L> *List<L>::addtofront(L data) {
Node<L> *new_node = new Node<L>(data);
if(first == 0 && last == 0) {
first = new_node;
last = new_node;
} else {
// there will be no previous since
// it is the first
new_node->next = first;
first->prev = new_node;
first = new_node;
}
num_elements++;
}
template <class L>
// Append data to the end of the list.
List<L> *List<L>::addtoback(L data) {
[...]
}
template <class L>
// Return a pointer to a copy of the first item in the list.
Node<L> *List<L>::getfirst() {
[...]
}
template <class L>
// Return a list of all but the first element of the original.
List<L> List<L>::getrest() {
[...]
}
template <class L>
// Print out the data in each node separated by a space.
void List<L>::show() {
Node<L> *current_node = first;
while (current_node != NULL) {
cout << current_node->data << " ";
current_node = current_node->next;
}
cout << endl;
}
template <class L>
// Returns a reversed version of toReverse
List<L> List<L>::reverse(List toReverse) {
[...]
}
Upvotes: 3
Views: 2720
Reputation: 104110
Is this it?
List.h
:
template <class L>
class List
{
/* ... */
List *addtofront(L);
But in List.cpp
:
template <class L>
// Appends data to the front of the list.
List<L> *List<L>::addtofront(L data) {
I see both List*
and List<L> *
.
Upvotes: 0
Reputation: 8704
It should work better if your link line looks like this:
g++ List.o UseList.o -o UseList
Upvotes: 0
Reputation: 7705
You need to put all Template implementations in the header file. As the compiler will not know what type the function might have, he is not able to compile the cpp file. So move all stuff from List.cpp to List.h and it should work.
Upvotes: 2
Reputation: 9080
Template functions must stay in the same data unit you will use it. This is because templates don't directly declare types, they are instantiated when used.
Put template implementation in your header files.
You can rename file "list.cpp" into a file called "list.hpp" and include it in "list.h". Someone use also the convention of "list.inc"
Upvotes: 1