Question

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.

TemplateDoublyLinkedList.h

#include <cstdlib>
#include <iostream>
using namespace std;
template <typename T>
class DoublyLinkedList; // class declaration

// list node
template <typename T>
class DListNode {
private: T obj;
  DListNode *prev, *next;
  friend class DoublyLinkedList<T>;
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 <typename T>
class DoublyLinkedList {
protected: DListNode header, trailer;
public:
  DoublyLinkedList() : header(0), trailer(0) // constructor
  { /*header.next = &trailer; trailer.prev = &header;*/ }
  DoublyLinkedList(const DoublyLinkedList<T>& dll); // copy constructor
  ~DoublyLinkedList(); // destructor
  DoublyLinkedList& operator=(const DoublyLinkedList<T>& 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 &trailer; }
  // return if the list is empty
  bool isEmpty() const { return header.next == &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 <typename T>
ostream& operator<<(ostream& out, const DoublyLinkedList<T>& dll);

// extend range_error from <stdexcept>
template <typename T>
struct EmptyDLinkedListException : std::range_error {
  explicit EmptyDLinkedListException(char const* msg=NULL): range_error(msg) {}
};

// copy constructor
template <typename T>
DoublyLinkedList<T>::DoublyLinkedList(const DoublyLinkedList<T>& dll)
{
  header.next = &trailer; trailer.prev = &header;

  DListNode<T>* current = dll.getFirst();
  while (current != dll.getAfterLast()) {
      T newObj = current->obj;
      insertLast(newObj);
      current = current->getNext();
  }

}
// assignment operator
template <typename T>
DoublyLinkedList<T>& DoublyLinkedList<T>::operator=(const DoublyLinkedList<T>& dll)
{
  delete this;

  header.next = &trailer; trailer.prev = &header;

  DListNode<T>* current = dll.getFirst();
  while (current != dll.getAfterLast()) {
      T newObj = current->obj;
      insertLast(newObj);
      current = current->getNext();
  }

  return *this;
}
// insert the object to the first of the linked list
template <typename T>
void DoublyLinkedList<T>::insertFirst(T newobj)
{ 
  DListNode<T> *newNode = new DListNode(newobj, &header, header.next);
  header.next->prev = newNode;
  header.next = newNode;
}
// insert the object to the last of the linked list
template <typename T>
void DoublyLinkedList<T>::insertLast(T newobj)
{
  DListNode<T> *newNode = new DListNode(newobj, trailer.prev,&trailer);
  trailer.prev->next = newNode;
  trailer.prev = newNode;
}
// remove the first object of the list
template <typename T>
T DoublyLinkedList<T>::removeFirst()
{ 
  if (isEmpty())
    throw EmptyDLinkedListException("Empty Doubly Linked List");
  DListNode<T> *node = header.next;
  node->next->prev = &header;
  header.next = node->next;
  T obj = node->obj;
  delete node;
  return obj;
}
// remove the last object of the list
template <typename T>
T DoublyLinkedList<T>::removeLast()
{
  if (isEmpty())
    throw EmptyDLinkedListException("Empty Doubly Linked List");
  DListNode<T> *node = trailer.prev;
  node->prev->next = &trailer;
  trailer.prev = node->prev;
  T obj = node->obj;
  delete node;
  return obj;
}
// destructor
template <typename T>
DoublyLinkedList<T>::~DoublyLinkedList()
{
  DListNode<T> *prev_node, *node = header.next;
  while (node != &trailer) {
    prev_node = node;
    node = node->next;
    delete prev_node;
  }
  header.next = &trailer;
  trailer.prev = &header;
}
// return the first object
template <typename T>
T DoublyLinkedList<T>::first() const
{ 
  if (isEmpty())
    throw EmptyDLinkedListException("Empty Doubly Linked List");
  return header.next->obj;
}
// return the last object
template <typename T>
T DoublyLinkedList<T>::last() const
{
  if (isEmpty())
    throw EmptyDLinkedListException("Empty Doubly Linked List");
  return trailer.prev->obj;
}
// return the list length
template <typename T>
T DoublyLinkedListLength(DoublyLinkedList<T>& dll) {
  DListNode<T> *current = dll.getFirst();
  int count = 0;
  while(current != dll.getAfterLast()) {
    count++;
    current = current->getNext(); //iterate
  }
  return count;
}
// output operator
template <typename T>
ostream& operator<<(ostream& out, const DoublyLinkedList<T>& dll) {
  DListNode<T> *current = dll.getFirst();
  while (current != dll.getAfterLast()) {
      out << current->getElem() << '\n';
      current = current->getNext();
  }
  return out;
}

TemplateMain.cpp

#include "TemplateDoublyLinkedList.h"
#include <iostream>
#include <string>
#include <cstdio>
#include <sstream>
using namespace std;
int main () {
  // Construct a linked list with header & trailer
  cout << "Create a new list" << endl;
  DoublyLinkedList<string> dll;
  cout << "list: " << dll << endl << endl;

  // Insert 10 nodes at back with value 10,20,30,..,100
  cout << "Insert 10 nodes at back with value 10,20,30,..,100" << endl;
  for (int i=10;i<=100;i+=10) {
    stringstream ss;
    ss << i;
    dll.insertLast(ss.str());
  }
  cout << "list: " << dll << endl << endl;

  // Insert 10 nodes at front with value 10,20,30,..,100
  cout << "Insert 10 nodes at front with value 10,20,30,..,100" << endl;
  for (int i=10;i<=100;i+=10) {
    stringstream ss;
    ss << i;
    dll.insertFirst(ss.str());
  }
  cout << "list: " << dll << endl << endl;

  // Copy to a new list
  cout << "Copy to a new list" << endl;
  DoublyLinkedList<string> dll2(dll);
  cout << "list2: " << dll2 << endl << endl;

  // Assign to another new list
  cout << "Assign to another new list" << endl;
  DoublyLinkedList<string> dll3=dll;
  cout << "list3: " << dll3 << endl << endl;

  // Delete the last 10 nodes
  cout << "Delete the last 10 nodes" << endl;
  for (int i=0;i<10;i++) {
    dll.removeLast();
  }
  cout << "list: " << dll << endl << endl;

  // Delete the first 10 nodes
  cout << "Delete the first 10 nodes" << endl;
  for (int i=0;i<10;i++) {
    dll.removeFirst();
  }
  cout << "list: " << dll << endl << endl;

  // Check the other two lists
  cout << "Make sure the other two lists are not affected." << endl;
  cout << "list2: " << dll2 << endl;
  cout << "list3: " << dll3 << endl;

  return 0;
}

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 &)' with T=std::string"

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.

EDIT: I think I fixed all locations such as DListNode *current = dll.getFirst();

But I am still getting a few errors such as at line 24 where it says use of class template requires template argument list

No correct solution

OTHER TIPS

I did not look through all your class definitions but even the first constructor of DoublyLinkedList is invalid

  DoublyLinkedList() : header(0), trailer(0) // constructor
  { header.next = &trailer; trailer.prev = &header; }

If header and trailer are initialized by zero then the both assignmnets

header.next = &trailer; trailer.prev = &header;

can result in abend of the program.

Moreover they have not any sense. The constructor should be simple without these assignments

  DoublyLinkedList() : header(0), trailer(0) {}

Also your definitions have other errors. For example instead of

  DListNode* current = dll.getFirst();

There should be

  DListNode<T>* current = dll.getFirst();

because class DListNode is a template class.

Also it is a bad design of your list. Class DListNode should be an internal class of DoublyLinkedList. There is no sense to define it separatly from class DoublyLinkedList. Moreover if DoublyLinkedList is a friend class of DListNode then it is not clear why methods getNext and getPrev are defined.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top