views:

61

answers:

1

Okay, I'm making a project that implements a Double Linked List using classes, templates and structures. I constantly get the error:

doublelinklist.h(21) : error C2955: 'Node' : use of class template requires template argument list

when declaring the head and tail of a node in the LinkedList class.

DoubleLinkList.h:

#ifndef DOUBLELINKLIST_H
#define DOUBLELINKLIST_H
#ifndef NULL
#define NULL 0
#endif
//#include <stdio.h>
//#include <string>

template <class T>
struct Node 
{
 T val;
 Node * next;
 Node * prev; //both of these are self-referential data types/structures
};

template <class T>
class LinkedList
{
private:
 static Node * head; //C2955
 static Node * tail; //C2955
public:
 bool push(T);
 //bool pop();
 //T at(); //C2146
 //bool clear();

 LinkedList()
 {
  /*static Node * */head = NULL;
  /*static Node * */tail = NULL;
 }
 ~LinkedList()
 {}
};

#endif

DoubleLinkList.cpp

#include "DoubleLinkList.h"

template <class T>
bool LinkedList<T>::push(T pushMe)
{
 Node * newN = new Node;

 newN->next = NULL;
 newN->prev = NULL;

 if(this->head == NULL)
 {
  head = newN;
  head->val = pushMe;
  tail = newN;
  printf("the value in the head is %d\n", head->val);
  return true;
 }

 newN->prev = tail;
 tail->next = newN;
 newN->pushMe;
 tail = newN;

 printf("The value in the head is %d\n", head->val);
 return true;
}

//bool LinkedList::pop(int remove_where)
//{
// Node * toRemove = at(remove_where);
//
// if(toRemove == head)
// {
//  toRemove->next->prev = NULL;
//  head = toRemove->next;
// }
//
// else if(toRemove = tail)
// {
//  toRemove->prev->next = NULL;
//  tail = toRemove->prev;
// }
// 
// else
// {
//  toRemove->prev->next = toRemove->next;
//  toRemove->next->prev = toRemove->prev;
// }
//
// delete toRemove;
//
// return true;
//
//}
//
//T LinkedList::at()
//{
// 
// 
//}
//
//LinkedList::clear()
//{
// 
//
//}

main.cpp

/*

1) Implement a Double-Linked List using templates and classes in C++.
   You may use the STL type "List" as a reference. 
   A) Don't forget to implement a NODE class...
   B) Don't forget to implement a class that is the actual list...
        i) You need to have AT LEAST:

            Push
            Pop
            At
            Clear 

2) Write a program that tests the functionality of your list class with the data types "int" and "std::string".
*/
#include <stdio.h>
#include <string>
#include "DoubleLinkList.h"

//template <class T>
int main()
{
    int x = 5;
    LinkedList<int> derp;
    derp.push(x);
    return 0;    
}
+3  A: 

Error C2955 (link) relates to the absence of a type argument list to types that require one. In your code you reference the type Node which is actually a template and requires a type argument list. The fixes are below:

First of all, in DoubleLinkedList.h in the declaration of LinkedList (in the private: section at the top):

static Node * head;
static Node * tail;

should be (they should also not be declared static since I'm pretty certain each individual linked list needs its own head and tail):

Node<T> * head;
Node<T> * tail;

since Node is actually the template class Node<T> and requires the type parameter itself.

Similarly in DoubleLinkedList.cpp in the push method:

Node * newN = new Node;

should be:

Node<T> * newN = new Node<T>;

for the same reason.

Furthermore, template definitions should be defined in header files and the header files included using #include, e.g. #include "DoubleLinkedList.h", (and not compiled as you would .cpp files) since template expansion to produce concrete versions of the classes is performed by the preprocessor. Finally, there is also a problem with newN->pushMe; in your definition of LinkedList<T>::push: no such method exists. Fix these issues and there's a chance it might compile! Beyond that I don't vouch for the correctness of the code.

Richard Cook
++ I suspected something like this after looking up what the error code meant.
John at CashCommons
That worked. Though, now I get these linker errors
Gregory R. Morton
It worked. Now I get the errors: LNK2019 and two LNK2001s. Pasting the full details in here would make everything looked jumbled up.
Gregory R. Morton
Can you summarize the error messages? What are the unresolved symbol names?
Richard Cook
For the 2019, it's "public: bool __thiscall LinkedList<int>::push(int)"; For the other two, it's "private: static struct Node<int> * LinkedList<int>::tail" and "private: static struct Node<int> * LinkedList<int>::head"
Gregory R. Morton
It's certainly in my project. Do I actually have to #include DoubleLinkedList.cpp somewhere?
Gregory R. Morton
Templates should not be split into separate `.cpp` and `.h` files. So merge the content of `DoubleLinkedList.cpp` into the `.h` file and remove the `.cpp` file altogether. I've updated my answer to reflect this.
Richard Cook
Also see my comment about the `head` and `tail` members: they should be instance variables not `static`.
Richard Cook
Are you saying it's just not possible to use Templates across multiple files? Or is it possible, but just really difficult?
Gregory R. Morton
No, it's possible but they need to be included using `#include` like you would header files and *not* compiled like `.cpp` files normally are. I added this clarification to my answer.
Richard Cook
putting something like "#include template <class T>" in the header of DoubleLinkList.cpp causes another error.
Gregory R. Morton
You need to insert `#include "DoubleLinkedList.cpp"` into your `main.cpp` source file. But I would highly recommend renaming `DoubleLinkedList.cpp` to something with a `.h` file name extension to indicate that it is a header file and not a source file to be compiled.
Richard Cook
Thanks! That actually seemed to get the job done. I already had the .h version in there anyway.
Gregory R. Morton