Doubly Linked List : Unresolved Externals
<blockquote>
  <p><strong>Possible Duplicate:</strong><br>
  <a href="http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file">Why can templates only be implemented in the header file?</a><br>
  <a href="http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix">What is an undefined reference/unresolved external symbol error and how do I fix it?</a>  </p>
</blockquote>



<p>Again this is a homework assignment and my instructor has given us plenty of feedback but I am still at a lost for this compile issue. </p>

<p>When I place the main function inside the implementation file the program compiles and works perfectly.  However when I place the main function into main.cpp the compiler complains:</p>

<pre><code> unresolved external symbol "public: __thiscall doublyLinkedList&lt;int&gt;::doublyLinkedList&lt;int&gt;(void)" (??0?$doublyLinkedList@H@@QAE@XZ) referenced in function
</code></pre>

<h1>Header File</h1>

<pre><code>#ifndef H_doublyLinkedList
#define H_doublyLinkedList

#include &lt;iostream&gt;
#include &lt;cassert&gt;

using namespace std;

//Definition of the node
template &lt;class Type&gt;
struct nodeType
{  
   Type info;
   nodeType&lt;Type&gt; *next;
   nodeType&lt;Type&gt; *back;  
};

template &lt;class Type&gt;
class doublyLinkedList
{
public:
const doublyLinkedList&lt;Type&gt;&amp; operator=
                       (const doublyLinkedList&lt;Type&gt; &amp;);
  //Overload the assignment operator.

void initializeList();
  //Function to initialize the list to an empty state.
  //Postcondition: first = NULL; last = NULL; count = 0;

bool isEmptyList() const;
  //Function to determine whether the list is empty.
  //Postcondition: Returns true if the list is empty,
  //               otherwise returns false.

void destroy();
  //Function to delete all the nodes from the list.
  //Postcondition: first = NULL; last = NULL; count = 0;

void print() const;
  //Function to output the info contained in each node.

void reversePrint() const;
  //Function to output the info contained in each node
  //in reverse order.

int length() const;
  //Function to return the number of nodes in the list.
  //Postcondition: The value of count is returned.

Type front() const;
  //Function to return the first element of the list.
  //Precondition: The list must exist and must not be empty.
  //Postcondition: If the list is empty, the program 
  //               terminates; otherwise, the first 
  //               element of the list is returned. 

Type back() const;
  //Function to return the last element of the list.
  //Precondition: The list must exist and must not be empty.
  //Postcondition: If the list is empty, the program
  //               terminates; otherwise, the last
  //               element of the list is returned. 

bool search(const Type&amp; searchItem) const;
  //Function to determine whether searchItem is in the list.
  //Postcondition: Returns true if searchItem is found in
  //               the list, otherwise returns false.

void insert(const Type&amp; insertItem);
  //Function to insert insertItem in the list.
  //Precondition: If the list is nonempty, it must be in
  //              order.
  //Postcondition: insertItem is inserted at the proper place
  //               in the list, first points to the first
  //               node, last points to the last node of the
  //               new list, and count is incremented by 1.

void deleteNode(const Type&amp; deleteItem);
  //Function to delete deleteItem from the list. 
  //Postcondition: If found, the node containing deleteItem
  //               is deleted from the list; first points
  //               to the first node of the new list, last
  //               points to the last node of the new list,
  //               and count is decremented by 1; otherwise,
  //               an appropriate message is printed. 

doublyLinkedList(); 
  //default constructor
  //Initializes the list to an empty state.
  //Postcondition: first = NULL; last = NULL; count = 0;

doublyLinkedList(const doublyLinkedList&lt;Type&gt;&amp; otherList); 
  //copy constructor
~doublyLinkedList(); 
  //destructor
  //Postcondition: The list object is destroyed.

public:
int count;
nodeType&lt;Type&gt; *first; //pointer to the first node
nodeType&lt;Type&gt; *last;  //pointer to the last node

public:
void copyList(const doublyLinkedList&lt;Type&gt;&amp; otherList); 
  //Function to make a copy of otherList.
  //Postcondition: A copy of otherList is created and
  //               assigned to this list.
};



#endif
</code></pre>

<h1>Implementation file:</h1>

<pre><code>#include &lt;iostream&gt;
#include &lt;cassert&gt;
#include "doublyLinkedList.h"

using namespace std;


template &lt;class Type&gt;
doublyLinkedList&lt;Type&gt;::doublyLinkedList()
{
first= NULL;
last = NULL;
count = 0;
}

template &lt;class Type&gt;
bool doublyLinkedList&lt;Type&gt;::isEmptyList() const
{
return (first == NULL);
}

template &lt;class Type&gt;
void doublyLinkedList&lt;Type&gt;::destroy()
{  
nodeType&lt;Type&gt;  *temp; //pointer to delete the node

while (first != NULL)
{
    temp = first;
    first = first-&gt;next;
    delete temp;
}

last = NULL;
count = 0;
}

template &lt;class Type&gt;
void doublyLinkedList&lt;Type&gt;::initializeList()
{
destroy();
}

 template &lt;class Type&gt;
 int doublyLinkedList&lt;Type&gt;::length() const
{
return count;
}

template &lt;class Type&gt;
void doublyLinkedList&lt;Type&gt;::print() const
{
nodeType&lt;Type&gt; *current; //pointer to traverse the list

current = first;  //set current to point to the first node

while (current != NULL)
{
    cout &lt;&lt; current-&gt;info &lt;&lt; "  ";  //output info
    current = current-&gt;next;
}//end while
}//end print


 template &lt;class Type&gt;
 void doublyLinkedList&lt;Type&gt;::reversePrint() const
 {
nodeType&lt;Type&gt; *current; //pointer to traverse 
                         //the list

current = last;  //set current to point to the 
                 //last node

while (current != NULL)
{
    cout &lt;&lt; current-&gt;info &lt;&lt; "  ";  
    current = current-&gt;back;
}//end while
}//end reversePrint

template &lt;class Type&gt;
 bool doublyLinkedList&lt;Type&gt;::
                   search(const Type&amp; searchItem) const
{
bool found = false;
nodeType&lt;Type&gt; *current; //pointer to traverse the list

current = first;

while (current != NULL &amp;&amp; !found)
    if (current-&gt;info &gt;= searchItem)
        found = true;
    else
        current = current-&gt;next;

if (found)
   found = (current-&gt;info == searchItem); //test for 
                                          //equality

 return found;
 }//end search

template &lt;class Type&gt;
Type doublyLinkedList&lt;Type&gt;::front() const
{
assert(first != NULL);

return first-&gt;info;
}

template &lt;class Type&gt;
Type doublyLinkedList&lt;Type&gt;::back() const
{
assert(last != NULL);

return last-&gt;info;
}

template &lt;class Type&gt;
void doublyLinkedList&lt;Type&gt;::insert(const Type&amp; insertItem)
{
nodeType&lt;Type&gt; *current;      //pointer to traverse the list
nodeType&lt;Type&gt; *trailCurrent; //pointer just before current
nodeType&lt;Type&gt; *newNode;      //pointer to create a node
bool found;

newNode = new nodeType&lt;Type&gt;; //create the node
newNode-&gt;info = insertItem;  //store the new item in the node
newNode-&gt;next = NULL;
newNode-&gt;back = NULL;

if(first == NULL) //if the list is empty, newNode is 
                  //the only node
{
   first = newNode;
   last = newNode;
   count++;
}
else
{
    found = false;
    current = first;

    while (current != NULL &amp;&amp; !found) //search the list
        if (current-&gt;info &gt;= insertItem)
            found = true;
        else
        {
            trailCurrent = current;
            current = current-&gt;next;
        }

    if (current == first) //insert newNode before first
    {
        first-&gt;back = newNode;
        newNode-&gt;next = first;
        first = newNode;
        count++;
    }
    else
    {
          //insert newNode between trailCurrent and current
        if (current != NULL)
        {
            trailCurrent-&gt;next = newNode;
            newNode-&gt;back = trailCurrent;
            newNode-&gt;next = current;
            current-&gt;back = newNode;
        }
        else
        {
            trailCurrent-&gt;next = newNode;
            newNode-&gt;back = trailCurrent;
            last = newNode;
        }

        count++;
    }//end else
}//end else
}//end insert

template &lt;class Type&gt;
void doublyLinkedList&lt;Type&gt;::deleteNode(const Type&amp; deleteItem)
{
nodeType&lt;Type&gt; *current; //pointer to traverse the list
nodeType&lt;Type&gt; *trailCurrent; //pointer just before current

bool found;

if (first == NULL)
    cout &lt;&lt; "Cannot delete from an empty list." &lt;&lt; endl;
else if (first-&gt;info == deleteItem) //node to be deleted is  
                                   //the first node
{
    current = first;
    first = first-&gt;next;

    if (first != NULL)
        first-&gt;back = NULL;
    else
        last = NULL;

    count--;

    delete current;
}
else 
{
    found = false;
    current = first;

    while (current != NULL &amp;&amp; !found)  //search the list
        if (current-&gt;info &gt;= deleteItem)
            found = true;
        else
            current = current-&gt;next;

    if (current == NULL)
        cout &lt;&lt; "The item to be deleted is not in " 
             &lt;&lt; "the list." &lt;&lt; endl;
    else if (current-&gt;info == deleteItem) //check for 
                                             //equality
    {
        trailCurrent = current-&gt;back; 
        trailCurrent-&gt;next = current-&gt;next;

        if (current-&gt;next != NULL)
            current-&gt;next-&gt;back = trailCurrent;

        if (current == last)
            last = trailCurrent;

        count--;
        delete current;
    }
    else
        cout &lt;&lt; "The item to be deleted is not in list." 
             &lt;&lt; endl;
}//end else
}//end deleteNode

template &lt;class Type&gt;
void doublyLinkedList&lt;Type&gt;::copyList(const doublyLinkedList&lt;Type&gt;&amp; otherList)
 {

//cout &lt;&lt; "The definition of this function is left as an exercise." &lt;&lt; endl;
//cout &lt;&lt; "See Programming Execrise 9." &lt;&lt; endl;


 template &lt;class Type&gt;
 doublyLinkedList&lt;Type&gt;::doublyLinkedList(const doublyLinkedList&lt;Type&gt;&amp; otherList)
 {

// cout &lt;&lt; "The definition of the copy constructor is left as an exercise." &lt;&lt;         endl;
 // cout &lt;&lt; "See Programming Execrise 9." &lt;&lt; endl;
}

template &lt;class Type&gt;
const doublyLinkedList&lt;Type&gt;&amp; doublyLinkedList&lt;Type&gt;::operator=
                        (const doublyLinkedList&lt;Type&gt; &amp;)

//  cout &lt;&lt; "Overloading the assignment operator is left as an exercise." &lt;&lt; endl;
//  cout &lt;&lt; "See Programming Execrise 9." &lt;&lt; endl;
}

 template &lt;class Type&gt;
 doublyLinkedList&lt;Type&gt;::~doublyLinkedList()
 {

//cout &lt;&lt; "Definition of the destructor is left as an exercise." &lt;&lt; endl;
//cout &lt;&lt; "See Programming Execrise 9." &lt;&lt; endl;
 }
</code></pre>

<h1>Main Function:</h1>

<pre><code>//Program to test various operations on a doubly linked list


#include &lt;iostream&gt;
#include "doublyLinkedList.h"  

using namespace std; 

int main()
{
char choice;
int n = 0;
 doublyLinkedList&lt;int&gt; myList;

cout&lt;&lt;"this is a test"&lt;&lt;endl;

do {
 cout&lt;&lt;"Main Menu:"&lt;&lt;endl;
 cout&lt;&lt;"Choice of operations to perform on Dobule Linked List"&lt;&lt;endl;
 cout&lt;&lt;"Create list values :  C"&lt;&lt;endl;
 cout&lt;&lt;"Initialize List:   Z"&lt;&lt;endl;
 cout&lt;&lt;"Check List Empty:   M"&lt;&lt;endl;
 cout&lt;&lt;"Destroy List:   E  "&lt;&lt;endl;
 cout&lt;&lt;"Print List  : P"&lt;&lt;endl;
 cout&lt;&lt;"Reverse printed list:  R"&lt;&lt;endl;
 cout&lt;&lt;"Length of List: L"&lt;&lt;endl;
 cout &lt;&lt;"Front of List: F"&lt;&lt;endl;
 cout&lt;&lt;"Back of List: B"&lt;&lt;endl;
 cout&lt;&lt;"Search list: S"&lt;&lt;endl;
 cout&lt;&lt;"Insert List: I"&lt;&lt;endl;
 cout&lt;&lt;"delete list: D"&lt;&lt;endl;
 cout&lt;&lt;"use copy constructor : U" &lt;&lt;endl;
 cout &lt;&lt;"quit: Q"&lt;&lt;endl;

 cin &gt;&gt; choice;
 if ((choice == 'I' )|| (choice =='D')|| (choice == 'S'))
 {
     cout&lt;&lt;"Enter value to manipulate: "&lt;&lt;endl;
     cin &gt;&gt; n;
 }
 switch ( choice) 
 {
 case 'C':
  cout&lt;&lt;"Please enter a list"&lt;&lt;endl;
 while(n!= -999){
     myList.insert(n);
     cin&gt;&gt;n;}
     break;

 case 'S':  if (myList.search(n))
            cout&lt;&lt; " List contains: "&lt;&lt;n&lt;&lt;endl;
            else
                cout&lt;&lt;"List does not contain "&lt;&lt;n&lt;&lt;endl;
            break;
case 'I': 
    myList.insert(n);
    cout&lt;&lt;"element was inserted"&lt;&lt;endl;
    break;
case 'D':
        myList.deleteNode(n);
        cout&lt;&lt;"node was deleted"&lt;&lt;endl;
        break;

case 'L':  cout&lt;&lt;"Length is \n"&lt;&lt;endl;
    myList.length();
    break;
case 'B': 
        cout&lt;&lt;"back element is :  "&lt;&lt; myList.back();
        break;
case 'F' : 
    cout&lt;&lt;"front element is "&lt;&lt;myList.front();
    break;
case 'Z' : myList.initializeList();
        cout&lt;&lt;"list initialized"&lt;&lt;endl;
case 'M': if (myList.isEmptyList())
        cout&lt;&lt;"is empty"&lt;&lt; endl;
        else
        cout&lt;&lt;"is not empty"&lt;&lt;endl;
        break;
    case 'E': myList.destroy();
    cout&lt;&lt;"list destroyed"&lt;&lt;endl;
    break;
    case 'P': myList.print();
    break;
    case'R': cout&lt;&lt;"reversed"&lt;&lt;endl;
    myList.reversePrint();
    break;
    }
    }while(choice!= 'Q');
    return 0;

 }
</code></pre>

<p>I am looking for guidance.  I know the answer is really simple and I am just not seeing it.  I thought about using the keyword extern but am not sure really how to use it.  Like I said in the tags this is homework so I am not looking for a quick fix I am looking to learn from my mistakes. 
I really appreciate this site and all the members.</p>

<p>All the code i posted on here was available for free by the book publisher, I have left out my original code except for main.cpp</p>
