title: Doubly Linked List Template Errors (C++)
body: <p>I am working on an assignment for my programming class where we have to write a Doubly Linked List and then convert it to a template Doubly Linked List. I got the non-template version to work, but now I can't figure out how to fix my errors on the template version. I'll put the code here first and then talk about my errors below it.</p>
  
  <p>TemplateDoublyLinkedList.h</p>
  
  <pre><code>#include &lt;cstdlib&gt;
  #include &lt;iostream&gt;
  using namespace std;
  template &lt;typename T&gt;
  class DoublyLinkedList; // class declaration
  
  // list node
  template &lt;typename T&gt;
  class DListNode {
  private: T obj;
    DListNode *prev, *next;
    friend class DoublyLinkedList&lt;T&gt;;
  public:
    DListNode(T object = T(), DListNode *p = NULL, DListNode *n = NULL)
      : obj(object), prev(p), next(n) {}
    T getElem() const { return obj; }
    DListNode * getNext() const { return next; }
    DListNode * getPrev() const { return prev; }
  };
  
  // doubly linked list
  template &lt;typename T&gt;
  class DoublyLinkedList {
  protected: DListNode header, trailer;
  public:
    DoublyLinkedList() : header(0), trailer(0) // constructor
    { /*header.next = &amp;trailer; trailer.prev = &amp;header;*/ }
    DoublyLinkedList(const DoublyLinkedList&lt;T&gt;&amp; dll); // copy constructor
    ~DoublyLinkedList(); // destructor
    DoublyLinkedList&amp; operator=(const DoublyLinkedList&lt;T&gt;&amp; dll); // assignment operator
    // return the pointer to the first node
    DListNode *getFirst() const { return header.next; } 
    // return the pointer to the trailer
    const DListNode *getAfterLast() const { return &amp;trailer; }
    // return if the list is empty
    bool isEmpty() const { return header.next == &amp;trailer; }
    T first() const; // return the first object
    T last() const; // return the last object
    void insertFirst(T newobj); // insert to the first of the list
    T removeFirst(); // remove the first node
    void insertLast(T newobj); // insert to the last of the list
    T removeLast(); // remove the last node
  };
  // output operator
  template &lt;typename T&gt;
  ostream&amp; operator&lt;&lt;(ostream&amp; out, const DoublyLinkedList&lt;T&gt;&amp; dll);
  
  // extend range_error from &lt;stdexcept&gt;
  template &lt;typename T&gt;
  struct EmptyDLinkedListException : std::range_error {
    explicit EmptyDLinkedListException(char const* msg=NULL): range_error(msg) {}
  };
  
  // copy constructor
  template &lt;typename T&gt;
  DoublyLinkedList&lt;T&gt;::DoublyLinkedList(const DoublyLinkedList&lt;T&gt;&amp; dll)
  {
    header.next = &amp;trailer; trailer.prev = &amp;header;
  
    DListNode&lt;T&gt;* current = dll.getFirst();
    while (current != dll.getAfterLast()) {
        T newObj = current-&gt;obj;
        insertLast(newObj);
        current = current-&gt;getNext();
    }
  
  }
  // assignment operator
  template &lt;typename T&gt;
  DoublyLinkedList&lt;T&gt;&amp; DoublyLinkedList&lt;T&gt;::operator=(const DoublyLinkedList&lt;T&gt;&amp; dll)
  {
    delete this;
  
    header.next = &amp;trailer; trailer.prev = &amp;header;
  
    DListNode&lt;T&gt;* current = dll.getFirst();
    while (current != dll.getAfterLast()) {
        T newObj = current-&gt;obj;
        insertLast(newObj);
        current = current-&gt;getNext();
    }
  
    return *this;
  }
  // insert the object to the first of the linked list
  template &lt;typename T&gt;
  void DoublyLinkedList&lt;T&gt;::insertFirst(T newobj)
  { 
    DListNode&lt;T&gt; *newNode = new DListNode(newobj, &amp;header, header.next);
    header.next-&gt;prev = newNode;
    header.next = newNode;
  }
  // insert the object to the last of the linked list
  template &lt;typename T&gt;
  void DoublyLinkedList&lt;T&gt;::insertLast(T newobj)
  {
    DListNode&lt;T&gt; *newNode = new DListNode(newobj, trailer.prev,&amp;trailer);
    trailer.prev-&gt;next = newNode;
    trailer.prev = newNode;
  }
  // remove the first object of the list
  template &lt;typename T&gt;
  T DoublyLinkedList&lt;T&gt;::removeFirst()
  { 
    if (isEmpty())
      throw EmptyDLinkedListException("Empty Doubly Linked List");
    DListNode&lt;T&gt; *node = header.next;
    node-&gt;next-&gt;prev = &amp;header;
    header.next = node-&gt;next;
    T obj = node-&gt;obj;
    delete node;
    return obj;
  }
  // remove the last object of the list
  template &lt;typename T&gt;
  T DoublyLinkedList&lt;T&gt;::removeLast()
  {
    if (isEmpty())
      throw EmptyDLinkedListException("Empty Doubly Linked List");
    DListNode&lt;T&gt; *node = trailer.prev;
    node-&gt;prev-&gt;next = &amp;trailer;
    trailer.prev = node-&gt;prev;
    T obj = node-&gt;obj;
    delete node;
    return obj;
  }
  // destructor
  template &lt;typename T&gt;
  DoublyLinkedList&lt;T&gt;::~DoublyLinkedList()
  {
    DListNode&lt;T&gt; *prev_node, *node = header.next;
    while (node != &amp;trailer) {
      prev_node = node;
      node = node-&gt;next;
      delete prev_node;
    }
    header.next = &amp;trailer;
    trailer.prev = &amp;header;
  }
  // return the first object
  template &lt;typename T&gt;
  T DoublyLinkedList&lt;T&gt;::first() const
  { 
    if (isEmpty())
      throw EmptyDLinkedListException("Empty Doubly Linked List");
    return header.next-&gt;obj;
  }
  // return the last object
  template &lt;typename T&gt;
  T DoublyLinkedList&lt;T&gt;::last() const
  {
    if (isEmpty())
      throw EmptyDLinkedListException("Empty Doubly Linked List");
    return trailer.prev-&gt;obj;
  }
  // return the list length
  template &lt;typename T&gt;
  T DoublyLinkedListLength(DoublyLinkedList&lt;T&gt;&amp; dll) {
    DListNode&lt;T&gt; *current = dll.getFirst();
    int count = 0;
    while(current != dll.getAfterLast()) {
      count++;
      current = current-&gt;getNext(); //iterate
    }
    return count;
  }
  // output operator
  template &lt;typename T&gt;
  ostream&amp; operator&lt;&lt;(ostream&amp; out, const DoublyLinkedList&lt;T&gt;&amp; dll) {
    DListNode&lt;T&gt; *current = dll.getFirst();
    while (current != dll.getAfterLast()) {
        out &lt;&lt; current-&gt;getElem() &lt;&lt; '\n';
        current = current-&gt;getNext();
    }
    return out;
  }
  </code></pre>
  
  <p>TemplateMain.cpp</p>
  
  <pre><code>#include "TemplateDoublyLinkedList.h"
  #include &lt;iostream&gt;
  #include &lt;string&gt;
  #include &lt;cstdio&gt;
  #include &lt;sstream&gt;
  using namespace std;
  int main () {
    // Construct a linked list with header &amp; trailer
    cout &lt;&lt; "Create a new list" &lt;&lt; endl;
    DoublyLinkedList&lt;string&gt; dll;
    cout &lt;&lt; "list: " &lt;&lt; dll &lt;&lt; endl &lt;&lt; endl;
  
    // Insert 10 nodes at back with value 10,20,30,..,100
    cout &lt;&lt; "Insert 10 nodes at back with value 10,20,30,..,100" &lt;&lt; endl;
    for (int i=10;i&lt;=100;i+=10) {
      stringstream ss;
      ss &lt;&lt; i;
      dll.insertLast(ss.str());
    }
    cout &lt;&lt; "list: " &lt;&lt; dll &lt;&lt; endl &lt;&lt; endl;
  
    // Insert 10 nodes at front with value 10,20,30,..,100
    cout &lt;&lt; "Insert 10 nodes at front with value 10,20,30,..,100" &lt;&lt; endl;
    for (int i=10;i&lt;=100;i+=10) {
      stringstream ss;
      ss &lt;&lt; i;
      dll.insertFirst(ss.str());
    }
    cout &lt;&lt; "list: " &lt;&lt; dll &lt;&lt; endl &lt;&lt; endl;
  
    // Copy to a new list
    cout &lt;&lt; "Copy to a new list" &lt;&lt; endl;
    DoublyLinkedList&lt;string&gt; dll2(dll);
    cout &lt;&lt; "list2: " &lt;&lt; dll2 &lt;&lt; endl &lt;&lt; endl;
  
    // Assign to another new list
    cout &lt;&lt; "Assign to another new list" &lt;&lt; endl;
    DoublyLinkedList&lt;string&gt; dll3=dll;
    cout &lt;&lt; "list3: " &lt;&lt; dll3 &lt;&lt; endl &lt;&lt; endl;
  
    // Delete the last 10 nodes
    cout &lt;&lt; "Delete the last 10 nodes" &lt;&lt; endl;
    for (int i=0;i&lt;10;i++) {
      dll.removeLast();
    }
    cout &lt;&lt; "list: " &lt;&lt; dll &lt;&lt; endl &lt;&lt; endl;
  
    // Delete the first 10 nodes
    cout &lt;&lt; "Delete the first 10 nodes" &lt;&lt; endl;
    for (int i=0;i&lt;10;i++) {
      dll.removeFirst();
    }
    cout &lt;&lt; "list: " &lt;&lt; dll &lt;&lt; endl &lt;&lt; endl;
  
    // Check the other two lists
    cout &lt;&lt; "Make sure the other two lists are not affected." &lt;&lt; endl;
    cout &lt;&lt; "list2: " &lt;&lt; dll2 &lt;&lt; endl;
    cout &lt;&lt; "list3: " &lt;&lt; dll3 &lt;&lt; endl;
  
    return 0;
  }
  </code></pre>
  
  <p>Now it is listing a bunch of errors but a common theme among all the errors is it says (in summary): "while compiling class template member function 'DoublyLinkedList::DoublyLinkedList(const DoublyLinkedList &amp;)' with T=std::string"</p>
  
  <p>So I think that means there is an error with my template and it isn't accepting string into the template but don't know how to fix it. Thanks for your help.</p>
  
  <p>EDIT: I think I fixed all locations such as 
      DListNode *current = dll.getFirst();</p>
  
  <p>But I am still getting a few errors such as at line 24 where it says use of class template requires template argument list</p>