Everything was working before I introduced templates to my code
EDIT:
Here is the problem to which I was able to narrow it down, thanks to your tips:
In file included from main.cpp:4:
stack.cpp: In member function void Stack<TYPE>::push(Stack<TYPE>&, TYPE)':
stack.cpp:35: error:node' is not a type
I wonder if a similar problem could appear later in the pop function, but it seems like it does not.
I'm confused as to why it seems to insist that node is not a type.
EDIT#2:
this statement in the main.cpp file is now causing trouble. I have moved all the definitions out of stack.cpp to stack.h. After this Stack<int> list;my compiles says Segmentation fault (core dumped).
stack.h:
#include <iostream>
using namespace std;
template <typename TYPE>
struct node {
TYPE data;
node<Type> *next;
node(){
data = NULL;
next = NULL;
}
~node(){
if (data!=0)
delete next;
}
explicit node(int i){
data = i;
}
};
template <typename TYPE>
class Stack {
private:
node<TYPE> *top;
void init();
public:
Stack(); // default constructor
virtual ~Stack(); // destructor
bool empty();
void push(Stack&,TYPE);
TYPE pop(Stack&);
int peek();
void clear();
ostream& printf(ostream&, node<TYPE> *);
ostream& print(ostream&);
ostream& sequentialPrint(Stack&,ostream&);
ostream& reversePrint(Stack&,ostream&);
friend ostream& operator<<(ostream&, Stack&);
};
stack.cpp:
template <typename TYPE>
void Stack<TYPE>::push(Stack<TYPE> &s, TYPE i) {
node<TYPE> * n = new node(i);
n->next = top;
top = n;
}
template <typename TYPE>
TYPE Stack<TYPE>::pop(Stack<TYPE> &s){
if (empty()) {
cerr<<"Stack is empty \n";
}
TYPE temp = s.top->data;
top = top->next;
return temp;
}
friend ostream& operator<<(ostream&, Stack&); is not needed
you can't define template methods in cpp file. Every element of template which is template parameter depended must be defined in header file.
Related
I am trying to create a Doubly Linked List and respective node class and am having an issue trying to add the data types of head and tail to my IntDLList class. I'm not quite sure what I missed, but an error is occurring stating that both head and tail were not declared, and that my Node class does not take a type. Any help is appreciated!
Edit: This does not seem to be a duplicate question, I looked at the other answers and trying to resolve an invalid use of incomplete type did not solve the same issue as my name type error.
IntDLList
using namespace std;
template <class T>
class IntDLList {
public:
IntDLList() {
head=tail=0; // error: 'head' was not declared in this scope (& same for tail)
}
~IntDLList();
int isEmpty() {
return head==0; // error: 'head' was not declared in this scope
}
void addToDLLHead(const T&);
void addToDLLTail(const T&);
T deleteFromDLLHead();
T deleteFromDLLTail();
void deleteDLLNode(const T&);
bool isInList(const T&) const;
void showList();
private:
IntDLLNode<T> *head, *tail; //error: IntDLLNode does not name a type
};
IntDLLNode
using namespace std;
template<class T>
class IntDLLNode {
friend class IntDLList;
public:
IntDLLNode() {next = prev = 0;}
IntDLLNode(const T& el, IntDLLNode *n = 0, IntDLLNode *p = 0) {
info = el;
next = n;
prev = p;
}
protected:
T info;
IntDLLNode<T> *next,*prev;
private:
};
I would like to save my binary tree to txt file. Here's what I have
qt.h
#ifndef QT_H_INCLUDED
#define QT_H_INCLUDED
#include<iostream>
using namespace std;
template<typename T>
class Node{
T data;
Node<T> *left;
Node<T> *right;
public:
Node(T d) : data(d), left(nullptr), right(nullptr){}
void print(){
cout << data << endl;}
T getData()const {
return data;
}
void setData(const T &value){
data = value;
}
template<typename X> friend class Tree;
template<T> friend ostream& operator<<(ostream &os, Node &n);
};
template<typename T>
ostream& operator<<(ostream &os, Node<T> &n){
os << n->data;
return os;
}
#endif // QT_H_INCLUDED
then tree.h
#ifndef TREE_H_INCLUDED
#define TREE_H_INCLUDED
#include "qt.h"
#include <fstream>
#include <iostream>
namespace std;
template<typename T>
class Tree{
Node<T> *root;
void insertIntoTree(T &d, Node<T> *&r);
void printTree(Node<T> *r);
void deleteTree(Node<T> *&r);
Node<T>* findInTree(T &d, Node<T> *r, Node<T> *&parent);
void deleteLeaf(Node<T> *p, Node<T> *q);
void deleteInBranch(Node<T> *p, Node<T> *g);
void zapisDoSouboru(Node<T> *r);
public:
Tree() : root(nullptr){}
~Tree(){
clean();
}
bool find(T d){
Node<T> *dummy=nullptr;
return findInTree(d, root, dummy);
};
void clean(){
deleteTree(root);}
void insert(T d){
insertIntoTree(d, root);}
void print(){
printTree(root);
}
bool deleteNode(T d);
void zapis(){
zapisDoSouboru(root);
}
}
template<typename T>
void Tree<T>::zapisDoSouboru(Node<T> *r){
fstream f;
f.open("mytext.txt", ios_base::app);
if(r){
f << r;
}
f.close();
zapisDoSouboru(r->left);
zapisDoSouboru(r->right);
}
the idea was to overload operator<< for Node and then use recursion in zapisDoSouboru and save it Node by Node. Unfortunately it does not work.
Does anybody know, where the problem is?
Thank you for helping
EDIT
in
class Tree{
void zapis(ostream& f, Node<T> *r);
public:
void zapisDoSouboru(){
fstream f;
f.open("mytext.txt", ios_base::app);
zapis(f, root);
f.close();
}
}
template<typename T>
void Tree<T>::zapis(ostream& f,Node<T> *r){
if(r){
zapis(f, r->left);
f << r;
zapis(f, r->right);
}
}
I changed the whole recursion, but now it looks like it works, but it doesnt write anything in the file. Isnt the reference to f wrong? The file opens and close, zapis() goes through all nodes.
In the function zapisDoSouboru you need to check if the child nodes are nullptr otherwise it will segfault whenever it reaches the leaf nodes.
Here is the modified version:
template
void Tree<T>::zapisDoSouboru(Node<T> *r){
fstream f;
f.open("mytext.txt", ios_base::app);
if(r){
f << r;
}
f.close();
if(nullptr != r->left) {
zapisDoSouboru(r->left);
}
if(nullptr != r->right) {
zapisDoSouboru(r->right);
}
}
Also the operator you have defined for node it is not being picked up by the compiler.
This is the piece of code of your operator:
template<typename T>
ostream& operator<<(ostream &os, Node<T> &n){
os << n->data;
return os;
}
The variable n it is passed by reference and you are accessing it with -> which expects a pointer. The reason why the code compiles is because when you call f << r you actually call the operator with a Node<T>* so the compiler does not use the template function which expects a Node<T>&. Which means the template function is never instantiated.
I think there is not much need for having the operator overload in this case. You can just simply call r->getData()
Also general things i noticed while looking at the code:
I would try to use unique_ptr
I would try to avoid using friend classes
I would refactor the code to not open and close the file at every recursive call
Let me know if you need any clarifications
I have a header file for a program that utilizes singly linked list. The data that is originally stored in the nodes were integers, however, in an attempt to use the template class, I tried to convert the Node class and AnyList class to template classes; however, when I compile, an error message that says "'Node": use of class template requires template argument list" appears. I've seen examples of template classes, but there's a bit of confusion since I'm trying to make two template classes in one header file.
#ifndef ANYLIST_H
#define ANYLIST_H
#include<iostream>
#include <string>
using namespace std;
template <typename T>
class Node
{
public:
Node() : data(0), next(NULL) {}
Node(T& theData, Node *newNext) : data(theData), next(newNext){}
Node* getNext() const { return next; }
T getData( ) const { return data; }
void setData(T& theData) { data = theData; }
void setNext(Node *newNext) { next = newNext; }
~Node(){}
private:
T data;
Node *next; //pointer that points to next node
};
template <typename T>
class AnyList
{
friend ostream& operator<<(ostream& out, const AnyList<T>& theList);
public:
AnyList();
void insert(const T& elem);
int getNumOfElem() const;
void destroyList();
~AnyList();
private:
Node *first;
int count;
};
#endif
Simply put, Node<> and List<> are different templates. So you need to forward the template parameter from List to Node.
Replace
Node *first;
By
Node<T> *first;
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why do I get “unresolved external symbol” errors when using templates?
LinkedList.h
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include<iostream>
template<class T> class LinkedList;
//------Node------
template<class T>
class Node {
private:
T data;
Node<T>* next;
public:
Node(){data = 0; next=0;}
Node(T data);
friend class LinkedList<T>;
};
//------Iterator------
template<class T>
class Iterator {
private:
Node<T> *current;
public:
friend class LinkedList<T>;
Iterator operator*();
};
//------LinkedList------
template<class T>
class LinkedList {
private:
Node<T> *head;
public:
LinkedList(){head=0;}
void push_front(T data);
void push_back(const T& data);
Iterator<T> begin();
Iterator<T> end();
};
#endif /* LINKEDLIST_H */
LinkedList.cpp
#include "LinkedList.h"
#include<iostream>
using namespace std;
//------Node------
template<class T>
Node<T>::Node(T data){
this.data = data;
}
//------LinkedList------
template<class T>
void LinkedList<T>::push_front(T data){
Node<T> *newNode = new Node<T>(data);
if(head==0){
head = newNode;
}
else{
newNode->next = head;
head = newNode;
}
}
template<class T>
void LinkedList<T>::push_back(const T& data){
Node<T> *newNode = new Node<T>(data);
if(head==0)
head = newNode;
else{
head->next = newNode;
}
}
//------Iterator------
template<class T>
Iterator<T> LinkedList<T>::begin(){
return head;
}
template<class T>
Iterator<T> Iterator<T>::operator*(){
}
main.cpp
#include "LinkedList.h"
using namespace std;
int main() {
LinkedList<int> list;
int input = 10;
list.push_front(input);
}
Hi, I am fairly new at c++ and I am trying to write my own LinkedList using templates.
I followed my book pretty closely and this is what I got. I am getting this error though.
/main.cpp:18: undefined reference to `LinkedList::push_front(int)'
I have no clue why, any ideas?
You are using templates in your Program. When you use templates, you have to write the code and the headers in the same file because the compiler needs to generate the code where it is used in the program.
You can do either this or include #inlcude "LinkedList.cpp" in main.cpp
This question might help you.
Why can templates only be implemented in the header file?
Okay, guys i have been trying to define a Stack , each node also being of template type but i get dozen different types of errors when the prog tries to compile. i will paste the program which uses a char-type stack and tries to pop letter 'e'
#ifndef STACK_LIST_H
#define STACK_LIST_H
#include "List.h"
using namespace std;
template <class T>
class Stack {
public:
T pop();
void push(T x);
T isEmpty();
T top();
private:
int size;
Node<T> * headNode;
Node<T> * currentNode;
};
#endif
Now the function definitions:
#include <iostream>
#include "Stack_list.h"
using namespace std;
template <class T>
T Stack<T>::pop(){
T x = headNode->get();
Node<T>* p = new Node<T>::Node();
p = headNode;
headNode = headNode->getNext();
delete p;
return x; }
template <class T>
void Stack<T>::push(T x){
Node<T>* newNode = new Node<T>::Node();
newNode->setNext(headNode);
newNode->set(x);
headNode=newNode;
}
template <class T>
int Stack<T>::isEmpty(){
return (headNode ==NULL);}
template <class T>
T Stack<T>::top(){
return headNode->get();
}
now the template class node:
#ifndef LIST_H
#define LIST_H
using namespace std;
/* The Node class */
template <class T>
class Node
{
public:
Node(T here){object=here;};
T get() { return object; };
void set(T object) { this->object = object; };
Node<T>* getNext() { return nextNode; };
void setNext(Node<T>* nextNode) { this->nextNode = nextNode; };
Node<T>* getPrev(){ return prevNode;};
void setPrev(Node<T>* prevNode){this->prevNode=prevNode;};
private:
T object;
Node<T>* nextNode;
Node<T>* prevNode;
};
#endif
and finally the program that evokes the classes:
#include <iostream>
#include "Stack_list.cpp"
using namespace std;
int main(){
Stack <char>s;
s.push("e");
cout<<s.pop();
}
As you can see, this is my first try at template classes. In definitions of Stack::pop() and push(T) it says, "expected type-specifier before ‘Node’"
Node<T>* newNode = new Node() is inconsistent. Is Node a class or a class template? The first time that you mention it, you treat it as a template and instantiate it with T, but the second time you treat it as a class. It can't be both.
Your method definition signatures are:
T Stack<T>::pop()
but they should be
template<typename T>
T Stack<T>::pop()
Also, since Stack uses Node, you have to include Node.h in Stack.h.
Furthermore - in Stack you declared T isEmpty(); but implemented it as int Stack<T>::isEmpty(). Stick to one return type (probably bool is more appropriate here, but int is also OK).
Lastly:
Stack <char>s;
s.push("e");
The template specialization is char, but "e" is a const char*. The correct way would be:
Stack <char>s;
s.push('e'); // <- note the single quotes