Trouble with templates - c++

I have three files and I want to compile and run them, but I keep getting some errors and warnings. Redefinition of struct Node< T >. I don't know much about templates, but this looks right to me. And, I spent a lot of time trying to figure out whats wrong. Thanks.
//mystack.h
#ifndef MYSTACK_H
#define MYSTACK_H
template <class T>
struct Node
{
T info;
T *next;
};
template <class T>
class MyStack
{
private:
struct Node<T> *top;
public:
void Push(T item);
void Pop();
int Top();
void Print();
};
#endif
//mystack.cpp
#include <iostream>
#include "mystack.h"
template <class T>
struct Node
{
T info;
T* next;
};
template <class T>
class MyStack
{
private:
struct Node<T>* top;
public:
void Push(T item)
{
if(top == NULL)
{
top = new( struct Node<T> );
top->info = item;
top->next = NULL;
} else
{
Node<T>* temp;
temp = top;
top = new( struct Node<T> );
top->info = item;
top->next = temp;
}
}
void Pop()
{
if( top == NULL )
{
} else
{
Node<T>* temp;
temp = top->next;
delete top;
top = temp;
}
}
int Top()
{
return top;
}
void Print()
{
if(top != NULL)
{
Node<T>* temp;
temp = top;
while(temp != NULL)
{
std::cout << temp << std::endl;
temp = temp->next;
}
}
}
};

One mistake you did in the listings is that you redefine this structure as it says.
Thats the definition:
template <class T>
struct Node
{
T info;
T* next;
};
This definition is done in both listings.
Edit: The second thing is that your class method implementation does not look right. You will have the most success if you try not to split cpp and header files while using templates.

If you were designing a class instead of a template, what you're doing would be wrong because you're redefining types.
But since you're writing templates, you're wrong earlier than that: you can't separately compile templates.
Brief pointer on the C++ compilation model:
// Definition of Node
template<typename T>
struct Node {
T info;
T* next; // shouldn't that be a Node*?
};
// Definition of MyStack
template <typename T>
class MyStack
{
private:
Node<T> *top;
public:
// Declarations, but not definitions, of the Mystack function members.
void Push(T item);
void Pop();
int Top();
void Print();
};
// Example definition of MyStack::Push
template<typename T>
void
MyStack<T>::Push(T item)
{
// as before
}
The type definitions usually appear in headers (if they are to be reused in different TUs) with include guards as you are doing. The guards are here because the definitions must appear at most once per TU. Do not manually repeat a type definition (e.g. in a source file as you did). This is wrong as it should be: nobody wants copy-n-paste errors.
The function members definitions usually appear in source files, unless they are the members of a template. In the latter case it's simpler to put them in headers (they don't have to be inline either).
You can learn the details of the compilation model elsewhere on SO, or in books, or on the Internet. Searching for 'template definition' or 'one definition rule' (or ODR) can help.

First, In header, remove 'struct' from the line 'struct Node *top;'. In C++ structs are almost identical to classes, the only difference being that struct members are public by default and class members are private by default. You do not need to preface struct types with the struct keyword like in straight C.
Second, Your CPP is all wrong. Templates are instantiated by the compiler when needed, so they do not live in CPP files to be compiled into objects like normal (apart from template specializations). You can put your template definitions in the HPP itself or a better general solution is to use an IPP file, i.e
// mystack.ipp
#ifndef MYSTACK_IPP
#define MYSTACK_IPP
#include "mystack.h"
#include <iostream>
template <class T>
void MyStack<T>::Push(T item)
{
if(top == NULL)
{
top = new( struct Node<T> );
top->info = item;
top->next = NULL;
} else
{
Node<T>* temp;
temp = top;
top = new( struct Node<T> );
top->info = item;
top->next = temp;
}
}
template <class T>
void MyStack<T>::Pop()
{
if( top == NULL )
{
} else
{
Node<T>* temp;
temp = top->next;
delete top;
top = temp;
}
}
template <class T>
int MyStack<T>::Top()
{
return top;
}
template <class T>
void MyStack<T>::Print()
{
if(top != NULL)
{
Node<T>* temp;
temp = top;
while(temp != NULL)
{
std::cout << temp << std::endl;
temp = temp->next;
}
}
}
#endif
Then '#include "mystack.ipp"' in any file which makes use of the implementation of MyStack

Related

Reversing Linked List with Recursion, using STL

Code for Reversing Linked List with Recursion, using STL
#include<iostream>
#include<conio.h>
#include<list>
using namespace std;
template<typename T>
class node
{
public:
T data;
node<T> *next;
node(){ next = NULL; }
node(const T& item, node<T> *nextnode = NULL)
{
data = item;
next = nextnode;
}
};
template<typename T>
class Reverse_list
{
private:
node<T> *head;
void reverse(node<T> *front);
public:
Reverse_list(){ head = NULL; }
//template<typename T>
void Reverse();
template<typename T>
void Display( list<T>& alist );
};
int main()
{
Reverse_list <int> rl;
list<int> intlist;
int size, no;
cout << "Size of List ?? ";
cin >> size;
for (int i = 1; i <= size; i++)
{
cout << "Enter the " << i <<" "<< "element";
cin >> no;
intlist.push_front(no);
}
rl.Display(intlist);
rl.Reverse();
rl.Display(intlist);
_getch();
return 0;
}
template<typename T>
void Reverse_list<T>::Display(list<T>& alist)
{
list<int>::iterator iter = alist.begin();
while (iter != alist.end())
{
cout << *iter << " ";
iter++;
}
}
template<typename T>
void Reverse_list<T>::reverse(node<T> *front)
{
if (front->next == NULL)
{
head = front;
return;
}
reverse(front->next);
node<int> *back = front->next;
back->next = front;
front->next = NULL;
}
template<typename T>
void Reverse_list<T>::Reverse()
{
reverse(head);
}
The above code generates 2 errors.
Error 1) No instance of function template matches the argument list. ( No error number.)
If I remove line 1 ( mentioned in a code ) then above error is no more. ( Why? )
Error 2) C2783: 'void Reverse_list::Reverse1(void)' : could not deduce template argument for 'T'
How to solve above errors.
In above program , I wanted to pass " head" node ( which is private ) as
argument to Reverse function. But we can not access private member outside of the class. So I passed indirectly. Is this a correct way of passing ?? Or there is some other way of accessing private data ??
I'm not sure to understand your intentions but...
You're trying to declare a method (reverse()) inside another method (Reverse()) ? Uhmmm....
We return to this later.
Imagine that the following instruction is correct instruction of Reverse_list<T>::Reverse()
node<T> *back = front->next;
Why you declare back as a pointer to a generic Node<T> when you assign front->next (so a specific Node<int>) to it?
If you define back as a node<int> pointer, the method Reverse() has no longer reason to be a template (dependant from T) method. And you can avoid both errors.
With your actual code, when you call
rl.Reverse();
you call a template method but the compiler doesn't know how to determine the type T. You could explicit it in this way
rl.Reverse<int>();
but, as written before, I thik it's better if you remove the whole template part.
Or, alternatively, you can transform the whole class in a template class; where head is a pointer to a generic Node<T>, not a specifica Node<int>.
Something like (if I understand correctly your intentions)
template <typename T>
class Reverse_list
{
private:
node<T> *head;
void reverse (node<T> * front);
public:
Reverse_list() : head(NULL)
{ }
void Reverse();
void Display(list<T>& alist);
};
template<typename T>
void Reverse_list<T>::reverse (node<T> * front)
{
if (front->next == NULL)
{
head = front;
return;
}
reverse(front->next);
node<T> *back = front->next;
back->next = front;
front->next = NULL;
}
template<typename T>
void Reverse_list<T>::Reverse()
{ reverse(head); }
In this case, in main(), rl should be declared as
Reverse_list<int> rl;
fixing T as int, and the call to Reverse() should be
rl.Reverse();
--- EDIT 2016.05.10 ---
With the "template Reverse_list" solution, you should correct three points (at last).
1) in Reverse_list class declaration, you have commented the template<typename T> row before void Reverse(); good; you should delete (comment) the same line (for the same reason) before void Display( list<T>& alist );; so the class become
template<typename T>
class Reverse_list
{
private:
node<T> *head;
void reverse(node<T> *front);
public:
Reverse_list(){ head = NULL; }
//template<typename T>
void Reverse();
//template<typename T>
void Display( list<T>& alist );
};
2) Display() now is a method of a templated class; so the line
list<int>::iterator iter = alist.begin();
become
list<T>::iterator iter = alist.begin();
3) reverse() now is a method of a templated class; so the line
node<int> *back = front->next;
become
node<T> *back = front->next;

Friend class declaration error [duplicate]

This question already has answers here:
Understanding templates in c++
(2 answers)
Closed 7 years ago.
I'm implementing a singly linked list. Here's the node class
template <typename T> class node{
friend class slist<T>;
public:
explicit node():data(0), next(NULL){}
private:
T data;
node<T> *next;
};
And here's the list class.
template<typename T> class slist{
public:
slist():head(NULL){}
bool empty(){
return head == NULL;
}
void add_front(const T& data){
if(head == NULL){
node<T>* n = new node<T>();
n->data = data;
n->next = NULL;
head = n;
return;
}
node<T>* n = new node<T>();
n->data = data;
n->next = head;
head = n;
}
void remove_front(){
if(head == NULL) return;
node<T>* old = head;
head = old->next;
delete old;
}
void print_list(){
if(head == NULL) return;
while(!empty()){
std::cout<<head->data<<std::endl;
head = head->next;
}
}
~slist(){
while(!empty()) remove_front();
}
private:
node<T>* head;
};
The implementation works perfectly fine if I declare the members in the node as public. However the moment I declare them private and make the slist a friend class, I get the following error.
In file included from src.cpp:3:
./slist.hpp:5:28: error: redefinition of 'slist' as different kind of symbol
template<typename T> class slist{
^
./node.hpp:4:15: note: previous definition is here
friend class slist;
I can obviously find other implementation of single linked list, but I'm trying to understand what's going wrong here. So please refrain from unsolicited advice as "google it". Thanks.
You need to forward declare the List class as a template class:
#include <iostream>
template<typename T> class List; //<< fwd decl
template<typename T> class Node {
int i;
public:
friend class List<T>; //<< usage same as you have now
Node() : i(123) {}
int value() { return i; }
};
template<typename T> class List { //<< definition
public:
List(Node<T>* node) { node->i++; }
};
int main() {
Node<int> node{};
List<int> list{&node};
std::cout << node.value() << "\n";
}
http://ideone.com/2RUWgj
The friend class declaration needs it's own template parameter declaration without shadowing the enclosing classes template parameters:
template<typename U> class slist; // Forward declare slist
template <typename T>
class node{
template<typename U> // <<<<<
friend class slist<U>;
// ^ <<<<<
// ...
};

C++ Linked Lists with Multi-Files

I am a bit new to using multi-files. I have this very simple code for a linked list, but when I debug, it "stops working".
This problem has occured with me several times before. I want to know is there something wrong with my "linked list" code? Or is something wrong with the multi-files organization?
Any help would be highly appreciated.
======================================
//linkedListMAIN.cpp
#include "linkedlist.cpp"
void main()
{
linkList<int> l;
l.append(5);
l.traverse();
}
======================================
//linkedList.h
#include<iostream>
using namespace std;
template <class T>
class linkList
{
private:
struct node
{
T data;
node *next;
};
node *head;
node *tail;
int noOfEl;
public:
linkList()
{
noOfEl = 0;
head=tail=NULL;
}
void traverse();
int length();
void insertAt(T, int);
T delAt(int);
void append(T);
void clear();
};
======================================
//linkedList.cpp
#include "linkedlist.h"
template <class T>
void linkList<T>:: traverse()
{
node<T> *current=head;
if(head == NULL)
{
cout<<"List empty."<<endl;
}
while(current != NULL)
{
cout<<current->data;
current = current->next;
}
}
template <class T>
void linkList<T>::append(T data)
{
node< *newNode= new node;
newNode->next = NULL;
tail->next = newNode;
tail = newNode;
noOfEl++;
}
You should not include the .cpp in inkedListMAIN.cpp but the header (.h). Also unless you are using c++11 you will have to put the class definition of templated classes in the header.

Why is Visual Studio forcing StackNode two different ways?

So I wrote a Linked List based implementation of the Stack ADT recently. However, I'm not quite sure why there is a bit of a discrepancy between how the nodes of the Stack are being declared. The compiler gets very angry and won't compile until I write them a certain way for certain functions. I'm extremely curious as to why this is the case.
Here are two different methods which the compiler wants two different formats.
Here is my destructor where the compiler wants StackNode *temp.
template <typename DataType>
StackLinked<DataType>::~StackLinked() {
StackNode *temp;
while (top != 0) {
temp = top;
top = top->next;
delete temp;
}
}
Here is my assignment operator overload where the compiler wants StackNode<DataType> *temp.
template <typename DataType>
StackLinked<DataType>& StackLinked<DataType>::operator=(const StackLinked& other) {
if (this != &other) {
StackNode<DataType> *newNode, *current, *last;
if (top != 0) {
StackNode<DataType> *temp;
while (top != 0) {
temp = top;
top -> top->next;
delete temp;
}
}
if (other.top == 0) {
top = 0;
}
else {
current = other.top;
top = new StackNode<DataType>;
top->dataItem = current->dataItem;
top->next = 0;
last = top;
current = current->next;
while (current != 0) {
newNode = new StackNode<DataType>;
newNode->dataItem = current->dataItem;
newNode->next = 0;
last-> next = newNode;
last = newNode;
current = current->next;
}
}
}
return *this;
}
I don't know why this is, but the unknown is bothering me.
Note: My StackNode class is an inner class of the StackLinked class.
EDIT: Class declaration:
#ifndef STACKARRAY_H
#define STACKARRAY_H
#include <stdexcept>
#include <iostream>
using namespace std;
#include "Stack.h"
template <typename DataType>
class StackLinked : public Stack<DataType> {
public:
StackLinked(int maxNumber = Stack<DataType>::MAX_STACK_SIZE);
StackLinked(const StackLinked& other);
StackLinked& operator=(const StackLinked& other);
~StackLinked();
void push(const DataType& newDataItem) throw (logic_error);
DataType pop() throw (logic_error);
void clear();
bool isEmpty() const;
bool isFull() const;
void showStructure() const;
private:
class StackNode {
public:
StackNode(const DataType& nodeData, StackNode* nextPtr);
DataType dataItem;
StackNode* next;
};
StackNode* top;
};
#endif
If any other details are needed. Just ask! Thank you for your time!
From the code you showed, StackNode<DataType> is not correct, because StackNode is not a class template.
This makes me think you have a template also named StackNode that the compiler is finding. Go check whether any of your files contain another version of StackNode.

C++ Templates - LinkedList

EDIT -- Answered below, missed the angled braces. Thanks all.
I have been attempting to write a rudimentary singly linked list, which I can use in other programs. I wish it to be able to work with built-in and user defined types, meaning it must be templated.
Due to this my node must also be templated, as I do not know the information it is going to store. I have written a node class as follows -
template <class T> class Node
{
T data; //the object information
Node* next; //pointer to the next node element
public:
//Methods omitted for brevity
};
My linked list class is implemented in a seperate class, and needs to instantiate a node when adding new nodes to the end of the list. I have implemented this as follows -
#include <iostream>
#include "Node.h"
using namespace std;
template <class T> class CustomLinkedList
{
Node<T> *head, *tail;
public:
CustomLinkedList()
{
head = NULL;
tail = NULL;
}
~CustomLinkedList()
{
}
//Method adds info to the end of the list
void add(T info)
{
if(head == NULL) //if our list is currently empty
{
head = new Node<T>; //Create new node of type T
head->setData(info);
tail = head;
}
else //if not empty add to the end and move the tail
{
Node* temp = new Node<T>;
temp->setData(info);
temp->setNextNull();
tail->setNext(temp);
tail = tail->getNext();
}
}
//print method omitted
};
I have set up a driver/test class as follows -
#include "CustomLinkedList.h"
using namespace std;
int main()
{
CustomLinkedList<int> firstList;
firstList.add(32);
firstList.printlist();
//Pause the program until input is received
int i;
cin >> i;
return 0;
}
I get an error upon compilation however - error C2955: 'Node' : use of class template requires template argument list - which points me to the following line of code in my add method -
Node* temp = new Node<T>;
I do not understand why this has no information about the type, since it was passed to linked list when created in my driver class. What should I be doing to pass the type information to Node?
Should I create a private node struct instead of a seperate class, and combine the methods of both classes in one file? I'm not certain this would overcome the problem, but I think it might. I would rather have seperate classes if possible though.
Thanks, Andrew.
While the answers have already been provided, I think I'll add my grain of salt.
When designing templates class, it is a good idea not to repeat the template arguments just about everywhere, just in case you wish to (one day) change a particular detail. In general, this is done by using typedefs.
template <class T>
class Node
{
public:
// bunch of types
typedef T value_type;
typedef T& reference_type;
typedef T const& const_reference_type;
typedef T* pointer_type;
typedef T const* const_pointer_type;
// From now on, T should never appear
private:
value_type m_value;
Node* m_next;
};
template <class T>
class List
{
// private, no need to expose implementation
typedef Node<T> node_type;
// From now on, T should never appear
typedef node_type* node_pointer;
public:
typedef typename node_type::value_type value_type;
typedef typename node_type::reference_type reference_type;
typedef typename node_type::const_reference_type const_reference_type;
// ...
void add(value_type info);
private:
node_pointer m_head, m_tail;
};
It is also better to define the methods outside of the class declaration, makes it is easier to read the interface.
template <class T>
void List<T>::add(value_type info)
{
if(head == NULL) //if our list is currently empty
{
head = new node_type;
head->setData(info);
tail = head;
}
else //if not empty add to the end and move the tail
{
Node* temp = new node_type;
temp->setData(info);
temp->setNextNull();
tail->setNext(temp);
tail = tail->getNext();
}
}
Now, a couple of remarks:
it would be more user friendly if List<T>::add was returning an iterator to the newly added objects, like insert methods do in the STL (and you could rename it insert too)
in the implementation of List<T>::add you assign memory to temp then perform a bunch of operations, if any throws, you have leaked memory
the setNextNull call should not be necessary: the constructor of Node should initialize all the data member to meaningfull values, included m_next
So here is a revised version:
template <class T>
Node<T>::Node(value_type info): m_value(info), m_next(NULL) {}
template <class T>
typename List<T>::iterator insert(value_type info)
{
if (m_head == NULL)
{
m_head = new node_type(info);
m_tail = m_head;
return iterator(m_tail);
}
else
{
m_tail.setNext(new node_type(info));
node_pointer temp = m_tail;
m_tail = temp.getNext();
return iterator(temp);
}
}
Note how the simple fact of using a proper constructor improves our exception safety: if ever anything throw during the constructor, new is required not to allocate any memory, thus nothing is leaked and we have not performed any operation yet. Our List<T>::insert method is now resilient.
Final question:
Usual insert methods of single linked lists insert at the beginning, because it's easier:
template <class T>
typename List<T>::iterator insert(value_type info)
{
m_head = new node_type(info, m_head); // if this throws, m_head is left unmodified
return iterator(m_head);
}
Are you sure you want to go with an insert at the end ? or did you do it this way because of the push_back method on traditional vectors and lists ?
Might wanna try
Node<T>* temp = new Node<T>;
Also, to get hints on how to design the list, you can of course look at std::list, although it can be a bit daunting at times.
You need:
Node<T> *temp = new Node<T>;
Might be worth a typedef NodeType = Node<T> in the CustomLinkedList class to prevent this problem from cropping up again.
That line should read
Node<T>* temp = new Node<T>;
Same for the next pointer in the Node class.
As said, the solution is
Node<T>* temp = new Node<T>;
... because Node itself is not a type, Node<T> is.
And you will need to specify the template parameter for the Node *temp in printlist also.
// file: main.cc
#include "linkedlist.h"
int main(int argc, char *argv[]) {
LinkedList<int> list;
for(int i = 1; i < 10; i++) list.add(i);
list.print();
}
// file: node.h
#ifndef _NODE_H
#define _NODE_H
template<typename T> class LinkedList;
template<typename T>class Node {
friend class LinkedList<T>;
public:
Node(T data = 0, Node<T> *next = 0)
: data(data), next(next)
{ /* vacio */ }
private:
T data;
Node<T> *next;
};
#endif//_NODE_H
// file: linkedlist.h
#ifndef _LINKEDLIST_H
#define _LINKEDLIST_H
#include <iostream>
using namespace std;
#include "node.h"
template<typename T> class LinkedList {
public:
LinkedList();
~LinkedList();
void add(T);
void print();
private:
Node<T> *head;
Node<T> *tail;
};
#endif//_LINKEDLIST_H
template<typename T>LinkedList<T>::LinkedList()
: head(0), tail(0)
{ /* empty */ }
template<typename T>LinkedList<T>::~LinkedList() {
if(head) {
Node<T> *p = head;
Node<T> *q = 0;
while(p) {
q = p;
p = p->next;
delete q;
}
cout << endl;
}
}
template<typename T>LinkedList<T>::void add(T info) {
if(head) {
tail->next = new Node<T>(info);
tail = tail->next;
} else {
head = tail = new Node<T>(info);
}
}
template<typename T>LinkedList<T>::void print() {
if(head) {
Node<T> *p = head;
while(p) {
cout << p->data << "-> ";
p = p->next;
}
cout << endl;
}
}
You Should add new node in this way
Node<T>* temp=new node<T>;
Hope you Solved :)
#include<iostream>
using namespace std;
template < class data > class node {
private :
data t;
node<data > *ptr;
public:
node() {
ptr = NULL;
}
data get_data() {
return t;
}
void set_data(data d) {
t = d;
}
void set_ptr(node<data > *p) {
ptr = p;
}
node * get_ptr() {
return ptr;
}
};
template <class data > node < data > * add_at_last(data d , node<data > *start) {
node< data > *temp , *p = start;
temp = new node<data>();
temp->set_data(d);
temp->set_ptr(NULL);
if(!start) {
start = temp;
return temp;
}
else {
while(p->get_ptr()) {
p = p->get_ptr();
}
p->set_ptr(temp);
}
}
template < class data > void display(node< data > *start) {
node< data > *temp;
temp = start;
while(temp != NULL) {
cout<<temp->get_data()<<" ";
temp = temp->get_ptr();
}
cout<<endl;
}
template <class data > node < data > * reverse_list(node<data > * start) {
node< data > *p = start , *q = NULL , *r = NULL;
while(p->get_ptr()) {
q = p;
p = p->get_ptr();
q->set_ptr(r);
r = q;
}
p->set_ptr(r);
return p;
}
int main() {
node < int > *start;
for(int i =0 ; i < 10 ; i ++) {
if(!i) {
start = add_at_last(i , start);
}
else {
add_at_last(i , start);
}
}
display(start);
start = reverse_list(start);
cout<<endl<<"reverse list is"<<endl<<endl;
display(start);
}