0

I am practicing some coding for my exam tomorrow, for some reason I cannot get my program to run. I keep getting an error:

Undefined reference ..pract\ArrayListType\main.cpp:47: error: undefined reference to 'arrayListType<std::string>::Print() const'

Here is my code that I have so far, from what I see it looks pretty much alright. Tried commenting out lines of code to no avail. Don't know what can be wrong.

//Header File:

#ifndef ARRAYLISTTYPE_H
#define ARRAYLISTTYPE_H

using namespace std;


template <class elemType>
class arrayListType
{
public:
    const arrayListType<elemType>& operator= (const arrayListType<elemType>&);
    //Overloads the assignment operator

    bool isEmpty() const;
    //Determines if list is empty

    bool isFull() const;
    //Determines if the list is full

   int listSize() const;
   //Function to determine number of elements in the list

   int maxListsize() const;
   //Function to determine the size of the list

   void Print() const;
   //Function to output the elements in the list

   bool isItemAtEqual(int location, const elemType& item) const;
   //Function to determine if an item entered is the same as another item at a specific location

   void insertAt(int location, elemType& insertItem);
   //Function to insert an item at a specified location

   void insertEnd(const elemType& insertItem);
   //Function to insert an item at the end of the list

   void removeAt(int location);
   //Function to remove an item at a specified location

   void retrieveAt(int location, const elemType& retItem) const;
   //Function to retrieve the item located at the position specified

   void replaceAt(int location, const elemType& repItem);
   //Function to replace a value in the list at a specified location

   void clearList();
   //Function to remove all the elements from the list

   int seqSearch(const elemType& item) const;
   //Function to search the list for a given item

   void insert(const elemType& insertItem);
   //function to insert an item into the list

   void remove(const elemType& removeItem);
   //function to remove an item from the list

   arrayListType(int size = 100);
   //Constructor to initialize the size of the list to 100

   arrayListType(const arrayListType<elemType>& otherList);
   //Copy constructor

  ~arrayListType();
   //Destructor

protected:
   elemType *list;
   int length;
   int maxSize;
};

#endif // ARRAYLISTTYPE_H

//Definition file

#include <iostream>
#include <string>
#include "arraylisttype.h"

using namespace std;

template <class elemType>
bool arrayListType<elemType>::isEmpty() const {
    return (length == 0);
}

template <class elemType>
bool arrayListType<elemType>::isFull() const {
    return (length == maxSize);
}

template <class elemType>
int arrayListType<elemType>::listSize() const {
    return length;
}  

template <class elemType>
int arrayListType<elemType>::maxListsize() const {
    return maxSize;
}
//All the above functions have a running time of O(1) - constant as they will
//produce the same result int eh same time due to only having one line to run.
//_____________________________________________________________________________

template <class elemType> // O(n)
void arrayListType<elemType>::Print() const {
    for (int i = 0; i <length; i++) {
        cout << list[i] << " ";
    }
    cout << endl;
}
//The print function will have a running time of O(n) as it is linear to the size of the list
//and how full the list is.

template <class elemType> // O(1) - constant
bool arrayListType<elemType>::isItemAtEqual(int location, const elemType &item) const {
    return(list[location] == item);
}

template <class elemType> //O(n)
void arrayListType<elemType>::insertAt(int location, elemType &insertItem) {
    if (location < 0 || location >= maxSize)
        cerr << "The position to be inserted at is out of range!";
    else
        if (length >= maxSize)
            cerr << "Cannot insert in a full list";
    else {
        for (int i = length; i > location; i--)
            list[i] = list[i - 1]; // Move elements down.
            list[location] = insertItem; // insert the item at the specified location
            length++;

        }
}

template <class elemType>
void arrayListType<elemType>::insertEnd(const elemType &insertItem) {
    if (length >= maxSize)
        cerr << "Cannot insert in a full list";
    else {
        list[length] = insertItem;
        length++;
    }
}

template <class elemType>
void arrayListType<elemType>::removeAt(int location) {
    if (location < 0 || location >= maxSize)
        cerr << "the location fo the item to be retrieved is out of bounds";
    else {
        for (int i = location; i < length - 1; i++)
            list[i] = list[i+1];
        length--;
    }
}

template <class elemType>
void arrayListType<elemType>::retrieveAt(int location, const elemType& retItem) const {
    if (location < 0 || location >= maxSize)
        cerr << "the location fo the item to be retrieved is out of bounds";
    else (retItem = list[location]);
}

template <class elemType>
void arrayListType<elemType>::replaceAt(int location, const elemType &repItem) {
    if (location < 0 || location >= length)
        cerr << "The location of the item to be replaced is out of bounds.";
    else
        list[location] = repItem;
}

template <class elemType>
void arrayListType<elemType>::clearList() {
    length = 0;
}

template <class elemType>
arrayListType<elemType>::arrayListType(int size) {
    if (size < 0) {
        cerr << "The array size must be positive. creating an array of size 100";
    maxSize = 100;
    }
    else
        maxSize = size;
    length = 0;

    list = new elemType[maxSize];
    assert(list!=NULL);
}

template <class elemType>
arrayListType<elemType>::~arrayListType() {
    delete [] list;
}

template <class elemType>
arrayListType<elemType>::arrayListType(const arrayListType<elemType> &otherList) {
    maxSize = otherList.maxSize;
    length = otherList.length;
    list = new elemType[maxSize];

    for (int j = 0; j < length; j++)
        list[j] = otherList.list[j];
}

template <class elemType>
const arrayListType<elemType>& arrayListType<elemType>::operator=(const arrayListType<elemType>& otherList) {
    if (this != &otherList) {
        delete [] list;
        maxSize = otherList.maxSize;
        length = otherList.length;

        list = new elemType[maxSize];
        assert(list != NULL);

        for (int i = 0; i < length; i++)
            list[i] = otherList.list[i];
    }
    return *this;
}

template <class elemType>
int arrayListType<elemType>::seqSearch(const elemType &item) const {
    int loc;
    bool found = false;

    for (loc = 0; loc < length; loc++)
        if (list[loc] == item) {
            found = true;
            break;
        }
    if (found)
        return loc;
    else
        return -1;
}

template <class elemType>
void arrayListType<elemType>::insert(const elemType &insertItem) {
    int loc;

    if (length == 0)
        list[length++] == insertItem;
    else if (length == maxSize)
        cerr << "Cannot insert into full list.";
    else {
        loc == seqSearch(insertItem);

        if (loc == -1)
            list[length++] = insertItem;
        else
            cerr << "The item to be inserted is already in the list."
                 << "\nNo duplicates are allowed.";
    }
}

template <class elemType>
void arrayListType<elemType>::remove(const elemType &removeItem) {
    int loc;

    if (length == 0)
        cerr << "Cannot delete from an empty list";
    else {
        loc = seqSearch(removeItem);

        if (loc != -1)
            removeItem(loc);
        else
            cout << "The item to be deleted is not int eh list.";
    }
}

//Main

#include <iostream>
#include <string>
#include "arraylisttype.h"

using namespace std;

int main()
{

    arrayListType<int> intList(100);
    arrayListType<string> stringList;

    int number;

    cout << "List 10: Enter 5 integers: ";

    for (int counter = 0; counter < 5; counter++) {
        cin >> number;
        intList.insertAt(counter, number);
    }

    cout << endl;
    cout << "List 19: The list you entered is: ";
    intList.Print();
    cout << endl;

    cout << "Line 20: Enter the item to be deleted: ";
    cin >> number;
    intList.remove(number);
    cout << "Line 23: After removing " << number << ", the lsit is: " << endl;
    intList.Print();
    cout << endl;

    string str;

    cout << "Line 27: Enter 5 strings: ";

    for (int counter = 0; counter < 6; counter++) {
        cin >> str;
        stringList.insertAt(counter, str);
    }

    cout << endl;
    cout << "Line 34: The list you entered is: ";
    stringList.Print();
    cout << endl;

    cout << "Line 37: Enter the string to be deleted: ";
    cin >> str;
    stringList.remove(str);
    cout << "Line 40: After removing " << str << " the list is: " << endl;
    stringList.Print();

    return 0;
}
Mat
  • 202,337
  • 40
  • 393
  • 406
Benefit
  • 19
  • 1
  • 4
  • Besides the above, why do you have the includes listed twice in your "Definition file"? – Mihai Todor Jun 01 '14 at 15:56
  • What was the last change you made, just before the error appeared? And why can't you prepare a [minimal complete example](http://www.sscce.org/)? – Beta Jun 01 '14 at 16:12

1 Answers1

0

When you use templates classes or methods, compiler generates code and compiler needs access to the definition. Therefor you have to put your template method definition to the header files itself and include where you use them. Templates are compile time features and not run-time. Template definitions can not be isolated to cpp files.

Ivan Marinov
  • 2,737
  • 1
  • 25
  • 17