templateClassName <className> t; Cannot assign class to template class argument - c++

C++ noob here. I trying to create a student information program by implementing
a Linked-List class as its data structure.
LinkedList.h
#pragma once
#include <stdexcept>
template <typename T>
class LinkedList
{
private:
struct Node
{
T elem;
Node *prev;
Node *next;
};
Node *header;
Node *trailer;
int size;
public:
LinkedList()
{
header = new Node;
trailer = new Node;
header->next = trailer;
trailer->prev = header;
}
~LinkedList()
{
while (!isEmpty())
removeFirst();
delete header;
delete trailer;
}
const int& n_elem() const
{
return size;
}
const bool isEmpty() const
{
return size == 0;
}
const T& getFirst() const
{
if (isEmpty())
throw std::out_of_range("List is empty.");
return header->next->elem;
}
const T& getLast() const
{
if (isEmpty())
throw std::out_of_range("List is empty.");
return trailer->prev->elem;
}
void addFirst(const T& item)
{
addBetween(item, header, header->next);
}
void addLast(const T& item)
{
addBetween(item, trailer->prev, trailer);
}
void addAt(int index, const T& item)
{
Node *node = header;
for (int i = 0; i < index; i++)
node = node->next;
addBetween(item, node, node->next);
}
const T removeFirst()
{
if (isEmpty())
throw std::out_of_range("List is empty.");
return remove(header->next);
}
const T removeLast()
{
if (isEmpty())
throw std::out_of_range("List is empty.");
return remove(trailer->prev);
}
const T removeAt(int index)
{
if (isEmpty())
throw std::out_of_range("List is empty.");
Node *node = header;
for (int i = 0; i < index; i++)
node = node->next;
return remove(node->next);
}
const T& itemAt(int index) const
{
if (isEmpty())
throw std::out_of_range("List is empty.");
Node *node = header;
for (int i = 0; i < index; i++)
node = node->next;
return node->next->elem;
}
protected:
void addBetween(const T& item, Node *predecessor, Node *successor)
{
Node *newest = new Node;
newest->prev = predecessor;
newest->next = successor;
predecessor->next = newest;
successor->prev = newest;
size++;
}
const T remove(Node *node)
{
Node *predecessor = node->prev;
Node *successor = node->next;
predecessor->next = successor;
successor->prev = predecessor;
T oldItem = node->elem;
size--;
delete node;
return oldItem;
}
};
Student class is defined below.
Program.cpp
#include "stdafx.h"
#include <iostream>
#include <string>
#include "LinkedList.h"
using namespace std;
class Student
{
public:
string name;
string id;
int score;
static const int total = 100;
double grade;
Student(string n, string i, int s)
{
name = n;
id = i;
score = s;
grade = getGrade(score);
}
private:
double getGrade(int score)
{
return (23.0 / 3.0 - ((20.0 * score) / (3.0 * total)));
}
};
LinkedList<Student> l;
int main()
{
//Some code here
return 0;
}
I don't know the reason why
LinkedList<Student> l;
produces an error:
LinkedList<Student>::Node::Node(void)': attempting to reference a deleted function
But when I use:
LinkedList<Student*> l;
there's no error.
Please help.
I'm using Visual Studio 2015.
And sorry for bad English.

In LinkedList<Student>, the inner struct Node looks like this:
struct Node
{
Student elem;
Node *prev;
Node *next;
};
so every Node contains a Student.
However, you'll note that Student has a constructor that takes arguments:
Student(string n, string i, int s)
and it does not have a constructor that does not take arguments.
So if you were to write new Node, the computer would create a Node, and as part of that it would create a Student, but it can't do that because it doesn't have any arguments to give to Student's constructor.
That's (approximately) what "deleted function" means here - normally the compiler would make a Node constructor for you, but in this case it can't.
And so new Node doesn't work, because Node doesn't have a constructor.
Probably the easiest fix here is just to give Student a no-argument constructor as well - something like:
Student()
{
name = "";
id = "";
score = 0;
grade = getGrade(score);
}

Related

double free detected in tcache 2 when initializing a list, crashes upon entry insertion

Reading from a file, each line is stored in a list as an individual row. Each row contains two standard values and a variable amount stored in a list. Therefore each node has two values and a list. Initialization through operator>> works, but as soon as I try to run the loadfile function it crashes with the error: free(): double free detected in tcache 2 Aborted (core dumped)
Here is the code
#include <iostream>
#include "Resource.h"
#include "list.h"
#include "node.h"
using std::cout;
using rows = List<Resource>;
using row = Node<Resource>;
void loadFile(string idata, rows &res)
{
ifstream ifs(idata, ifstream::in);
while (ifs.good())
{
Resource s;
ifs >> s;
row *temp = new Node<Resource>(s);
res.insert(temp);
}
ifs.close();
}
int main()
{
rows resList;
loadFile("data.txt", resList);
cout << resList.getHead()->getValue();
}
this is the source for the class that stores the values, that will be wrapped in a Node template class.
#ifndef RESOURCE_H
#define RESOURCE_H
#include <iostream>
#include <fstream>
#include <string>
#include "list.h"
#include "node.h"
#include <stdio.h>
#include <algorithm>
using std::cout;
using std::istream;
using std::string;
class Resource
{
private:
string Name;
int amt;
List<string> clientList;
public:
Resource(string n, int a) : Name(n), amt(a) {}
Resource(string n) : Resource(n, 0) {}
Resource() : Resource("", 0) {}
string getName()
{
return this->Name;
}
int getAmt()
{
return this->amt;
}
void setName(string n)
{
this->Name = n;
}
void setAmt(int a)
{
this->amt = a;
}
friend ostream &operator<<(ostream &out, const Resource &r)
{
out << r.Name << ";" << r.amt;
List<string> temp = r.clientList;
for (Node<string> *app = temp.getHead(); app != NULL; app = app->getNext())
{
out << ';';
out << app->getValue();
}
return out;
}
friend istream &operator>>(istream &in, Resource &r)
{
string Name;
string amt;
string params;
string tempVar;
getline(in, Name, ';');
getline(in, amt, ';');
getline(in, params, '\n');
const int paramsOriginalLength = count(params.begin(), params.end(), ';');
for (int i = 0; i < paramsOriginalLength; i++)
{
r.clientList.insert(params.substr(0, params.find(';')));
params.erase(0, params.find(';') + 1);
}
r.setName(Name);
r.setAmt(stoi(amt));
return in;
}
};
#endif
EDIT: Since the problem might be caused by the data structure's defintion I will include the source of list.h and node.h
List:
#ifndef LIST_H
#define LIST_H
// Standard Template Linked List - List - by Eduardo Meli - 2020
#include "node.h"
#include <iostream>
using namespace std;
template <class T>
class List
{
private:
int length;
Node<T> *head;
public:
List(int length, Node<T> *head) : length(length), head(head) {}
List() : List(0, NULL) {}
Node<T> *getHead()
{
return this->head;
}
int getLength()
{
return this->length;
}
void insert(T value)
{
Node<T> *app = new Node<T>(value);
this->insert(app);
}
void insert(Node<T> *n)
{
if (head == NULL)
{
head = n;
length++;
return;
}
Node<T> *curr = head;
while (curr->getNext() != NULL)
{
curr = curr->getNext();
}
curr->setNext(n);
length++;
}
void deleteNode(Node<T> *n)
{
if (n == this->getHead())
{
this->head = head->getNext();
this->length = length - 1;
delete n;
return;
}
Node<T> *prev = head;
Node<T> *curr = head->getNext();
while (curr != NULL)
{
if (curr == n)
{
prev->setNext(curr->getNext());
length--;
return;
}
prev = curr;
curr = curr->getNext();
}
}
Node<T> *deleteNode(T value)
{
if (this->seekNode(value))
{
if (head->getValue() == value)
{
Node<T> *temp = head;
head = head->getNext();
length--;
return temp;
}
Node<T> *prev = head;
Node<T> *curr = head->getNext();
while (curr != NULL)
{
if (curr->getValue() == value)
{
prev->setNext(curr->getNext());
length--;
return curr;
}
prev = curr;
curr = curr->getNext();
}
}
return NULL;
}
void print()
{
Node<T> *nk = this->getHead();
while (nk != NULL)
{
cout << nk->getValue() << endl;
nk = nk->getNext();
}
}
~List()
{
Node<T> *ptr;
for (ptr = head; head; ptr = head)
{
head = head->getNext();
delete ptr;
}
}
};
#endif
And node:
#ifndef NODE_H
#define NODE_H
// Standard Template Linked List - Node - by Eduardo Meli - 2020
#include <fstream>
#include <iostream>
using namespace std;
template <class T>
class Node
{
private:
T value;
Node<T> *next;
public:
Node(T value, Node<T> *next) : value(value), next(next) {}
Node(T value) : Node(value, NULL) {}
Node() : Node(0, NULL) {}
T getValue()
{
return this->value;
}
Node<T> *getNext()
{
return this->next;
}
void setValue(T val)
{
this->value = val;
}
void setNext(Node<T> *n)
{
this->next = n;
}
friend ostream &operator<<(ostream &out, const Node &n)
{
out << n.value;
return out;
}
};
#endif

a simple payroll system using linked list c++

i am simply creating a payroll system that has a employee name and a working hours for that employee.. the data is supposed to be stored in a linked list data structure, but i can not connect the linked list to the object of the class employee, i tried making the pay roll linked list (i.e empList) as a static member so that all the objects of the class can use the same list object and data can be stored but once i compile my code i get an error of "undefined reference to employee::empList" at line 130 that is the last line of constructor, same error on line 150 that is a print pay roll function.. where ever i am trying to call any payRollLinkedList class's function in employee class it gives error.. bottom line is that all i want is to data be stored in a doubly linked list of employees and i can not access the list.
#include <iostream>
using namespace std;
class payRollLinkedList;
class node
{
private:
node* previousPointer;
string name;
int hoursWorked;
node* nextPointer;
friend class payRollLinkedList;
public:
explicit node(const string argName, const int argHoursWorked)
: previousPointer{nullptr}, name{argName}, hoursWorked{argHoursWorked}, nextPointer{nullptr}
{}
};
class payRollLinkedList
{
private:
node* headPointer{nullptr};
node* tailPointer{nullptr};
node* getNewNode(const string argName, const int argHoursWorked)
{
return new node(argName, argHoursWorked);
}
public:
void addAtBack(const string argName, const int argHoursWorked)
{
node* newNode{getNewNode(argName, argHoursWorked)};
if(isEmpty())
{
headPointer = tailPointer = *newNode;
}
else
{
tailPointer->nextPointer = newNode;
newNode->previousPointer = tailPointer;
tailPointer = newNode;
newNode = nullptr;
delete newNode;
}
}
bool deleteNode(string argName)
{
node* currentPointer{headPointer};
if(isEmpty())
{
cout <<"the list is already empty\n";
return false;
}
else
{
while(currentPointer != nullptr)
{
if(currentPointer->name == argName)
{
if(currentPointer == headPointer)
{
node* tempPointer{headPointer};
headPointer = headPointer->nextPointer;
tempPointer->nextPointer = nullptr;
headPointer->previousPointer = nullptr;
delete tempPointer;
break;
}
if(currentPointer == tailPointer)
{
node*tempPointer{tailPointer};
tailPointer = tailPointer->previousPointer;
tempPointer->previousPointer = nullptr;
tailPointer->nextPointer = nullptr;
delete tempPointer;
break;
}
node* tempPointer{currentPointer};
node* nextPtr{tempPointer->nextPointer};
currentPointer = currentPointer->previousPointer;
currentPointer->nextPointer = nextPtr;
nextPtr->previousPointer = currentPointer;
tempPointer->nextPointer = nullptr;
tempPointer->previousPointer = nullptr;
currentPointer = nullptr;
nextPtr = nullptr;
delete tempPointer;
delete currentPointer;
delete nextPtr;
}
else
currentPointer = currentPointer->nextPointer;
}
return true;
}
}
void print()
{
if(isEmpty())
{
cout <<"nothing to show\n";
return;
}
else
{
node* currentPointer{headPointer};
while(currentPointer != nullptr)
{
cout <<currentPointer->name <<"\t";
currentPointer = currentPointer->nextPointer;
}
}
}
bool isEmpty()
{
return headPointer == nullptr? true : false;
}
};
class employee
{
private:
string name;
int hoursWorked;
static payRollLinkedList empList;
public:
employee()
: name{""}, hoursWorked{0}
{}
employee(string argName, int argHoursWorked)
{
name = argName;
hoursWorked = argHoursWorked;
empList.addAtBack(name, hoursWorked);
}
void printPayRoll()
{
empList.print();
}
};
int main()
{
employee emp("usman", 12);
employee emp1("ali", 12);
emp.printPayRoll();
}
https://en.cppreference.com/w/cpp/language/static
You need to define static member of class at global scope (out of class).
i suggest you to split your code .h and .cpp files and define the member in .cpp file.
payRollLinkedList employee::empList;

How to fix Access Violation Reading location error? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am currently working on a program that uses a Hash table. I have worked on my own Hash table class and the program works but then crashes after it has already done the work involving the hash table. The error I get is a Access Violation reading location error. I have spent hours going through my code and still cannot find what I'm doing wrong or why the program is crashing. Here are my problem classes below:
Hashtable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <string>
#include "LinkedList.h"
#include <iostream>
using namespace std;
class hashTable
{
public:
hashTable();
virtual ~hashTable();
void insertNode(string nodeData);
bool removeNode(string nodeKey);
Node * checkForDuplicate( string nodeData );
private:
LinkedList * tableArray;
int length;
int hash(string stateKey);
};
#endif // HASHTABLE_H
Hashtable.cpp:
#include "hashTable.h"
hashTable::hashTable()
{
length = 181667;
tableArray = new LinkedList[length];
}
int hashTable::hash(string stateKey) {
int multiplier = 1;
int total = 0;
int l = stateKey.length();
for(int i = l - 1; i > -1; --i) {
int temp;
temp = (stateKey[i] - '0') * multiplier;
total += temp;
multiplier = multiplier * 10;
}
return(total) % length;
}
void hashTable::insertNode(string stateData) {
Node * newNode;
newNode = new Node;
newNode->data = stateData;
int index = hash(newNode -> data);
tableArray[index].insertNode(newNode);
delete newNode;
}
bool hashTable::removeNode(string nodeKey) {
int index = hash(nodeKey);
return tableArray[index].removeNode(nodeKey);
}
Node * hashTable::checkForDuplicate( string nodeData )
{
int index = hash( nodeData );
return tableArray[ index ].getNode(nodeData);
}
hashTable::~hashTable()
{
delete [] tableArray;
//dtor
}
LinkedList.h:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include<string>
#include<iostream>
using namespace std;
struct Node {
string data;
Node *next;
};
class LinkedList
{
public:
LinkedList();
void insertNode(Node * newNode);
bool removeNode(string stateData);
Node * getNode(string stateData);
int getLength();
virtual ~LinkedList();
private:
Node * top;
int length;
};
#endif // LINKEDLIST_H
LinkedList.cpp:
#include "LinkedList.h"
LinkedList::LinkedList()
{
top = new Node;
top->next = NULL;
length = 0;
}
void LinkedList :: insertNode(Node * newNode) {
Node * a = top;
Node * b = top;
while(b) {
a = b;
b = a -> next;
if (a== NULL) { break; }
}
a -> next = newNode;
newNode -> next = NULL;
length++;
}
bool LinkedList :: removeNode(string stateData) {
if(!top -> next){
return false;
}
Node * a = top;
Node * b = top;
while(b) {
if(b->data == stateData) {
a->next = b->next;
delete b;
length--;
return true;
}
a = b;
b = a ->next;
}
return false;
}
Node * LinkedList :: getNode(string stateData) {
if(top == NULL) { return NULL ;}
Node * current = top;
while (current->next != NULL) {
if((current->data == stateData)) {
return current;
}
current = current -> next;
}
return NULL;
}
int LinkedList :: getLength() {
return length;
}
LinkedList::~LinkedList()
{
Node * a = top;
Node * b = top;
while (b) {
a = b;
b = a->next;
if(b) delete a;
}
}
Your hashTable::insertNode() method is allocating a new Node object, then passing it to LinkedList::insertNode() to take ownership of the object, but then delete's it afterwards, thus leaving the LinkedList with a dangling pointer to invalid memory. Any access to that node will cause undefined behavior. DO NOT delete the new node after LinkedList takes ownership of it.
It would be better if LinkedList::insertNode() took a string as input instead of a Node* pointer. Let LinkedList allocate the new node internally.
Also, there are some other minor issues with your LinkedList() implementation in general (like not following the Rule of Three, and not using a double-linked list for more efficient inserts and removals).
Try something more like this instead:
Hashtable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <string>
#include "LinkedList.h"
class hashTable
{
public:
hashTable();
hashTable(const hashTable &src);
~hashTable();
void insertNode(const std::string &nodeData);
bool removeNode(const std::string &nodeData);
bool checkForDuplicate(const std::string &nodeData);
hashTable& operator=(const hashTable &rhs);
private:
std::vector<LinkedList> tableArray;
int length;
int hash(const std::string &nodeData);
};
#endif // HASHTABLE_H
Hashtable.cpp:
#include "hashTable.h"
hashTable::hashTable()
: length(181667), tableArray(new LinkedList[length])
{
}
hashTable::hashTable(const hashTable &src)
: length(src.length), tableArray(new LinkedList[length])
{
for (int i = 0; i < length; ++i)
tableArray[i] = src.tableArray[i];
}
hashTable::~hashTable()
{
delete[] tableArray;
}
hashTable& hashTable::operator=(const hashTable &rhs)
{
hashTable tmp(rhs);
std::swap(tableArray, tmp.tableArray);
std::swap(length, tmp.length);
return *this;
}
int hashTable::hash(const std::string &nodeData)
{
int multiplier = 1;
int total = 0;
int l = nodeData.length();
for(int i = l - 1; i > -1; --i)
{
int temp = (nodeData[i] - '0') * multiplier;
total += temp;
multiplier *= 10;
}
return total % length;
}
void hashTable::insertNode(const std::string &nodeData)
{
int index = hash(nodeData);
tableArray[index].insertNode(nodeData);
}
bool hashTable::removeNode(const std::string &nodeData)
{
int index = hash(nodeData);
return tableArray[index].removeNode(nodeData);
}
bool hashTable::checkForDuplicate(const std::string &nodeData)
{
int index = hash(nodeData);
return (tableArray[index].getNode(nodeData) != NULL);
}
LinkedList.h:
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <string>
struct Node
{
std::string data;
Node *previous;
Node *next;
};
class LinkedList
{
public:
LinkedList();
LinkedList(const LinkedList &src);
~LinkedList();
void insertNode(const std::string &nodeData);
bool removeNode(const std::string &nodeData);
Node* getNode(const std::string &nodeData);
int getLength();
LinkedList& operator=(const LinkedList &rhs);
private:
Node *head;
Node *tail;
int length;
};
#endif // LINKEDLIST_H
LinkedList.cpp:
#include "LinkedList.h"
#inclue <algorithm>
LinkedList::LinkedList()
: head(NULL), tail(NULL), length(0)
{
}
LinkedList::LinkedList(const LinkedList &src)
: head(NULL), tail(NULL), length(0)
{
Node *current = src.top;
while (current != NULL)
{
insertNode(current->data);
current = current->next;
}
}
LinkedList::~LinkedList()
{
Node *current = top;
while (current != NULL)
{
Node *next = current->next;
delete current;
current = next;
}
}
LinkedList& LinkedList::operator=(const LinkedList &rhs)
{
LinkedList tmp;
Node *current = rhs.top;
while (current != NULL)
{
tmp.insertNode(current->data);
current = current->next;
}
std::swap(top, tmp.top);
std::swap(bottom, tmp.bottom);
std::swap(length, tmp.length);
return *this;
}
void LinkedList::insertNode(const string &nodeData)
{
Node *newNode = new Node;
newNode->data = nodeData;
newNode->previous = NULL;
newNode->next = NULL;
if (top == NULL) top = newNode;
if (bottom != NULL)
{
newNode->previous = bottom;
bottom->next = newNode;
}
bottom = newNode;
length++;
}
bool LinkedList::removeNode(const string &nodeData)
{
Node* node = getNode(nodeData);
if (node != NULL)
{
if (node->next != NULL)
node->next->previous = node->previous;
if (node->previous != NULL)
node->previous->next = node->next;
if (top == node)
top = node->next;
if (bottom == node)
bottom = node->previous;
delete node;
length--;
return true;
}
return false;
}
Node* LinkedList::getNode(const string &nodeData)
{
Node *current = top;
while (current != NULL)
{
if (current->data == nodeData)
return current;
current = current->next;
}
return NULL;
}
int LinkedList::getLength()
{
return length;
}
With that said, you can then get rid of LinkedList altogether by using std::list instead, and simplify hashTable's memory management by using std::vector:
Hashtable.h:
#ifndef HASHTABLE_H
#define HASHTABLE_H
#include <string>
#include <list>
#include <vector>
class hashTable
{
public:
hashTable();
void insertNode(const std::string &nodeData);
bool removeNode(const std::string &nodeData);
bool checkForDuplicate(const std::string &nodeData);
private:
std::vector< std::list<std::string> > tableArray;
int hash(const std::string &stateKey);
};
#endif // HASHTABLE_H
Hashtable.cpp:
#include "hashTable.h"
#include <algorithm>
hashTable::hashTable()
: tableArray(181667)
{
}
int hashTable::hash(const std::string &nodeData)
{
int multiplier = 1;
int total = 0;
int l = nodeData.length();
for(int i = l - 1; i > -1; --i)
{
int temp = (nodeData[i] - '0') * multiplier;
total += temp;
multiplier *= 10;
}
return total % length;
}
void hashTable::insertNode(const std::string &nodeData)
{
int index = hash(nodeData);
tableArray[index].push_back(nodeData);
}
bool hashTable::removeNode(const string &nodeData)
{
int index = hash(nodeData);
std::list<std::string>::iterator iter = std::find(tableArray[index].begin(), tableArray[index].end(), nodeData);
if (iter != tableArray[index].end())
{
tableArray[index].erase(iter);
return true;
}
return false;
}
bool hashTable::checkForDuplicate(const std::string &nodeData)
{
int index = hash(nodeData);
std::list<std::string>::iterator iter = std::find(tableArray[index].begin(), tableArray[index].end(), nodeData);
return (iter != tableArray[index].end());
}

C++ custom template LinkedList crashes adding std::string

For academic purposes, I'm trying to develop a little "textual adventure game". I have to implement all data structures by my own. Now, I have some problems with the implementation of a generic (template) LinkedList.
In the specific, this data structure works with everything (primitive data types and custom objects) BUT strings! (standard library strings).
When I try to add strings to a list, the application crashes with the following error (in console):
"terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_constructor null not valid"
The list is implemented as a "double linked list" using the head-node as first-last node
Here the code ("Abstract" List interface):
#ifndef LIST_H_
#define LIST_H_
template <class T>
class List
{
public:
virtual ~List() {}
virtual T get(int position) = 0;
virtual List* add(T item) = 0;
virtual List* insert(T item, int position) = 0;
virtual List* remove(int position) = 0;
virtual int size() const = 0;
virtual bool isEmpty() const = 0;
protected:
private:
};
#endif /* LIST_H_ */
This is the LinkedList implementation (the "node" class):
#include "List.h"
#include <stdlib.h>
#ifndef LINKEDLIST_H_
#define LINKEDLIST_H_
template <class T>
class ListNode
{
public:
ListNode(T item)
{
mItem = item;
mNext = NULL;
mPrev = NULL;
}
ListNode(T item, ListNode<T>* next, ListNode<T>* prev)
{
mItem = item;
mNext = next;
mPrev = prev;
}
~ListNode()
{
delete &mItem;
}
T getItem()
{
return mItem;
}
ListNode<T>* getNext()
{
return mNext;
}
ListNode<T>* getPrev()
{
return mPrev;
}
void setItem(T item)
{
mItem = item;
}
void setNext(ListNode<T>* next)
{
mNext = next;
}
void setPrev(ListNode<T>* prev)
{
mPrev = prev;
}
protected:
private:
T mItem;
ListNode<T> *mNext, *mPrev;
};
The LinkedList class:
template <class K>
class LinkedList : public List<K>
{
public:
LinkedList()
{
mSize = 0;
mFirstNode = NULL;
}
~LinkedList()
{
// implementazione distruttore tramite ciclo sui nodi
}
K get(int position)
{
K item = NULL;
ListNode<K>* targetNode = getNodeAtPosition(position);
if (targetNode != NULL) item = targetNode->getItem();
return item;
}
List<K>* add(K item)
{
if (mFirstNode == NULL)
{
mFirstNode = new ListNode<K>(item);
mFirstNode->setNext(mFirstNode);
mFirstNode->setPrev(mFirstNode);
}
else
{
ListNode<K>* newNode = new ListNode<K>(item, mFirstNode, mFirstNode->getPrev());
mFirstNode->getPrev()->setNext(newNode);
mFirstNode->setPrev(newNode);
}
mSize++;
return this;
}
List<K>* insert(K item, int position)
{
ListNode<K>* targetNode = getNodeAtPosition(position);
if (targetNode != NULL)
{
ListNode<K>* newNode = new ListNode<K>(targetNode->getItem(), targetNode->getNext(), targetNode);
targetNode->setItem(item);
targetNode->setNext(newNode);
mSize++;
}
return this;
}
List<K>* remove(int position)
{
ListNode<K>* targetNode = getNodeAtPosition(position);
if (targetNode != NULL)
{
targetNode->setItem(targetNode->getNext()->getItem());
targetNode->setNext(targetNode->getNext()->getNext());
//delete targetNode->getNext();
mSize--;
}
return this;
}
int size() const
{
return mSize;
}
bool isEmpty() const
{
return (mFirstNode == NULL) ? true : false;
}
protected:
ListNode<K>* getNodeAtPosition(int position)
{
ListNode<K>* current = NULL;
if (mFirstNode != NULL && position < mSize)
{
current = mFirstNode;
for (int i = 0; i < position; i++)
{
current = current->getNext();
}
}
return current;
}
private:
int mSize;
ListNode<K>* mFirstNode;
};
#endif /* LINKEDLIST_H_ */
Suggestions?
Part of your problem is here:
ListNode(T item)
{
mItem = item; // for a std::string, this will be a class member, non-pointer
mNext = NULL;
mPrev = NULL;
}
ListNode(T item, ListNode<T>* next, ListNode<T>* prev)
{
mItem = item; // same here
mNext = next;
mPrev = prev;
}
~ListNode()
{
delete &mItem; // you are attempting to delete an item you never created
}
You should either change your constructors to create a T* object on the heap (which will then be deleted in your destructor), or remove the delete line from your destructor.
This problem will be evident with far more than just std::string, by the way.
Somewhere in your program you are doing this:
std::string s(nullptr);
Calling std::string's constructor with a null pointer is causing it to throw a std::logic_error exception.
From the standard:
ยง 21.4.2
basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
Requires: s shall not be a null pointer and n < npos.
It seems it's not possible to pass std::string as template argument...
Strings as Template Arguments
Now I use an "old" - char const* - to achieve the expected result, even if I have to implement my personal "utils" methods to work with those pointers now...

C++ "No appropriate default constructor available"

I am trying to create a linked list of arrays without using the STL. However, I am having difficulties passing the array to my Linked List...
When I compile I get the error listed above. How do I need to pass the array to the linked list? Thanks! (The code in question is marked by **, please remove if testing.)
SinglyLinkedList.h
#pragma once
#ifndef SinglyLinkedList_h
#define SinglyLinkedList_h
#include<iostream>
template <typename Type>
struct node
{
Type value;
node *next;
};
template <typename Object>
class SinglyLinkedList
{
private:
node<Object> *head;
public:
SinglyLinkedList();
~SinglyLinkedList();
bool insert(Object x);
bool empty();
};
template <typename Object>
SinglyLinkedList<Object>::SinglyLinkedList()
{
this->head = NULL;
}
template <typename Object>
bool SinglyLinkedList<Object>::insert(Object x)
{
node<Object> *temp = new node<Object>;
temp->value = x;
temp->next = NULL;
if (this->head==NULL)
{
this->head = temp;
}
else
{
node<Object> *S = this->head, *P = S;
while ((S->value < temp->value)&&(S != NULL))
{
S = S->next;
P = S;
}
if(S == NULL)
temp->next = P;
else
{
temp->next = S;
P->next = temp;
}
}
return true;
}
template <typename Object>
bool SinglyLinkedList<Object>::empty()
{
if(this->head == NULL)
return true;
else
return false;
}
template <typename Object>
SinglyLinkedList<Object>::~SinglyLinkedList()
{
delete this->head;
}
#endif
DynamicArrayClass.h
#pragma once
#ifndef DynamicArrayClass_h
#define DynamicArrayClass_h
#include<iostream>
template <class T>
class DynamicArrayClass
{
private:
T *array;
int size, numItems;
public:
DynamicArrayClass(int newSize)
{
size = newSize;
numItems=0;
array = new T[size];
}
int GetSize(){ return size;}
int GetNumItems() const { return numItems; }
bool isEmpty() const { return numItems==0; }
bool isFull() const { return numItems==size; }
bool addItem (const T &object)
{
if(isFull())
{
return false;
}
else
{
array[numItems++] = object;
return true;
}
}
const T& getItem(int index) {return array[index];}
void makeEmpty()
{
numItems = 0;
}
~DynamicArrayClass()
{
if(array !NULL)
delete [] array;
}
};
#endif
main.cpp
#include "DynamicArrayClass.h"
#include "SinglyLinkedList.h"
#include "stopwatch.h"
#include<iostream>
int main()
{
int totalCapacity = 0;
int arrayAddSize = 0;
while(totalCapacity < 10000)
{
if(totalCapacity==0)
{
DynamicArrayClass<int> *array1 = new DynamicArrayClass<int>(25);
totalCapacity = 25;
SinglyLinkedList<DynamicArrayClass<int>> *list = new SinglyLinkedList<DynamicArrayClass<int>>();
for(int i = 0; i<25; i++)
{
array1->addItem(1);
}
**list->insert(*array1);**
}
else
{
arrayAddSize = (totalCapacity/2);
totalCapacity = totalCapacity + arrayAddSize;
DynamicArrayClass<int> *array = new DynamicArrayClass<int>(arrayAddSize);
SinglyLinkedList<DynamicArrayClass<int>> *list = new SinglyLinkedList<DynamicArrayClass<int>>();
for(int i=0; i <arrayAddSize; i++)
{
array->addItem(1);
}
}
}
return 0;
}
The problem is in this part of insert:
node<Object> *temp = new node<Object>;
where the node contains an Object. To construct that, the Object needs a default constructor.
Perhaps you can add a constructor to node that copies the value it has to store? That would make it, for example:
node<Object> *temp = new node<Object>(x, NULL);
node<Object> *temp = new node<Object>;
This line in SinglyLinkedList::insert causes the error I assume. The problem is, that your node struct looks like this:
template <typename Type>
struct node
{
Type value;
node *next;
};
That Type value; will be default constructed by the new node<Object> call. Provide an appropriate constructor for the node struct and you should be fine.