I'm trying to make a custom set of header files to use a generic List and use operator<< to make it print into a ostream object
There are a couple of errors which I cannot resolve.
I'm trying to make a generic List class using a generic Node class. The generic List should be printed using the operator<< . However I'm getting a lot of errors.
#include <iostream>
using std::cout;
using std::ostream;
class List;
template<class T>
class Node
{
friend class List<Node>;
private:
T data_;
Node *next_;
public:
Node(T data);
T get_data();
};
template<typename T>
Node<T>::Node(T data)
{
data_ = data;
next_ = 0;
}
template<typename T>
T Node<T>::get_data()
{
return data_;
}
template<typename T>
class Node;
template<typename T>
class List
{
template<typename T>
friend ostream& operator<<(ostream& o , const List<T> head);
private:
Node<T> *start_;
bool is_empty();
public:
List();
~List();
void insert(T data);
void remove();
};
template<typename T>
bool List<T>::is_empty()
{
if(start_ == 0)
return true;
return false;
}
template<typename T>
List<T>::List()
{
start_ = 0;
}
template<typename T>
List<T>::~List()
{
if( !is_empty())
{
Node<T> *current = start_;
Node<T> *temp;
while(current != 0)
{
temp = current;
current = current->next_;
delete temp;
}
}
}
template<typename T>
void List<T>::insert(T data)
{
if(is_empty())
{
Node<T> *temp = new Node<T>(data);
start_ = temp;
}
else
{
Node<T> *temp = start_;
while(temp->next_ != 0)
{
temp = temp->next_;
}
temp->next_ = new Node<T>(data);
}
}
template<typename T>
void List<T>::remove()
{
if(start_->next_ == 0)
{
Node<T> *temp = start_->next_;
start_->next_ = 0;
delete temp;
}
else if(!is_empty())
{
Node<T> *stay = start_;
Node<T> *remove = stay->next_;
while(remove->next_ != 0)
{
stay = remove;
remove = remove->next_;
}
stay->next_ = 0;
delete remove;
}
}
// Experimental Stuff out here
template<typename T>
ostream& operator<<(ostream& o , const List<T> *head)
{
Node<T> *temp = head->start_;
if(!is_empty<T>())
{
while(temp->next_ != 0)
{
o << temp.get_data() << "\t";
o << "\n";
temp = temp->next_;
}
}
return o;
}
// End of Experimental Stuff
Assuming clients of your class instantiate it like this:
List<int> my_list;
You need to define your operator << overload like this:
template <typename T>
std::ostream& operator << (std::ostream& os, const List<T>& list)
{
// I'm gonna assume you have C++11
auto node = list.start_;
while (node != nullptr)
{
os << '\t' << node->get_data() << '\n';
node = node->next_;
}
return os;
}
Additionally, there are loads of errors in your code regarding templates, so please fix them first.
Related
I am trying to make a Generic Linked list in C++ using templates. But i am getting this error 'GenericNode::{ctor}': constructors not allowed a return type through which i can't possibly know what am i doing wrong?
PS. i have also gone through other posts here on Stack Overflow which says that the error is due to the missing semi-colon after the class definition but i think i don't have a 'missing semi-colon' case. Any help?
Code :
GenericLinkedList.h :
#pragma once
template <typename Datatype>
class GenericNode {
Datatype T;
GenericNode *next;
public:
GenericNode() {}
GenericNode(Datatype T);
};
template<typename Datatype>
void GenericNode<Datatype>::GenericNode(Datatype data) {
T = data;
}
template <typename Datatype>
class GenericLinkedList {
GenericNode *Data;
public:
GenericLinkedList() {
Data = NULL;
}
int isEmpty();
void addDataAtFront(Datatype data);
void addDataAtEnd(Datatype data);
void print();
};
template <typename Datatype>
int GenericLinkedList<Datatype>::isEmpty() {
return Data == NULL;
}
template <typename Datatype>
void GenericLinkedList<Datatype>::addDataAtFront(Datatype data) {
GenericNode *newNode, *tmpNode;
newNode = new Node;
newNode->T = data;
newNode->next = NULL;
if (Data == NULL) {
Data = newNode;
}
else {
tmpNode = Data;
Data = newNode;
Data->next = tmpNode;
}
}
template <typename Datatype>
void GenericLinkedList<Datatype>::addDataAtEnd(Datatype data) {
GenericNode *newNode, *tmpNode;
newNode = new Node;
newNode->T = data;
newNode->next = NULL;
if (Data == NULL) {
Data = newNode;
}
else {
tmpNode = Data;
while (tmpNode->next != NULL) {
tmpNode = tmpNode->next;
}
tmpNode->next = newNode;
}
}
template <typename Datatype>
void GenericLinkedList<Datatype>::print() {
GenericNode tmpNode;
tmpNode = Data;
for (tmpNode;tmpNode != NULL;tmpNode = tmpNode->next) {
cout << tmpNode->T << " ";
}
}
.cpp :
#include <iostream>
#include <conio.h>
#include "GenericLinkedList.h"
using namespace std;
int main() {
GenericLinkedList<int> T;
T.addDataAtFront(5);
T.addDataAtEnd(6);
T.addDataAtFront(4);
T.print();
_getch();
}
template<typename Datatype>
void GenericNode<Datatype>::GenericNode(Datatype data) {
T = data;
}
You write the return type void. It's a constructor.
void GenericNode::GenericNode(Datatype data)
remove void its a constructor. Constructors don't return and dont have a return type.
hello I have a problem with a template. I want a pointer stack using templates but I get the error "does not name a type". I have two classes, one that manages a stack of nodes and the other one is a node class. The problem is in the node class and I don't know how to resolve it. Could somebody explain to me how I should create a node object using a template decleared in another class. The code is below.
template<class T> class PointerStack
{
public:
PointerStack();
bool isEmpty();
bool push(T dataIn);
bool pop();
bool top(T &topItem);
void clear();
void print();
private:
int counter;
Node<T>* start;
};
template<class T>
class Node
{
public:
Node(T dataIn);
Node(T dataIn, Node vorigeIn);
T getData();
Node* getPrevious();
private:
T data;
Node* previous;
Node* next;
};
template<class T>
PointerStack<T>::PointerStack()
{
counter == 0;
}
template<class T>
bool PointerStack<T>::isEmpty()
{
if(counter == 0)
{
return true;
}
else
{
return false;
}
}
template<class T>
bool PointerStack<T>::push(T data)
{
if(isEmpty())
{
start = new Node<T>(data);
counter++;
return true;
}
else
{
Node<T> dummy = start;
start = new Node<T>(data, dummy);
counter++;
return true;
}
}
template<class T>
bool PointerStack<T>::pop()
{
if(isEmpty())
{
return false;
}
else
{
Node<T> dummy = start;
start = start->vorige;
counter--;
delete dummy;
return true;
}
}
template<class T>
bool PointerStack<T>::top(T &topItem)
{
if(isEmpty())
{
return false;
}
else
{
topItem = start.getData();
return true;
}
}
template<class T>
void PointerStack<T>::clear()
{
while(isEmpty())
{
pop();
}
}
template<class T>
void PointerStack<T>::print()
{
Node<T> dummy = start;
if(!isEmpty())
{
for(int i = 0; i < counter; i++)
{
std::cout<<dummy->getData();
dummy->v;
}
}
}
template<class T>
Node<T>::Node(T dataIn)
{
data = dataIn;
previous = NULL;
next = NULL;
}
template<class T>
Node<T>::Node(T dataIn, Node previousIn)
{
data = dataIn;
previous = previousIn;
next = NULL;
previousIn->volgende = this;
}
template<class T>
T Node<T>::getData()
{
return data;
}
template<class T>
Node<T>* Node<T>::getPrevious()
{
return previous;
}
and this is the error message:
You PointerStack class doesn't know of the Node class. You need to forward declare your Node class before declaring PointerStack:
template<class T>
class Node;
/* Your code goes here */
I cannot use std::list. The goal is to create a user defined MyList that can handle any data type. My problem is with my nested iterator class and possibly my function for overloading operator<<. I have been at this for awhile and I am stuck. Since the deadline is pretty close, I figure that I should risk my neck and ask the question here. It will be great if someone can assist me with this.
I realized that there are memory leaks in my code, but thats not my main concern at the moment.
I also realized that having so many friend function is not a good programming practice, I am planning to use getData() and setData() function to get/set the private variable within node later.
So please overlook the above 2 problems...
Error message:
"MyList.h", line 67: Error: iterator is not defined.
I'll include the whole header file just so that in case people need to see it. I'll include a comment at line 67 where the error is. Then I'll also include a section of my main function that uses the iterator to show how I am trying to set the iterator and iterate through the list.
#include<iostream>
#include<cstddef>
template<class T>
class Node
{
friend void MyList<T>::push_front(T aData);
friend void MyList<T>::push_back(T aData);
friend void MyList<T>::pop_front();
friend T MyList<T>::front();
friend void MyList<T>::print();
friend MyList<T>::~MyList();
friend std::ostream& operator<<(std::ostream&, Node<T>&);
private:
T data;
Node *next;
Node *prev;
public:
Node(T aData);
};
template<class T>
class MyList
{
Node<T> *head;
Node<T> *tail;
public:
MyList();
~MyList();
void push_front(T aData);
void push_back(T aData);
T front();
void pop_front();
void operator=(MyList<T>& another_List);
void print(); //Test function. Delete later.
class iterator
{
private:
MyList& object;
Node<T> *current;
public:
iterator(MyList<T>&, Node<T>*); // iterator a(*this, head);
// MyList<int>::iterator a = list.Begin();
iterator operator++(); // a++
iterator operator++(int); // ++a
iterator operator--();
bool operator!=(iterator);
friend std::ostream& operator<<(std::ostream&, iterator&);
};
iterator Begin();
iterator End();
};
template<class T>
std::ostream& operator<<(std::ostream& out, Node<T>& n)
{
out << *n.current << ' ';
return out;
}
template<class T>
std::ostream& operator<<(std::ostream& out, iterator& i) //ERROR
{
out << i->current << ' ';
return out;
}
template<class T>
Node<T>::Node(T aData)
{
data = aData;
}
template<class T>
MyList<T>::MyList()
{
head = NULL;
}
template<class T>
MyList<T>::~MyList()
{
Node<T> *temp;
while(head != NULL)
{
temp = head;
head = head->next;
delete temp;
}
head = NULL;
}
template<class T>
void MyList<T>::push_front(T aData)
{
if(head == NULL)
{
head = new Node<T>(aData);
head->next = tail;
head->prev = NULL;
tail->prev = head;
}
else
{
head->prev = new Node<T>(aData);
head->prev->prev = NULL;
head->prev->next = head;
head = head->prev;
}
}
template<class T>
void MyList<T>::push_back(T aData)
{
if(head == NULL)
{
head = new Node<T>(aData);
head->prev = NULL;
head->next = tail;
tail->prev = head;
}
else
{
tail->prev->next = new Node<T>(aData);
tail->prev->next->prev = tail->prev;
tail->prev->next->next = tail;
tail->prev = tail->prev->next;
}
}
template<class T>
T MyList<T>::front()
{
return head->data;
}
template<class T>
void MyList<T>::pop_front()
{
if(head == NULL)
std::cout << "The List is empty!" << endl;
else
{
head = head->next;
head->prev = NULL;
}
}
template<class T>
void MyList<T>::print()
{
while(head != NULL)
{
std::cout << "Test print function" << std::endl;
std::cout << '[' << head->data << ']' << std::endl;
head = head->next;
}
std::cout << "End of test print function" << std::endl;
}
template<class T>
MyList<T>::iterator::iterator(MyList<T>& list, Node<T>* p)
{
object = list;
current = p;
}
template<class T>
typename MyList<T>::iterator MyList<T>::iterator::operator++()
{
if(current == object.tail)
{
}
else
current = current->next;
return this;
}
template<class T>
typename MyList<T>::iterator MyList<T>::iterator::operator++(int)
{
if(current == object.tail)
{
}
else
current = current->next;
return this->prev;
}
template<class T>
typename MyList<T>::iterator MyList<T>::iterator::operator--()
{
if(current == object.head)
{
}
else
current = current->prev;
return this;
}
template<class T>
bool MyList<T>::iterator::operator!=(iterator b)
{
return (this.current == b.current);
}
template<class T>
typename MyList<T>::iterator MyList<T>::Begin()
{
return iterator(object, head);
}
template<class T>
typename MyList<T>::iterator MyList<T>::End()
{
return iterator(object, tail);
}
main.cpp
MyList<int>::iterator i = aList.Begin();
while(i != aList.End())
{
cout << i;
i++;
}
Since the definition of your iterator class is nested inside the definition of your MyList class template, for all code outside out MyList, its name is MyList<whatever>::iterator.
Perhaps you intended something slightly different in the code that contains the error though. While you've defined it as a template:
template<class T>
std::ostream& operator<<(std::ostream& out, iterator& i) //ERROR
{
out << i->current << ' ';
return out;
}
You don't seem to be using its template parameter (T) at all. Perhaps you really intended something more like:
template<class iterator>
std::ostream& operator<<(std::ostream& out, iterator& i) //ERROR
{
out << i->current << ' ';
return out;
}
In this case you don't need to supply a qualifier, since the iterator here is just referring to the template parameter. When you use this, the compiler will normally deduce the type of the iterator you actually pass.
Note that it's unnecessary but somewhat traditional to specify the iterator category in a template parameter like this, so you'd typically use something like OutIterator instead of just iterator for the template parameter.
This isn't really very generic though -- in particular, the ->current means it'll only really work for your specific iterator type. More typical code would overload operator * for the iterator type, so client code will just dereference the iterator. Also note that iterators are normally assumed to be "lightweight" enough that they're normally passed by value, not by reference.
class iterator {
// ...
T operator*() { return *current; }
};
// ...
template<class OutIt>
std::ostream& operator<<(std::ostream& out, OutIt i)
{
out << *i << ' ';
return out;
}
Here's a template (queue) I'm trying to write:
#include <iostream>
using namespace std;
template <typename T>
class Queue
{
friend ostream& operator<< (ostream &, const Queue<T> & );
private:
template<class> class Node;
Node<T> *front;
Node<T> *back;
public:
Queue() : front(0), back(0) {}
~Queue();
bool Empty()
{
return front == 0;
}
void Push(const T& NewEl)
{
Node<T&> *El = new Node<T> (NewEl);
if (Empty())
front=back=El;
else
{
back-> next = El;
back = El;
}
}
void Pop()
{
if (Empty())
cout << "Очередь пуста." << endl;
else
{
Node<T> *El = front;
front = front -> next;
delete El;
}
}
void Clear()
{
while (! Empty())
Pop();
}
};
template <typename T>
class Node
{
friend class Queue<T>;
public:
Node() {next = 0;}
Node(T nd) {nd=node; next=0;}
T& getsetnode(){return node;}
Node<T>*& getsetnext(){return next;}
private:
T front;
T back;
T node;
Node<T> *next;
};
template <class T> ostream& operator<< (ostream &, const Queue<T> & );
int main()
{
Queue<int> *queueInt = new Queue<int>;
for (int i = 0; i<10; i++)
{
queueInt->Push(i);
cout << "Pushed " << i << endl;
}
if (!queueInt->Empty())
{
queueInt->Pop();
cout << "Pop" << endl;
}
queueInt->Front();
queueInt->Back();
queueInt->Clear();
cout << "Clear" << endl;
return 0;
}
At these lines:
Node<T&> *El = new Node<T> (NewEl);
front = front -> next;
delete El;
I get Implicit instantiation of undefined template 'Queue<int>::Node<int>'. What am I doing wrong? After reading this post I tried changing int to const int to see if that was the problem, but apparently it isn't, because I get the same error.
I'm using XCode with LLVM compiler 4.2. When I switch to GCC I get more errors:
template<class> class Node; gets Declaration of 'struct Queue<int>::Node<int>',
Node<T&> *El = new Node<T> (NewEl); gets Invalid use of incomplete type,
and anything dealing with assignment of anything to El can't convert <int&>* to <int>* (but deleting reference doesn't change anything for LLVM).
template <typename T>
class Queue
{
private:
template<class> class Node;
/* ... */
This is a forward declaration of Queue::Node. The latter defined class Node is in the global namespace, so they aren't the same and any usage of Queue::Node will result in an incomplete-type error. Since you don't provide an interface to the interior nodes anyway just scrap the global definition of Node and stick it into Queue:
template <typename T>
class Queue
{
private:
class Node
{
public:
Node() {next = 0;}
/* ... */
};
/* ... */
};
I know there are a lot of similar questions out there - believe me, I've read them - but I can't get this to work. Which is peculiar, because I resolved a similar struggle with a related program just the other day. I realize that the answer to my question quite likely is out there somewhere, but I've spent a good hour or two looking, without much success.
I am trying to build a linked list. The program consists of four files - header files for the linked list and the node, as well as an interace to the list, and the .cpp file containing the main method.
ListTester.cpp
#include "StdAfx.h"
#include "LinkedList.h"
#include <iostream>
#include <string>
using namespace std;
template <typename T>
void main() {
LinkedList<int> a;
a.addFirst(22);
a.addFirst(24);
a.addFirst(28);
LinkedList<int> b;
b = a;
b = b + a;
b += a;
cout<<b;
}
LinkedList.h
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include "Node.h"
#include "List.h"
#include <ostream>
template <typename T>
class LinkedList : public List {
private:
int n;
Node<T> *first;
Node<T> *last;
public:
LinkedList();
LinkedList(const LinkedList & ll);
~LinkedList();
int size();
void clear();
void addFirst(T data);
void addLast(T data);
T removeFirst();
T removeLast();
T getFirst();
T getLast();
Node<T>* getFirstNode() const;
void addAt(int pos, T data);
T removeAt(int pos);
T getAt(int pos);
LinkedList& operator=(const LinkedList<T> &right);
T operator[](int i);
LinkedList& operator+(const LinkedList<T> &right);
LinkedList& operator+=(const LinkedList<T> &right);
friend std::ostream& operator<<(std::ostream &os, const LinkedList<T> & ll);
};
template <typename T>
LinkedList<T>::LinkedList() {
this->n = 0;
this->first = 0;
this->last = 0;
}
template <typename T>
LinkedList<T>::LinkedList(const LinkedList & ll) {
this-> n = 0;
this-> first = 0;
this-> last = 0;
Node *temp = ll.first;
while(temp) {
addLast(temp->getData());
temp = temp->getNext();
}
}
template <typename T>
void LinkedList<T>::addFirst(T data) {
Node *p = new Node(data, first);
first = p;
if(!n)
last = p;
n++;
}
template <typename T>
void LinkedList<T>::addLast(T data) {
Node *p = new Node(data, 0);
if(!n)
first = last = p;
else {
last->next = p;
last = p;
}
n++;
}
template <typename T>
T LinkedList<T>::removeFirst() {
T a = 0;
if(!n)
throw "Can't retrieve element from empty list!";
a = first->getData();
Node *p = first->next;
delete first;
first = p;
n--;
return a;
}
template <typename T>
T LinkedList<T>::removeLast() {
T a = 0;
if(!n)
throw "Can't retrieve element from empty list!";
if(n == 1) {
a = last->getData();
delete first;
first = last = 0;
}
else {
a = last->getData();
Node *p = first;
while(p->next->next != 0)
p = p->next;
delete p->next;
p->next = 0;
last = p;
}
n--;
return a;
}
template <typename T>
T LinkedList<T>::getFirst() {
if(n < 1)
throw "Can't retrieve element from empty list!";
return first->getData();
}
template <typename T>
T LinkedList<T>::getLast() {
if(n < 1)
throw "Can't retrieve element from empty list!";
return last->getData();
}
template <typename T>
Node<T>* LinkedList<T>::getFirstNode() const {
return first;
}
template <typename T>
int LinkedList<T>::size() {
return n;
}
template <typename T>
T LinkedList<T>::getAt(int pos) {
if(pos >= n)
throw "Element index out of bounds!";
Node *temp = first;
while(pos > 0) {
temp = temp->next;
pos--;
}
return temp->getData();
}
template <typename T>
void LinkedList<T>::clear() {
Node *current = first;
while(current) {
Node *next = current->next;
delete current;
if(next)
current = next;
else
current = 0;
}
}
template <typename T>
void LinkedList<T>::addAt(int pos, T data) {
if(pos >= n)
throw "Element index out of bounds!";
if(pos == 0)
addFirst(data);
else {
Node *temp = first;
while(pos > 1) {
temp = temp->next;
pos--;
}
Node *p = new Node(data, temp->next);
temp-> next = p;
n++;
}
}
template <typename T>
T LinkedList<T>::removeAt(int pos) {
if(pos >= n)
throw "Element index out of bounds!";
if(pos == 0)
return removeFirst();
if(pos == n - 1)
return removeLast();
else {
Node *p = first;
while(pos > 1) {
p = p->next;
pos--;
}
T a = p->next->getData();
Node *temp = p->next;
p->next = p->next->next;
delete temp;
n--;
return a;
}
}
template <typename T>
LinkedList<T>::~LinkedList() {
clear();
}
template <typename T>
LinkedList<T>& LinkedList<T>::operator=(const LinkedList<T> &right) {
if(this != &right) {
n = 0;
first = 0;
last = 0;
Node *temp = right.first;
while(temp) {
addLast(temp->getData());
temp = temp->getNext();
}
}
return *this;
}
template <typename T>
T LinkedList<T>::operator[](int i) {
return getAt(i);
}
template <typename T>
LinkedList<T>& LinkedList<T>::operator+(const LinkedList<T> &right) {
Node *temp = right.first;
while(temp) {
addLast(temp->getData());
temp = temp->getNext();
}
return *this;
}
template <typename T>
LinkedList<T>& LinkedList<T>::operator+=(const LinkedList<T> &right) {
Node *temp = right.first;
while(temp) {
addLast(temp->getData());
temp = temp->getNext();
}
return *this;
}
template <typename T>
std::ostream& operator<<(std::ostream &os, const LinkedList<T> &ll) {
Node *temp = ll.getFirstNode();
while(temp) {
os<<temp->getData()<<std::endl;
temp = temp->getNext();
}
return os;
}
#endif
Node.h
#ifndef NODE_H
#define NODE_H
template <typename T>
class Node {
private:
T data;
public:
Node<T>* next;
T getData();
Node<T>* getNext();
Node(T data, Node<T>* next);
Node(const Node & n);
};
template <typename T>
T Node<T>::getData() {
return data;
}
template <typename T>
Node<T>* Node<T>::getNext() {
return next;
}
template <typename T>
Node<T>::Node(T data, Node<T>* next) {
this->data = data;
this->next = next;
}
template <typename T>
Node<T>::Node(const Node & n) {
data = n.data;
next = n.next;
}
#endif
List.h
#ifndef LIST_H
#define LIST_H
class List
{
public:
virtual void addFirst(int data) = 0;
virtual void addAt(int pos, int data) = 0;
virtual void addLast(int data) = 0;
virtual int getFirst()= 0;
virtual int getAt(int pos) = 0;
virtual int getLast()= 0;
virtual int removeFirst()= 0;
virtual int removeAt(int pos) = 0;
virtual int removeLast()= 0;
virtual int size() = 0;
virtual void clear() = 0;
virtual ~List() {};
};
#endif
For this, I get LNK2019 and LNK1120 linking errors. I know I used to get this when implementing a Queue in separated .h and .cpp files. But worked around it by doing everything in the header. I also know that this can happen when not implementing a named method, but I can't find any of those here. So what's causing this? I wish the compiler / IDE could point me to the possible cause of the error. But then again, if it was an easy task to find the faulty line, I assume it would already do this. VS 2012 btw.
You made main a function template. Not only does this not make sense (there is no mention of the template parameter inside), it's also never instantiated (and even if it was, it probably wouldn't resolve to the correct main that a program needs as a start point).
Furthermore, it should be int main rather than void main.
// template <typename T>
void main() {
LinkedList<int> a;
a.addFirst(22);
a.addFirst(24);
a.addFirst(28);
LinkedList<int> b;
b = a;
b = b + a;
b += a;
cout<<b;
}
You need a main function, not a main function template. That's probably the source of your linker error: no function called "main".
The reason this won't work is primarily because class templates and function templates are never expanded to real code unless they're used. Since main is the entrypoint to your program, you never call main from anywhere and thus no code for main is ever generated.
Furthermore due to the name mangling that C++ compilers do to functions (to handle overloading, templates, namespaces etc) the symbol that will be generated in the resulting assembly for this main template probably won't be the right one. If it's looking for a symbol 'main' and it sees
$__T_float_main_blah_blah_blah
then you won't link anyways. Long story short: main is a function, not a function template.