Getting a template argument is invalid error? Why? - c++

For some reason, I keep getting a "template agrument 1 is invalid error" when compiling my code. I'm not sure why. I'm trying to create a linked list using templates. Here is my code
When running my main method where I introduce the class as:
Dlist<L> list;
Then I try to implement a few of the functions.
The error I get is:
Dlist<L> list; template agrument 1 is invalid.
^
HELP
ListNode.H
#ifndef LISTNODE_H
#define LISTNODE_H
#include <iostream>
using namespace std;
template <class L>
class ListNode
{
public:
L data;
ListNode *prev;
ListNode *next;
ListNode(L d);
ListNode();
~ListNode();
};
template <class L>
ListNode<L>::ListNode()//blank constructor
{
}
template <class L>
ListNode<L>::ListNode(L d)//overloaded constructor
{
next = NULL;
prev = NULL;
data = d;
}
template <class L>
ListNode<L>::~ListNode()//deconstructor
{
next = NULL;
prev = NULL;
}
#endif
DList.h
#ifndef DLIST_H
#define DLIST_H
#include <iostream>
#include "ListNode.h"
using namespace std;
template <class L>
class Dlist
{
private:
ListNode<L>* front;
ListNode<L>* back;
unsigned int size;
public:
Dlist();//constructor
~Dlist();//destructor
//insert and remove functions
void insertFront(L data);
int removeFront();
void insertBack(L data);
int removeBack();
ListNode<L>* removeAt(L pos);
//other functions
bool isEmpty();
int find(L val);
int getFront();
int getBack();
unsigned int getSize();
void printList();
};
template <class L>
Dlist<L>::Dlist()
{
size = 0;
front = NULL;
back = NULL;
}
template <class L>
Dlist<L>::~Dlist()
{
if(front != NULL)
{
delete front;
}
}
template <class L>
void Dlist<L>::insertFront(L data)
{
ListNode<L> *node = new ListNode<L>(data);
if (size = 0)
{
back = node;
}
else
{
front->prev=node;
node->next=front;
}
size++;
front = node;
}
template <class L>
int Dlist<L>::removeFront()
{
ListNode<L> *temp = front;
if(front->next = NULL)
{
back = NULL;
}
else
{
front->next->prev = NULL;
front->next = NULL;
}
front = front->next;
int val = temp->data;
delete temp;
--size;
return val;
}
template <class L>
void Dlist<L>::insertBack(L data)
{
ListNode<L> *node = new ListNode<L>(data);
if (size == 0)
{
front = node;
}
else
{
back->next = node;
node->prev = back;
}
back = node;
size++;
}
template <class L>
int Dlist<L>::removeBack()
{
ListNode<L> *temp = back;
if(back->prev = NULL)
{
front = NULL;
}
else
{
back->prev->next = NULL;
}
back = back->prev;
int val = temp->data;
delete temp;
--size;
return val;
}
template <class L>
ListNode<L>* Dlist<L>::removeAt(L key)
{
ListNode<L>* curr = front;
while(curr->data != key)
{
curr=curr->next;
if (curr == NULL)
{
return NULL;
}
}
//found the key
if(curr == front)
{
front=curr->next;
}
else
{
curr->prev->next = curr->next;
}
if(curr==back)
{
back = curr->prev;
}
else
{
curr->next->prev = curr->prev;
}
curr->next=NULL;
curr->prev = NULL;
size--;
return curr;
}
template <class L>
unsigned int Dlist<L>::getSize()
{
return size;
}
template <class L>
void Dlist<L>::printList()
{
ListNode<L>* curr = front;
while(curr != NULL)
{
cout<< curr->data << endl;
curr = curr->next;
}
}
template <class L>
int Dlist<L>::getFront()
{
return front;
}
template <class L>
int Dlist<L>::getBack()
{
return back;
}
#endif

you can not use the template class as you are trying.
Dlist< L> list;
As L is not a valid data type. Valid data type includes built-in or user defined data type.
"L" you are using it as a template so you can use it only inside the template class.
The above statement would be valid if you define your own class 'L' like below:
class L
{
int a;
};
Hope that helps.

Related

Error C2955 while implementing a struct/template class based Linked List

I am trying to implement a Linked List by a template class and a struct for defining nodes. I expected that it would compile but it's not going to. The error that Visual Studio gives to me is C2955 "use of class template requires template argument list" and checking on Microsoft documentation my code seems to not match to any reported case. The error is reported two times on line 15 of file LinkedList.cpp where the add method start. Do not look at pop function as it is not completely implemented.
LinkedList.h source code:
#pragma once
template <typename T>
struct TNode {
T info;
TNode* next;
TNode* prev;
};
template <typename T>
class LinkedList {
private:
TNode* head, * tail;
int size = 0;
public:
LinkedList();
void add(T info);
T pop();
T peekTail();
T peekHead();
void print();
void rprint();
uint64_t length();
bool empty();
void debug();
};
LinkedList.cpp source code:
#include <cstdlib>
#include <iostream>
#include "LinkedList.h"
using namespace std;
template <typename T>
LinkedList<T>::LinkedList() {
head = NULL;
tail = NULL;
}
template <typename T>
void LinkedList<T>::add(T info) {
TNode* temp = new TNode;
temp->info = info;
temp->next = NULL;
if (head == NULL) {
head = temp;
tail = temp;
}
else {
tail->next = temp;
temp->prev = tail;
tail = tail->next;
}
size++;
}
template <typename T>
T LinkedList<T>::pop() {
if (size != 0) {
T info = tail->info;
size--;
return info;
}
}
template <typename T>
T LinkedList<T>::peekTail() {
return tail->info;
}
template <typename T>
T LinkedList<T>::peekHead() {
return head->info;
}
template <typename T>
void LinkedList<T>::print() {
cout << "Elements of the Linked List: ";
TNode* temp = head;
while (temp != NULL) {
cout << temp->info << " ";
temp = temp->next;
}
}
template <typename T>
void LinkedList<T>::rprint() {
cout << "Elements of the Linked List (Reverse): ";
TNode* temp = tail;
while (temp != NULL) {
cout << temp->info << " ";
temp = temp->prev;
}
}
template <typename T>
uint64_t LinkedList<T>::length() {
return size;
}
template <typename T>
bool LinkedList<T>::empty() {
if (size == 0)
return true;
else
return false;
}
template <typename T>
void LinkedList<T>::debug() {
cout << length() << endl;
print();
cout << endl;
rprint();
}
How I do solve that problem?
You have TNode* head, * tail;, but TNode is a template class, so you must give it a type. In your case, you probably want TNode<T> *head, *tail;, so that the node contains the same as the linked list. Anywhere in your LinkedList where you use TNode would also need to specify the template parameter.
You're going to end up with other problems though. See here as for why.

Linking Doubly linked list with Stack and Queue classes in C++

so I have an assignment where I need to create a doubly linked list and then create a stack and queue class and inherit from the linkedlist class in order to create an RPN calculator. So far I have created my doubly linkedlist class and the other to classes. However, I am having trouble understanding how I will inherit and use the linked list class with the stack and queue. I will provide what I have so far.
I have gone to tutoring and have not had much help so I thought I would look for some extra help, do not want homework done for me but to just be pointed in the right direction.
Stack.h
using std::iterator;
using std::vector;
using std::string;
template<class T>
class Stack : public vector<T>
{
private:
T getElement(bool erase);
typename std::vector<T> ::iterator pEnd;
T top;
public:
Stack();
T pop();
T peek();
void push(T elem);
};
template<class T>
Stack<T>::Stack()
{
}
template<class T>
void Stack<T>::push(T elem)
{
this->push_back(elem);
}
template<class T>
T Stack<T>::peek()
{
return this->getElement(false);
}
template<class T>
T Stack<T>::pop()
{
return this->getElement(true);
}
template<class T>
T Stack<T>::getElement(bool erase)
{
this->pEnd = this->end() - 1;
T tmp;
if (this->size() > 0)
{
tmp = *this->pEnd;
if (erase) {
this->erase(pEnd);
}
}
return tmp;
}
Queue.h
using namespace std;
class Queue
{
private:
int items[MAXQUEUE];
int head;
int tail;
public:
Queue();
bool isEmpty();
bool isFull();
bool enqueue(int item);
int dequeue();
int peek();
};
Queue::Queue()
:head(QEMPTY), tail(QEMPTY)
{
}
bool Queue::isEmpty()
{
return this->head == this->tail;
}
bool Queue::isFull()
{
return this->tail == MAXQUEUE;
}
bool Queue::enqueue(int item)
{
if (this->isFull())
return false;
this->items[this->tail] = item;
tail = (tail + 1) % MAXQUEUE;
return true;
}
int Queue::dequeue()
{
if (this->isEmpty())
return EMPTY;
int item = this->items[head];
this->head = (this->head + 1) % MAXQUEUE;
return item;
}
int Queue::peek() {
return this->tail;
}
doublylinkedlist.h
using std::iterator;
using std::vector;
using std::string;
/*START OF NODE CLASS*/
/*---------------------------------------------*/
template<class T>
struct Node
{
T Data;
T Search;
T value;
Node<T>*Next;
Node<T>*Prev;
};
template<class T>
class LinkedList
{
private:
Node<T> *Head;
public:
LinkedList();
void addNode(T Data);
void deleteNode(T Search);
void insert(T Search, T value);
void printListBackwards();
void printListForwards();
};
template<class T>
LinkedList<T>::LinkedList()
{
this->Head = NULL;
}
template<class T>
void LinkedList<T>::addNode(T data)
{
if (Head == NULL)
{
Head = new Node<T>;
Head->Data = data;
Head->Next = NULL;
Head->Prev = NULL;
}
else
{
Node<T>*p = this->Head;
while (p->Next != NULL)
p = p->Next;
Node<T>*n = new Node<T>;
n->Data = data;
n->Next = NULL;
p->Next = n;
n->Prev = p;
}
}
template<class T>
void LinkedList<T>::insert(T Search, T value)
{
Node *p = Head;
while (p->Data != Search)
{
p = p->Next;
}
Node *n = new Node;
n->Data = value;
n->Next = p->Next;
p->Next = n;
}
template<class T>
void LinkedList<T>::deleteNode(T Search)
{
Node *p = Head;
while (p->Next->Data != Search)
{
p = p->Next;
}
Node *delPtr = p->Next;
p->Next = p->Next->Next;
delete delPtr;
}
template<class T>
void LinkedList<T>::printListBackwards()
{
Node<T> *p = Head;
while (p->Next != NULL)
{
p = p->Next;
}
while (p != NULL)
{
cout << p->Data<< endl;
p = p->Prev;
}
}
template<class T>
void LinkedList<T>::printListForwards()
{
Node<T> *p = Head;
while (p != NULL)
{
cout << p->Data << endl;
p = p->Next;
}
}
A doubly linked list can be added to at the head or the tail, and removed at the tail.
A stack pushes at one end (the head?) and pops at the same end (the head).
A queue pushes at one end (the tail) and pops at the other end (the head).

Bubble sort a doubly linked list

I've gone through a bunch of threads trying to understand what is going on exactly with linked lists and bubblesort, and I think I get the bulk of it.
Right now my program is simply crashing when I get to the sort function and I am not sure why. Hopefully another set of eyes will see what I do not.
Any help is greatly appreciated.
DoublyList.h:
#include "listNode.h"
#ifndef DOUBLYLIST_H
#define DOUBLYLIST_H
template <typename T>
class DoublyList
{
public:
DoublyList();
~DoublyList();
void addFront(T d);
void addBack(T d);
T removeFront();
T removeBack();
T peak();
bool isEmpty();
int getSize();
void printList();
void sortList();
private:
ListNode<T> *front;
ListNode<T> *back;
int numOfElements;
};
template <typename T>
DoublyList<T>::DoublyList(){
front = NULL;
back = NULL;
numOfElements = 0;
}
template <typename T>
DoublyList<T>::~DoublyList(){
if(numOfElements!=0){
ListNode<T> *current;
current = front;
while (current != back)
{
ListNode<T> *temp = current;
current = current->next;
temp->next = NULL;
temp->prev = NULL;
delete temp;
numOfElements--;
}
//at this point current = back, now delete it
current->next = NULL;
current->prev = NULL;
delete current;
numOfElements--;
}
//this is a safeguard if you create a LL and then delete it without doing anything to it
else{
cout<<"deleted empty LL"<<endl;
delete front;
delete back;
}
}
template <typename T>
void DoublyList<T>::addFront(T d)
{
ListNode<T> *node = new ListNode<T>();
node->data = d;
if (isEmpty()){
back = node;
}
else{
front->prev = node;
}
node->next = front;
front = node;
++numOfElements;
}
template <typename T>
T DoublyList<T>::removeFront()
{
if (isEmpty()){
return T();
}
else
{
ListNode<T>* temp = front;
if (front->next == 0){
back = 0;
}
else
{
front->next->prev = 0;
}
front = front->next;
temp->next = 0;
T theData = temp->data;
delete temp;
--numOfElements;
return theData;
}
}
template <typename T>
void DoublyList<T>::addBack(T d)
{
ListNode<T> *node = new ListNode<T>();
node->data = d;
if (isEmpty()){
front = node;
}
else{
back->next = node;
}
node->prev = back;
back = node;
++numOfElements;
}
template <typename T>
T DoublyList<T>::removeBack()
{
if (isEmpty()) {
return T();
}
else
{
ListNode<T>* temp;
temp = back;
if (back->prev == 0){
front = 0;
}
else{
back->prev->next = 0;
}
back = back->prev;
temp->prev = 0;
T theData = temp->data;
delete temp;
--numOfElements;
return theData;
}
}
template <typename T>
T DoublyList<T>::peak()
{
if (isEmpty()) {
return T();
}
return front->data;
}
template <typename T>
int DoublyList<T>::getSize(){
return numOfElements;
}
template <typename T>
bool DoublyList<T>::isEmpty(){
if(numOfElements == 0){
return true;
}
else{
return false;
}
}
template <typename T>
void DoublyList<T>::printList(){
if(numOfElements!=0){
ListNode<T> *current = front;
while(current!=back)
{
cout<<current->data<<endl;
current = current->next;
}
cout<<back->data<<endl;
}
else{
cout<<"list is empty"<<endl;
}
}
template <typename T>
void DoublyList<T>::sortList(){
int size = getSize();
ListNode<T> *current;
ListNode<T> *dummy;
ListNode<T> *next;
if(current == NULL) return;
if(current -> next == NULL) return;
int swapped = 1;
while(swapped){
swapped = 0; //last pass unless there is a swap
while(current -> next != NULL){
if(current-> data < current -> next -> data){
swapped = 1; //swap, will need to re-enter while loop
//actual number swap
dummy -> data = current -> data;
current -> data = current -> next -> data;
current -> next -> data = dummy -> data;
}
current = current -> next;
}
}
}
#endif
listNode.h:
#include <iostream>
#ifndef LISTNODE_H
#define LISTNODE_H
using namespace std;
template <typename T>
class ListNode
{
public:
T data;//the data that we will store
ListNode();
ListNode(int d);
~ListNode();
ListNode *next;//int and ptr and the member variables
ListNode *prev;
};
template <typename T>
ListNode<T>::ListNode(int d){
data = d;
next = NULL;
prev = NULL;
}
template <typename T>
ListNode<T>::ListNode(){}
template <typename T>
ListNode<T>::~ListNode(){
delete next;
delete prev;
cout<<"deleted Node"<<endl;
}
#endif
testList.cpp
#include <iostream>
#include "doublyList.h"
#include "genericQueue.h"
int main(){
DoublyList<int> testQueue;
testQueue.addBack(3);
testQueue.addBack(5);
testQueue.addBack(2);
testQueue.addBack(10);
testQueue.addBack(1);
cout << "Before Sort: " << endl;
testQueue.printList();
cout << "After Sort: " << endl;
testQueue.sortList();
testQueue.printList();
}
The erors I could find so far are:
Your default ListNode() constructor doesn't null the next and prev pointers.
In void DoublyList<T>::sortList() you don't initialize dummy, so it just points into nowhere. Actually there is no reason to use a node list at all, you can just directly use a variable of type T.
You don't initialize current in the same function and you actually should reset current to e.g. front at the beginning of each outer loop.
You don't use next at all (and don't need to), so just remove it.
To sum it up, this is what void DoublyList<T>::sortList() could look like:
template <typename T>
void DoublyList<T>::sortList(){
int size = getSize();
ListNode<T> *current=front;
T dummy;
if (current == NULL) return;
if (current->next == NULL) return;
int swapped = 1;
while (swapped){
current = front;
swapped = 0; //last pass unless there is a swap
while (current->next != NULL){
if (current->data < current->next->data){
swapped = 1; //swap, will need to re-enter while loop
//actual number swap
dummy = current->data;
current->data = current->next->data;
current->next->data = dummy;
}
current = current->next;
}
}
}
and this is my suggestion for the ListNode constructor.
template <typename T>
ListNode<T>::ListNode() :
next(nullptr),
prev(nullptr),
data{}
{}
Besides that, I also agree with DaveB that swapping pointers is the approach you should actually use.
To start with you need to initialize current in your sort function,
current = first;
template <typename T>
void DoublyList<T>::sortList(){
ListNode<T> *current;
ListNode<T> *next;
T tmp;
current = front;
if(current == NULL) return;
if(current -> next == NULL) return;
int swapped = 1;
while(swapped){
swapped = 0; //last pass unless there is a swap
while(current->next != nullptr){
if(current->data < current->next->data){
swapped = 1; //swap, will need to re-enter while loop
//actual number swap
tmp = current->data;
current->data = current->next->data;
current->next->data = tmp;
}
current = current -> next;
}
if (swapped) // go back to start of list for next pass
current = front;
}
}

The member functions of my class aren't working properly. Any idea why?

I made a linked list class to practice generic programming. The following code compiles, but my test in the main isn't printing anything to the console, like it should be. Any idea why? I know that Stack Overflow doesn't like the "fix my bug" posts, but I'm really at a loss here.
#include <iostream>
template <class T> class List {
public:
List();
~List();
int getSize();
void push_back(T);
bool contains(T);
private:
struct node {
T val;
node* next;
};
int size;
node* firstNodePtr;
node* lastNodePtr;
};
template <class T> List<T>::List() {
size = 0;
firstNodePtr = NULL;
lastNodePtr = NULL;
}
template <class T> List<T>::~List() {
node* curNodePtr = firstNodePtr;
node* nextNodePtr;
while (curNodePtr) {
nextNodePtr = curNodePtr->next;
delete curNodePtr;
curNodePtr = nextNodePtr;
}
}
template <class T> int List<T>::getSize() {
return size;
}
template <class T> void List<T>::push_back(T newElement) {
if (size == 0) {
firstNodePtr = new node;
firstNodePtr->next = lastNodePtr;
firstNodePtr->val = newElement;
++size;
} else {
node* newNode = new node;
lastNodePtr->next = newNode;
newNode->val = newElement;
newNode->next = NULL;
++size;
}
}
template <class T> bool List<T>::contains(T thisElement) {
node* curNodePtr = firstNodePtr;
while (curNodePtr) {
if (curNodePtr->val == thisElement)
return true;
curNodePtr = curNodePtr->next;
}
return true;
}
int main (int argc, char* const argv[]) {
List<int> myList;
myList.push_back(5);
myList.push_back(18);
std::cout << myList.getSize() << std::endl;
std::cout << myList.contains(18);
return 0;
}
Look here:
if (size == 0){
firstNodePtr = new node;
firstNodePtr->next = lastNodePtr;
firstNodePtr->val = newElement;
++size;
}
You forgot to assign a value to lastNodePtr. So when you try to dereference it in the second call to push_back, you get undefined behavior.
In the block handling the creation of the initial node in push_back,
you don't want this line:
firstNodePtr->next = lastNodePtr;
Also, you need to set lastNodePtr = firstNodePtr; at the end of push_back

how to extract a list from a linked list in c++

I'm trying to implement those two functions "extract" and "deleteList" and I somehow can't get my head around it.
I know how a linked-list works but I'm new to programming and just can't figure out an algorithm. Could I ask for some tips?
I want the extract function to return a list of values that fulfill the predicate and remove those from the original list (thats why its passed as a reference).
I want the delete function to delete all those that are the same as those passed from the argument
My code looks like this:
#include <iostream>
#include <string>
using namespace std;
template <typename T>
struct Node
{
T data;
Node* next;
};
template <typename T>
void showList(const Node<T>* head)
{
while(head->next != NULL)
{
cout<<head->data<<" ";
head = head->next;
}
cout<<endl;
}
template <typename T>
Node<T>* arrayToList(const T tab[], size_t size)
{
Node<T> *prev;
for(int i = size-1; i>=0 ; i--){
Node<T> *p = new Node<T>;
p->data = tab[i];
p->next = prev;
prev = p;
}
return prev;
}
template<typename T>
Node<T>* extract(Node<T>*& head, bool (*predicate)(const T&))
{
}
template <typename T>
void deleteList(Node<T>*& head)
{
//delete passed in
}
bool isEven(const int& n)
{
return n%2 == 0;
}
bool isLong(const string& s)
{
return s.size() >=5;
}
Thank you guys!
Firstly, your showList() has a potential problem with dereferencing
a null pointer. So it should look like this:
template <typename T>
void showList(const Node<T>* head)
{
while(head != NULL)
{
cout << head->data << " ";
head = head->next;
}
cout << endl;
}
Secondly, it is more convenient to have auxiliary functions like
pushToList() and popFromList():
template <typename T>
void pushToList(Node<T>*& head, const T &element)
{
Node<T> *p = new Node<T>;
p->data = element;
p->next = head;
head = p;
}
template <typename T>
T popFromList(Node<T>*& head)
{
T value;
if (head != NULL) {
Node<T>* tmp = head;
value = head->data;
head = head->next;
delete tmp;
}
return value;
}
You can rewrite your arrayToList() using pushToList():
template <typename T>
Node<T>* arrayToList(const T tab[], size_t size)
{
Node<T>* head = NULL;
for(int i = size - 1; i >= 0; i--){
pushToList(head, tab[i]);
}
return head;
}
And implement deleteList() using popFromList():
template <typename T>
void deleteList(Node<T>*& head)
{
while (head != NULL) {
popFromList(head);
}
}
exctract() also can be implemented in terms of push and pop. You
just create two temporary lists and push to them according to the
predicate:
template<typename T>
Node<T>* extract(Node<T>*& head, bool (*predicate)(const T&))
{
Node<T> *extracted = NULL;
Node<T> *rest = NULL;
while (head != NULL) {
T value = popFromList(head);
if (predicate(value)) {
pushToList(extracted, value);
} else {
pushToList(rest, value);
}
}
reverseList(extracted);
reverseList(rest);
head = rest;
return extracted;
}
One problem is after the main work the temporary lists are
reversed. So we need the reverseList() function, which can be also
implemented in terms of push and pop:
template <typename T>
void reverseList(Node<T>*& head)
{
Node<T> *result = NULL;
while(head != NULL) {
pushToList(result, popFromList(head));
}
head = result;
}
It is not a very effective implementation but I think it does the work.
I've put the complete source code here.