I'm trying to implement stack data structure using singly linked list.
This is the header file that has template class of Node and List
#pragma once
template <typename E>
class SNode {
E elem;
SNode<E>* next;
public:
friend class SLinkedList<E>;
};
template <typename E>
class SLinkedList {
private:
SNode<E>* head;
public:
SLinkedList();
~SLinkedList();
bool empty() const ();
const E& front() const;
void addFront(const E& e);
void removeFront();
};
template <typename E>
SLinkedList<E>::SLinkedList() : head(NULL) {}
template <typename E>
SLinkedList<E>::~SLinkedList() {
while(!empty()) removeFront();
}
template <typename E>
bool SLinkedList<E>::empty() const {
return head==NULL;
}
template <typename E>
const E& SLinkedList<E>::front() const {
return head->elem;
}
template <typename E>
void SLinkedList<E>::addFront(const E& e) {
SNode<E>* tmp = new SNode<E>;
tmp->elem = e;
tmp->next=head;
head=tmp;
}
template <typename E>
void SLinkedList<E>::removeFront() {
SNode<E>* old = head;
head=head->next;
delete old;
}
This is a simple main code
#include <iostream>
#include "SNode.h"
using namespace std;
int main() {
SNode<int> A(1);
SNode<int> B(2);
SLinkedList<int> L();
L.push(A);
L.push(B);
return 0;
}
When I compile this code the compiler says
SLinkedList is not a class template
I have no idea why it says that since I did put
template
You need to forward declare the SLinkedList templated class. like this:-
template <typename E>
class SLinkedList;
template <typename E>
class SNode {
E elem;
SNode<E>* next;
public:
friend class SLinkedList<E>;
};
...
There are other errors in you code. I hope you are able to resolve them by youself.
You have vexing parse with
SLinkedList<int> L();
Which declares a.. function L, taking no parameters, and returning SLinkedList<int>.
Use
SLinkedList<int> L;
or
SLinkedList<int> L{};
Related
This is a General Trees program, where I am trying to find the depth of the tree (depth of 2) and calculate the size of the directory. The two errors are declaration errors (towards the bottom of Tree.cpp) and can't seem to declare the function properly.
Tree.cpp
#include "Tree.h"
#include <iostream>
using namespace std;
template <typename E>
bool Tree<E>::Position::isRoot() const
{
if (u->parent == NULL)
return true;
else
return false;
}
template <typename E>
bool Tree<E>::Position::isExternal() const
{
return (u->child.empty());
}
template <typename E>
bool Tree<E>::Position::operator==(Tree<E>::Position p)
{
if (u == p.u)
return true;
else
return false;
}
template <typename E>
Tree<E>::Position::Position(TreeNode *v)
{
u = v;
}
template <typename E>
typename Tree<E>::Position Tree<E>::Position::parent()
{
return Tree<E>::Position(u->parent);
}
template <typename E>
typename Tree<E>::PositionList Tree<E>::Position::children()
{
return (u->child);
}
template <typename E>
E Tree<E>::Position::operator*()
{
return u->e;
}
template <typename E>
typename Tree<E>::Position Tree<E>::root()
{
return typename Tree<E>::Position(r);
}
template <typename E>
int Tree<E>::size() const
{
return this->n;
}
template <typename E>
bool Tree<E>::empty() const
{
return size() == 0;
}
template <typename E>
void Tree<E>::insert(E e, Tree<E>::Position p)
{
TreeNode *v = new TreeNode() ;
v->e = e;
if (empty())
v->parent = NULL;
else
v->parent = p.u;
if (!empty() )
{
p.u->child.insertBack(v);
}
else
{
v->parent = NULL;
r = v;
}
++n;
}
template <typename E>
NodeList<typename Tree<E>::Position> Tree<E>::Positions()
{
typename Tree<E>::PositionList list;
preorder(r, list);
return list;
}
template <typename E>
void Tree<E>::preorder(Tree<E>::Position p, Tree<E>::PositionList &pl)
{
pl.insertBack(p);
if (p.u->child.empty()==false)
for(typename Tree<E>::PositionList::Iterator ii = p.u->child.begin(); ii!= p.u->child.end(); ++ii)
preorder(*ii, pl);
}
template <typename E>
int Tree<E>::depth(Tree<E>::TreeNode& u, Tree<E>::Position& p) //ERROR: Out-of-line definition of 'depth' does not match any declaration in 'Tree<E>'
{
if (p.isRoot())
return 0;
else
return 1+depth(u, p.parent());
}
template <typename E>
int Tree<E>::directorySize(Tree<E>::TreeNode& u, Tree<E>::Position& p) //Out-of-line definition of 'directorySize' does not match any declaration in 'Tree<E>'
{
int s = size(p);
if (!p.isExternal())
{
PositionList ch = p.children();
for (typename Tree<E>::PositionList::Iterator q = ch.begin(); q != ch.end(); q++)
s += depth(u, *q);
cout << name(p) << ": " << s << endl;
}
return s;
}
Tree.h
#ifndef TREE_H
#define TREE_H
#include <cstdlib>
#include "NodeList.cpp"
template <typename E>
class Tree {
public:
class TreeNode;
public:
class Position // a node position
{
public:
E operator*(); // get element
Position parent();
NodeList<Position> children();
bool isRoot() const; // root node?
bool isExternal() const; // external node?
bool operator==(Position p);
int depth(const Tree& u, const Position& p); //DECLARED(ERROR) - DEPTH OF TWO FUNCTION
Position(typename Tree<E>::TreeNode *v);
Position(){}
typename Tree<E>::TreeNode *u;
friend class NodeList<Position>;
};
typedef NodeList<typename Tree<E>::Position> PositionList;
public:
class TreeNode
{
E e;
TreeNode *parent;
typename Tree<E>::PositionList child;
friend class Tree;
friend class Tree<E>::Position;
public:
TreeNode(){
parent = NULL;
}
TreeNode(E,Tree<E>::Position*, Tree<E>::PositionList*);
TreeNode& operator=(const TreeNode &t)
{
parent = t.parent;
child = t.child;
e = t.e;
}
};
public: // public functions of Tree
Tree<E>(){
n = 0;
}
int size() const; // number of nodes
bool empty() const; // is tree empty?
int directorySize(const TreeNode& u, const Position& p); //DECLARED(ERROR) - SIZE OF DIRECTORY
Position root();
PositionList Positions();
void insert(E e, Position p);
void preorder(Position p ,PositionList &pre_order);
private:
TreeNode *r;
int n;
friend class Position;
};
#endif
The error is only showing up in the Tree.cpp file.
There are multiple errors here:
The arguments are declared to be const qualified references but the const got dropped in the definitions.
depth() is a member of Tree<E>::Position not of Tree<E>.
The first parameter of depth() is a Tree<E> not a TreeNode.
Note that putting the code into a .cpp file is either confusion (if the intention is to include the file) or it will cause grief when using the template classes from another translation unit. This problem is unrelated to the question, though.
I have written a small code to practice data structures and the beautiful C++.
The code below works completely fine if make the variables in SNode to public and remove the friend class ... line. However, based on the textbook I'm reading, this should be working fine.
The errors I get are as follow:
line 11: error: ‘SLinkedList’ is not a class template
In instantiation of ‘class SNode’: line 10: error: template argument required for ‘class SLinkedList’
In instantiation of ‘void SLinkedList::addFront(const E&) [with E = int]’: line 9: error: ‘int SNode<int>::elem’ is private
Below is the code written in Clion:
#include <iostream>
using namespace std;
template <typename E>
class SNode {
private:
E elem; //line 9
SNode<E> * next; // line 10
friend class SLinkedList<E>; //Provide SLinkedList access to these private variables (line 11)
};
template <typename E>
class SLinkedList {
public:
SLinkedList();
~SLinkedList();
bool empty() const;
const E& front() const;
void addFront(const E& e);
void removeFront();
void printAll() const;
private:
SNode<E> * head;
};
template <typename E>
SLinkedList<E>::SLinkedList():head(NULL){};
template <typename E>
bool SLinkedList<E>::empty() const {
return (head==NULL);
}
template <typename E>
void SLinkedList<E>::addFront(const E &e) {
SNode<E> * node = new SNode<E>;
node->elem=e;
node->next=head;
head=node;
}
template <typename E>
void SLinkedList<E>::removeFront() {
SNode<E> * temp = head;
head = head->next;
delete temp;
}
template <typename E>
const E& SLinkedList<E>::front() const {
return head->elem;
}
template <typename E>
SLinkedList<E>::~SLinkedList() {
while (!empty()){
removeFront();
}
}
template <typename E>
void SLinkedList<E>::printAll() const {
SNode<E> * itr =head;
while (itr != NULL){
cout<<itr->elem<<" ";
itr = itr->next;
}
}
int main() {
cout << "Hello, World!" << endl;
SLinkedList<int> test ;
test.addFront(2);
test.addFront(3);
test.addFront(6);
test.addFront(8);
test.addFront(19);
test.printAll();
return 0;
}
friend class SLinkedList<E>;
This template is not declared yet. Your C++ code gets compiled in an orderly manner, from the beginning of your source file to the end. Until this template gets declared later on in this header file, the compiler has no clue what this is.
The solution is very simple: add a forward declaration to the beginning of the header file, because the SNode template declaration:
template <typename E> class SLinkedList;
template <typename E>
class SNode {
private:
E elem;
SNode<E> * next;
friend class SLinkedList<E>;
};
friend class SLinkedList<E>;
At this point SLinkedList is not defined yet as a template, hence giving the error. Give a forward declaration for SLinkedList, everything will be fine than.
Add this :-
template <typename E>
class SLinkedList;
I'm no expert in using templates but I'm not sure why I'm getting error: 'SLinked_List' is not a class template: friend class SLinked_List<T>; in the definition of class SNode. What is wrong with this piece of code?
Thank you,
Pranav
#include <iostream>
#include <string>
template <typename T>
class SNode{
friend class SLinked_List<T>;
private:
T data;
SNode<T>* next;
};
template <typename T>
class SLinked_List{
private:
SNode<T>* head;
public:
SLinked_List(){
head = nullptr;
}
bool empty() const { return head == nullptr; }
void insert_first (const T&);
};
template <typename T>
void SLinked_List<T> :: insert_first (const T& t){
SNode<T>* node = new SNode<T>;
node->data = t;
node->next = head;
head = node;
}
int main(){
SLinked_List<std::string> ls;
ls.insert_first("Hello");
return 0;
}
When you use template arguments to refer to a name you are saying that this type already exists as a template and I want to reference a specific specialization of that template. Inside SNode, SLinked_List hasn't been declared yet, so this can't be allowed because the compiler doesn't even know if it's a template yet.
It's clear you want to befriend the specialization taking a T, so you need to declare SLinked_List before SNode:
template <typename T>
class SLinked_List;
template <typename T>
class SNode{
friend class SLinked_List<T>;
private:
T data;
SNode<T>* next;
};
Now the compiler knows that SLinked_List is a template and can be referenced as such.
I am learning C++ templates for the first time, and have copied this code from "Data Structures and Algorithms in C++ by Michael Goodrich."
I get the error "Line 13: SLinkedList is not a template." I am at a complete loss as to why it is not since I have used "template " everywhere.
// ------------------ DEFINITION FOR NODE ------------------------
template <typename E>
class SNode{
private:
E elem;
SNode<E>* next;
friend class SLinkedList<E>;
public:
SNode(E element = NULL);
const E getElem() const;
void setElem(E element);
};
template <typename E>
SNode<E>::SNode(E element){ elem = element;}
template <typename E>
const E SNode<E>::getElem() const
{return elem;}
template <typename E>
void SNode<E>::setElem(E element)
{elem = element;}
// -------------------- DEFINITION FOR SINGLY-LINKED LIST --------------
template <typename E>
class SLinkedList
{
private:
SNode<E>* head;
public:
SLinkedList();
~SLinkedList();
bool isempty() const;
const E& infront() const;
void addfront(const E& e);
void removefront();
};
template <typename E>
SLinkedList<E>::SLinkedList()
:head(NULL) {}
template <typename E>
SLinkedList<E>::~SLinkedList()
{while(!isempty()) removefront();}
template <typename E>
bool SLinkedList<E>::isempty() const
{return (head == NULL);}
template <typename E>
const E& SLinkedList<E>::infront() const {return head->elem;}
template <typename E>
void SLinkedList<E>::addfront(const E& element) {
SNode<E>* v = new SNode<E>;
v->elem = element;
v->next = head;
head = v;
}
template <typename E>
void SLinkedList<E>::removefront() {
SNode<E>* old = head;
head = old->next;
delete old;
}
int main()
{
std::cout<<"Checking SLinkedList ..."<<std::endl<<std::endl;
SLinkedList<int> intList;
intList.addfront(13);
std::cout<<intList.head->next->getElem();
return 0;
}
friend class SLinkedList<E>;
This can be anything. The compiler doesn't know what it is. But if you tell him before declaring SNode that it will be defined later...:
template <typename E>
class SLinkedList;
... it might work ;)
You are using SLinkedList<E> even before declaring it. Before using it in you class `SNode', please declare it which is known as forward declaration.
I am having a problem with my first attempt at a proper go at modular programming....
I was wondering if anyone could suggest a possible direction as to how to approach the solution to the problem
here is my code and once again it is from Laszlo's Book on computational geometry ..the only thing I did different was break it into smaller pieces and a unit header file
The Code
header.h
#ifndef NULL
#define NULL 0
#endif
#ifndef A_H
#define A_H
// -----Definition of Node Class ----------------------------------
class Node{
protected:
Node *_prev;
Node * _next;
static int cindex;
public:
int index;
Node(void);
virtual ~Node(void);
Node *next(void); // accessor
Node *prev(void); //accessor
Node *insert(Node*);
Node*remove(void);
void splice (Node*);
};
// ------ end of definition of Node --------------------
//======================================================
//----------Start of Definition of ListNode class ------
template < class T > class List;
template<class T> class ListNode: public Node {
public:
T _val;
ListNode(T val);
friend class List<T>;
};
// ------ End of Definition of ListNode class --------------------
//====================================================++
//----------Start of Definition of List class ------
template<class T> class List {
private:
ListNode<T> *header;
ListNode<T> *win;
int _length;
public:
List(void);
~List(void);
T insert(T);
T append(T);
T prepend(T);
List * append(List*);
T remove(void);
void val(T);
T val(void);
T next(void);
T prev(void);
T first(void);
T last(void);
int length(void);
bool isFirst(void);
bool isLast(void);
bool isHead(void);
};
#endif
node.cpp
#include "header.h"
int Node::cindex=0;
Node::Node(void) :
_next(this), _prev(this)
{index=cindex++;}
Node::~Node(void) {}
Node* Node:: next(void)
{
return _next;
}
Node* Node::prev(void)
{
return _prev;
}
Node *Node::insert(Node*b){
b->_next=_next;
_next->_prev=b;
b->_prev=this;
_next=b;
return b;
}
Node*Node::remove(void)
{
_prev->_next=_next;
_next->_prev=_prev;
_next->_prev=this;
return this;
}
LstNode.cpp
#include "header.h"
template <class T> List <T> :: List(void): _length(0) //constructor for list
{
header =new ListNode<T>(NULL); //mind you this uses the LIstNode class
win=header;
}
template<class T> List <T>::~ List(void) // weird destructor
{
while (length()>0) {
first();remove();
}
delete header;
}
template <class T> T List <T> ::insert(T val)
{
win->insert( new ListNode <T> (val));
++_length;
return val;
}
template <class T> T List <T>::prepend(T val)
{
header->insert(new ListNode <T> (val));
++_length;
return val;
}
template <class T> T List <T>::append(T val)
{
header->prev()->insert(new ListNode <T> (val));
++_length;
return val;
}
template<class T> List <T>* List <T>::append(List<T>*l)
{
ListNode<T> *a =(ListNode<T>*)header->prev();
a->splice(l->header);
_length+=_length;
l->header-remove();
l->_length=0;
l->win=header;
return this;
}
template <class T> void List<T>::val(T v)
{
if (win!=header)
win->_val=v;
}
template <class T> T List<T>::val(void)
{
return win->_val;
}
template <class T> T List <T>:: next(void)
{
win=(ListNode <T>*)win->next();
return win->_val;
}
template <class T> T List <T>:: prev(void)
{
win=(ListNode <T>*)win->prev();
return win->_val;
}
template <class T> T List<T>::first(void)
{
win=(ListNode <T>*)header->next();
return win->_val;
}
template <class T> T List<T>::last(void)
{
win=(ListNode <T>*)header->prev();
return win->_val;
}
template <class T> int List <T>::length(void)
{
return _length;
}
template< class T> bool List <T> ::isFirst(void)
{
return (win==header->next()) &&(_length>0);
}
template< class T> bool List <T> ::isLast(void)
{
return (win==header->prev()) &&(_length>0);
}
template <class T> bool List <T>::isHead(void)
{
return (win == header);
}
experiment.cpp
#include <iostream>
#include "header.h"
int main()
{
List <int> dunder;
dunder.insert(9);
return 0;
}
THE PROBLEM
I first converted all of these files into object files with the generic command g++ -o file.cpp (separately) and then I did this g++ output.o output2.o ..
and this is the error I get :
experiment.o: In function `main':
experiment.cpp:(.text+0x11): undefined reference to `List<int>::List()'
experiment.cpp:(.text+0x22): undefined reference to `List<int>::insert(int)'
experiment.cpp:(.text+0x33): undefined reference to `List<int>::~List()'
experiment.cpp:(.text+0x46): undefined reference to `List<int>::~List()'
collect2: error: ld returned 1 exit status
You need to define your template class and its have its definition in the same file. As of right now template class header and definition are not separable.