c++undefined-reference

"Undefined reference to" function error


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) {
      [...]
}

Solution

  • 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.