Redefinition error while making Templated Node class - c++

I was working on this code, when I came across this redefinition error when I called it in my enqueue function. I've looked everywhere on how to fix it, but to no avail. I've used the header guard and I don't think I've redefined it anywhere else, I'm honestly pretty stuck here. Help is greatly appreciated. This is a little bit different from the cases I've looked up already, since they're not using templates.
#pragma once
#include <cstdio> // Needed for NULL
using namespace std;
template <class T>
class Node { // this is where the error happens, says "redefinition of class Node<T>" here, adds in a note that there's a previous definition of class Node<T> here.
public:
Node<T>* next;
T data;
Node();
Node(T dat);
}; // Node
template <class T>
Node<T>::Node(){
next = NULL;
}
template <class T>
Node<T>::Node(T thedata){
next = NULL;
data = thedata
}
//PriorityQueue.h
//There is a #pragma once at the top of the file.
template <class T>
void PriorityQueue<T>::enqueue(const T& x){
Node<T>* tempN;
Node<T>* newN = new Node<T>(x);
if(head == NULL || newN < head){
head = newN;
head->next = NULL;
}
else{
tempN = head;
while(tempN->next != NULL && tempN < newN){
tempN = tempN->next;
}
newN->next = tempN->next;
tempN->next = newN;
}
}
template <class T>
T& PriorityQueue<T>::peek() const throw(EmptyDataCollectionException){
return head->data;
}
#include "Queue.h"
#include "Event.h"
#include "PriorityQueue.h"
#include "EmptyDataCollectionException.h"
#include <iostream>
using namespace std;
int main () {
Event x;
Event x1;
Event x2;
//type 0 is arrival, type 1 is departure.
x.setLength(10);
x.setArrivaltime(5);
x1.setLength(4);
x1.setArrivaltime(3);
x2.setLength(4);
x2.setArrivaltime(8);
PriorityQueue<Event> Q;
Q.enqueue(x);
Q.enqueue(x1);
Q.enqueue(x2);
Event y = Q.peek();
cout << endl << "top: " << y;
return 0;
} // main
#pragma once
using namespace std;
typedef enum etype { arrival, departure } EventType;
// Desc: Represents a simulation event
class Event {
private:
EventType type;
unsigned arrivaltime;
// standing for arrival time.
unsigned length;
public:
//the default constructor for event.
Event();
EventType getType() const;
unsigned getArrivaltime() const;
unsigned getLength() const;
void setType(const EventType atype);
void setArrivaltime(const unsigned AnArrivaltime);
void setLength(const unsigned ALength);
// Desc: Comparators
bool operator<(const Event &r);
bool operator>(const Event &r);
bool operator<=(const Event &r);
bool operator>=(const Event &r);
friend ostream & operator<<(ostream & os, const Event & r);
}; // Event
#pragma once
#include "EmptyDataCollectionException.h"
#include <cstdio>
using namespace std;
template <class T>
class Queue {
private:
static unsigned const INITIAL_SIZE = 6;
int * arr;
unsigned size;
unsigned capacity;
unsigned frontindex;
unsigned backindex;
/* you choose your implementation */
Edit: Queue.h, Node.h, PriorityQueue.h and Event.h all have #pragma once.
Okay, EVERYTHING is in there now, I just felt like it would get really cluttered.

Related

Implement a template of a Queue, using 2 Classes [duplicate]

This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed last year.
I have a problem. I have implemented a Queue, while using a Class "Queue" and a Class "Element".
the problem i have now is, that I can't work out how to create the template for class Element.
If I don't use the template and just use int instead of T. Everything works fine. I already looked for many examples on the Internet. But nobody uses two classes, which is probably more efficient. I think my problem is that i don't know how to use the pointer in templates.
PS: The template in Queue.h and.cpp works i think, but if i start trying to create a template for Element it doesn't work.
My Queue.h file
#ifndef ELEMENT_H
#define ELEMENT_H
#include "Element.h"
template <class T>
class Queue{
public:
explicit Queue(int max_queue);
~Queue() = default;
void enqueue(T inhalt);
Element* dequeue();
Element* show();
bool isEmpty();
private:
Element<T>* front{};
Element<T>* back{};
int max;
int anzahl = 0;
};
#endif
My Queue.cpp file
#include "Queue.h"
#include <iostream>
#include <string>
template <class T>
Queue<T>::Queue(int max_queue){
max = max_queue;
}
template <class T>
void Queue<T>::enqueue(T inhalt){
Element* e = new Element(inhalt);
if(max > anzahl){
if(isEmpty()){
front = back = e;
}else{
back->setNext(e);
back = e;
}
} anzahl++;
}
template <class T>
Element* Queue<T>::dequeue(){
Element* e = front;
front = front->getNext();
e->setNext(nullptr);
return e;
}
template <class T>
bool Queue<T>::isEmpty()
{
return anzahl == 0;
}
template <class T>
Element* Queue<T>::show()
{
return front;
}
My Element.h file
#ifndef QUEUE_H
#define QUEUE_H
class Element{
public:
explicit Element(int);
~Element() = default;
int getInhalt()const;
void setInhalt(int);
Element*getNext()const;
void setNext(Element*);
protected:
int inhalt;
Element* next;
};
#endif
My Element.cpp file
#include <string>
#include "Element.h"
Element::Element( int inhalt_element )
{
inhalt = inhalt_element;
next = nullptr;
}
int Element::getInhalt() const {
return inhalt;
}
void Element::setInhalt(int inhalt) {
Element::inhalt = inhalt;
}
Element* Element::getNext() const {
return next;
}
void Element::setNext(Element *next) {
Element::next = next;
}
The warning I'm getting is main.cpp:(.text+0x1a): undefined reference to `Queue::Queue(int)'
And If I try to use a template for the element class. There are hundreds of lines in the warnings, so I know I'm thinking completely wrong.
I am still pretty novice if it is about programming so any help or any idea would be really appreciated.
Thank you
The implementation of template classes must be done in the .h
The following code compiles.
#include <iostream>
#include <string>
template <class T>
class Element{
public:
Element( T inhalt_element ){
inhalt = inhalt_element;
next = nullptr;
}
T getInhalt() const {
return inhalt;
}
void setInhalt(T inhalt) {
this->inhalt = inhalt;
}
Element<T>* getNext() const {
return next;
}
void setNext(Element<T> *next) {
this->next = next;
}
protected:
T inhalt;
Element<T>* next;
};
template <class T>
class Queue{
public:
Queue(int max_queue){
max = max_queue;
}
void enqueue(T inhalt){
Element<T>* e = new Element<T>(inhalt);
if(max > anzahl){
if(isEmpty()){
front = back = e;
}else{
back->setNext(e);
back = e;
}
} anzahl++;
}
Element<T>* dequeue(){
Element<T>* e = front;
front = front->getNext();
e->setNext(nullptr);
return e;
}
bool isEmpty(){
return anzahl == 0;
}
Element<T>* show(){
return front;
}
private:
Element<T>* front{};
Element<T>* back{};
int max;
int anzahl = 0;
};
int main() {
std::cout << "Hello World!";
Queue<int> queue(10);
return 0;
}

C++, instantiating a generic Node storing an instance of an object using templates

I am currently attempting to implement a Doubly Linked List for a Data Structures class.
I currently have implemented a generic Node* class and wanted to hold an instance of another class Student(int i, int j) that I have implemented.
This is what i'm attempting to do in my main method:
Student student1 = Student(10,11);
Node<Student()> node1 = Node<Student()> (student1);
This is the error I am receiving.
Everything worked absolutely fine when the Node was holding a primitive data type like an int but i'm unsure how to account for the difference between storing an int and storing a Student object.
I would love any insight or pushes in the right direction.
Thank you.
Here is my implementation of Node.
#ifndef NODE_H
#define NODE_H
template <class T>
class Node
{
public:
Node();
Node(T k);
virtual~Node();
T key;
Node<T>* prev;
Node<T>* next;
};
#endif
//default constructor
template <class T>
Node<T>::Node()
{
prev = NULL;
next = NULL;
}
template <class T>
Node<T>::Node(T k)
{
prev = NULL;
next = NULL;
key = k;
}
template<class T>
Node<T>::~Node()
{
//implement
}
Student.cpp
#include "Student.h"
Student::Student()
{
mArrivalTime = 0;
mTimeNeeded = 0;
}
Student::Student(int arrivalTime, int timeNeeded)
{
mArrivalTime = arrivalTime;
mTimeNeeded = timeNeeded;
}
Student::~Student()
{
//implement
}
int Student::getArrivalTime()
{
return mArrivalTime;
}
int Student::getTimeNeeded()
{
return mTimeNeeded;
}
Student.h
#ifndef STUDENT_H
#define STUDENT_H
using namespace std;
class Student
{
private:
int mArrivalTime;
int mTimeNeeded;
public:
Student();
Student(int arrivalTime, int timeNeeded);
~Student();
int getArrivalTime();
int getTimeNeeded();
};
#endif
Don't use (), just use the class name. e.g:
Node<Student> node1 = Node<Student> (student1);

How do I overload an operator for a template class in C++?

I have a binary search tree class (BST.h) and a node class (Node.h) of which works fine when I store data types such as integers in it. My problem is trying store class objects in my BST and use an attribute from the object as the key. My program also has a student class which contains studentID and studentName. How would I write an operator overload in my student class so every time my BST preforms operation on nodes, it will overload to the student.getID(), instead of operating on the object itself. I have the rough idea of what the overload function should look like but i don't know where it should go or if its coded correctly anyway.
//My attempt at an operator overload
bool operator< (const Student &s1, const Student &s2)
{
return s1.GetID < s2.GetID;
}
//Node.h
#ifndef NODE_H
#define NODE_H
#include <iostream>
using namespace std;
template<class T>
class Node
{
public:
Node();
T data;
Node *left;
Node *right;
Node(T);
};
template<class T>
Node<T>::Node()
{
}
template<class T>
Node<T>::Node(T d)
{
data = d;
left = NULL;
right = NULL;
}
#endif //
//BST.h
#ifndef BST_H
#define BST_H
#include <iostream>
#include "Node.h"
#include <string>
using namespace std;
template<class T>
class BST
{
public:
BST();
void Insert(T);
Node<T> *Search(T);
void preOrder();
void inOrder();
void postOrder();
~BST();
private:
Node<T> *root;
void Insert(T , Node<T> *aNode);
Node<T> *Search(T, Node<T> *aNode);
void preOrder(Node<T> *aNode);
void inOrder(Node<T> *aNode);
void postOrder(Node<T> *aNode);
};
template<class T>
BST<T>::BST()
{
root = NULL;
}
template<class T>
void BST<T>::Insert(T data, Node<T> *aNode)
{
if (data < aNode->data)
{
if (aNode->left != NULL)
{
Insert(data, aNode->left);
}
else
{
aNode->left = new Node<T>(data);
aNode->left->left = NULL;
aNode->left->right = NULL;
}
}
else
{
if (data >= aNode->data)
{
if (aNode->right != NULL)
{
Insert(data, aNode->right);
}
else
{
aNode->right = new Node<T>(data);
aNode->right->left = NULL;
aNode->right->right = NULL;
}
}
}
}
template<class T>
void BST<T>::Insert(T data)
{
if (root != NULL)
{
Insert(data, root);
}
else
{
root = new Node<T>(data);
root->left = NULL;
root->right = NULL;
}
}
template<class T>
Node<T>* BST<T>::Search(T data, Node<T> *aNode)
{
if (aNode != NULL)
{
if (data == aNode->data)
{
return aNode;
}
if (data < aNode->data)
{
return Search(data, aNode->left);
}
else
{
return Search(data, aNode->right);
}
}
else
{
return NULL;
}
}
template<class T>
Node<T>* BST<T>::Search(T data)
{
return Search(data, root);
}
template<class T>
void BST<T>::preOrder()
{
preOrder(root);
}
template<class T>
void BST<T>::preOrder(Node<T> *aNode)
{
if (aNode != NULL)
{
cout << aNode->data << " ";
preOrder(aNode->left);
preOrder(aNode->right);
}
}
template<class T>
void BST<T>::inOrder()
{
inOrder(root);
}
template<class T>
void BST<T>::inOrder(Node<T> *aNode)
{
if (aNode != NULL)
{
inOrder(aNode->left);
cout << aNode->data << " ";
inOrder(aNode->right);
}
}
template<class T>
void BST<T>::postOrder()
{
postOrder(root);
}
template<class T>
void BST<T>::postOrder(Node<T> *aNode)
{
if (aNode != NULL)
{
postOrder(aNode->left);
postOrder(aNode->right);
cout << aNode->data << " ";
}
}
template<class T>
BST<T>::~BST()
{
}
#endif // !BST_H
//Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include <iostream>
#include <string>
using namespace std;
class Student
{
public:
Student();
Student(string, int);
~Student();
int Student::GetID();
private:
string name;
int ID;
};
inline int Student::GetID()
{
return ID;
}
You seem to be asking about operator< taking Students , however Student is not a class template, so the title of your post is baffling.
As someone else pointed out, your operator< is almost correct, except you have to actually call GetID() instead of comparing pointers to member functions.
This won't work yet until you fix GetID however. Instead of int Student::GetID(); it should be:
int GetID() const;
The const means that it can be called on objects passed by const reference, as you have in your operator< implementation. And you don't repeat the Student:: when declaring functions inside the class. (You use it when defining class members outside of the class definition).
Declare it as a friend function within your Student class, next to the rest of your member functions
friend bool operator < (Student& s1, Student& s2);
Your implementation is correct, it should go outside your Student class within the same header file.

Apple mach-o linker (id) error with C++

I created a new project in Xcode 5.0 to implement a Queue class as following:
I created a .h file called QueueArray.h and it contains the following:
#ifndef __Queue__QueueArray__
#define __Queue__QueueArray__
#include <iostream>
template <class T>
class QueueArray
{
public:
QueueArray(int cap);
~QueueArray();
void Enqueue(T& val);
T Dequeue(void);
T GetFirst(void);
T GetLast(void);
bool IsEmpty(void);
bool IsFull(void);
void Clear(void);
private:
T* data;
int capacity, size, first, last;
};
#endif
and a .cpp file called QueueArray.cpp that contains the following:
#include "QueueArray.h"
using namespace std;
template <class T>
QueueArray<T>::QueueArray(int cap)
{
capacity = cap;
data = new T[capacity];
size = 0;
first = last = -1;
}
template <class T>
QueueArray<T>::~QueueArray(void)
{
delete [] data;
}
template <class T>
void QueueArray<T>::Enqueue(T& el)
{
if(IsFull() == true)
{
printf("\n Can't enqueue into a full queue!");
return;
}
if(IsEmpty() == true)
first = last = 0;
else if(last == capacity-1)//if at the last entry
last = 0; //wrap around to the first entry
else
last++;
data[last] = el;
size++;
}
template <class T>
T QueueArray<T>::Dequeue()
{
if(IsEmpty() == true)
{
printf("\n Can't dequeue from an empty queue!");
return -1;
}
T el = data[first];
if(first == last) //if only one element in queue
last = first = -1; //we'll get an empty queue
else if(first == capacity-1) //if at the last entry
first = 0; //wrap around to the first entry
else //normal case
first++;
size--;
return el;
}
template <class T>
T QueueArray<T>::GetFirst()
{
return data[first];
}
template <class T>
T QueueArray<T>::GetLast()
{
return data[last];
}
template <class T>
bool QueueArray<T>::IsEmpty(void)
{
return size == 0;
}
template <class T>
bool QueueArray<T>::IsFull(void)
{
return size == capacity;
}
and a main.cpp file that contains the following:
#include <iostream>
#include "QueueArray.h"
using namespace std;
int main(int argc, const char * argv[])
{
QueueArray<int> q(100);
for (int i=0; i<100; i++)
{
q.Enqueue(i);
}
for (int i=0; i<100; i++) {
cout<<q.Dequeue()<<endl;
}
return 0;
}
When I try to run the project, a message appears saying "Build Failed" and here is a screenshot of the errors:
How to fix that?
The compiler needs to see the definition of the Template before using it.
http://www.parashift.com/c++-faq-lite/templates-defn-vs-decl.html
There are more than one solution:
a. Move the definitions from .cpp file to the .h file
b. Use the export keyword if your compiler supports
http://www.parashift.com/c++-faq-lite/separate-template-fn-defn-from-decl-export-keyword.html
c. Add an inline declaration:
http://www.parashift.com/c++-faq-lite/separate-template-fn-defn-from-decl.html
You need to include the template definitions in-line with their declarations. An easy solution to this is to rename QueueArray.cpp to something like QueueArray_impl.h and #include it from the bottom of QueueArray.h
#ifndef __Queue__QueueArray__
#define __Queue__QueueArray__
#include <iostream>
template <class T>
class QueueArray
{
public:
QueueArray(int cap);
~QueueArray();
void Enqueue(T& val);
T Dequeue(void);
T GetFirst(void);
T GetLast(void);
bool IsEmpty(void);
bool IsFull(void);
void Clear(void);
private:
T* data;
int capacity, size, first, last;
};
#include "QueueArray_impl.h"
#endif

Expression Must have Class Type?

So I've been playing around with Nodes and keep running into this error when I try to test it. If I use Parentheses I get this Error on list. - "Expression must have class type!"
If I don't use Parentheses I get this Error on list, insert and display - "this is inaccessible."
This happens when Declaring my LList in Main(). What's going on and why is this?
My Driver
#include "LList.h"
#include <iostream>
using namespace std;
int main()
{
LList<int> list;
bool test = list.insert(5);
list.display();
return 0;
}
Class LList
#include "Nodes.h"
#ifndef LLIST_H
#define LLIST_H
template<typename TYPE>
class LList
{
Node<TYPE>* front;
LList();
~LList();
bool insert(const TYPE& dataIn);
void display() const;
};
template<typename TYPE>
LList<TYPE>::LList()
{
front = null;
};
template<typename TYPE>
LList<TYPE>::~LList()
{
Node<TYPE>* temp;
while(front)
{
temp = front;
front = fornt -> next;
delete temp;
}
};
template<typename TYPE>
bool LList<TYPE>::insert(const TYPE& dataIn)
{
bool success = false;
Node<TYPE> pBefore = null;
Node<TYPE> pAfter = front;
while(pAfter && PAfter->data < dataIn)
{
pBefore = pAfter;
pAfter = pAfter->next;
}
if(Node<TYPE>* store = new Node<TYPE>)
store->data = dataIn
return success;
};
template<typename TYPE>
void LList<TYPE>::display() const
{
TYPE* temp = front;
while(front && temp->next != null)
{
cout << temp->data << endl;
}
};
#endif
Class Nodes
#ifndef NODES_H
#define NODES_H
template<typename TYPE>
struct Node
{
Node<TYPE>* next;
TYPE data;
Node();
Node(TYPE d, Node<TYPE> n);
};
template<typename TYPE>
Node<TYPE>::Node()
{
data = 0;
next = null;
};
template<typename TYPE>
Node<TYPE>::Node(TYPE d, Node<TYPE> n)
{
data = d;
next = n;
};
#endif
Your errors are a result of your class declaration:
template<typename TYPE>
class LList
{
Node<TYPE>* front;
LList();
~LList();
bool insert(const TYPE& dataIn);
void display() const;
};
The clue is in the error "This is inaccesible." Because you have not given any access modifiers, all of the members of this class default to private. To fix this, you just need to label the public and private sections of your class:
template<typename TYPE>
class LList
{
public:
LList();
~LList();
bool insert(const TYPE& dataIn);
void display() const;
private:
Node<TYPE>* front;
};
With this change, your code should work with or without parentheses at the end of your variable declaration for list.