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;
}
Related
I'm trying to create a individual List with a templated value, but unfortunately I can not link from my List to the ListElements with templates.
In my main I call List<int> list1; to create a instance of the class List.
A List contains multiple ListElements that contain the value, that should be templated.
Compiler throws an error at
ListElement* first;
ListElement* last;
in List.h.
It says C2955 - 'ListElement' : use of class type requires type argument list
List.h
#pragma once
#include <string>
#include "ListElement.h"
template<class T>
class List
{
private:
ListElement* first;
ListElement* last;
public:
List();
~List();
void printList();
void pushBack(T value);
void pushFront(T value);
};
List.cpp
#include <iostream>
#include "List.h"
template<class T>
List<T>::List()
{
first = NULL;
last = NULL;
}
template<class T>
List<T>::~List()
{
}
template<class T>
void List<T>::pushBack(T value)
{
if (last)
{
ListElement* tmp = last;
last = new ListElement(value);
last->setPrev(tmp);
tmp->setNext(last);
}
else
{
first = new ListElement(value);
last = first;
}
}
template<class T>
void List<T>::pushFront(T value)
{
if (first)
{
ListElement* tmp = first;
first = new ListElement(value);
first->setNext(tmp);
tmp->setPrev(first);
}
else
{
last = new ListElement(value);
first = last;
}
}
template<class T>
void List<T>::printList()
{
if (first)
{
ListElement* tmp = first;
while (tmp)
{
std::cout << tmp->getValue() << std::endl;
if (tmp != last)
tmp = tmp->getNext();
else
break;
}
}
else
{
std::cout << "List is empty!" << std::endl;
}
}
template class List<int>;
template class List<std::string>;
ListElement.h
#pragma once
#include <string>
template<class T>
class ListElement
{
private:
ListElement* next;
ListElement* prev;
T value;
public:
ListElement(T val);
~ListElement();
ListElement* getNext() { return next; }
ListElement* getPrev() { return prev; }
void setNext(ListElement* elem) { next = elem; }
void setPrev(ListElement* elem) { prev = elem; }
T getValue() { return value; }
};
ListElement.cpp
#include "ListElement.h"
template<class T>
ListElement<T>::ListElement(T val)
{
value = val;
}
template<class T>
ListElement<T>::~ListElement()
{
}
template class ListElement<int>;
template class ListElement<std::string>;
ListElement is a template, so you want to use a specific instantiation for your pointers:
template<class T>
class List
{
private:
ListElement<T>* first;
ListElement<T>* last;
// note: ^^^
likewise for other occurrences. Only within the template, the template name is usable for the current instantiation, i.e., within List, you can use List as a shortcut for List<T>.
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.
My program not discovery the functions returnTest or others new function that are create in struct Node. The g++ compiler return this error:
linkedList.cpp: In instantiation of 'void LinkedList<T>::insert(T) [with T = int]':
linkedList.cpp:37:22: required from here
linkedList.cpp:31:13: error: 'struct LinkedList<int>::Node' has no member named
'returnTest' std::cout << auxHead->returnTest();
My files are:
Main.cpp
#include "linkedList.hpp"
#include <iostream>
#include <cstdlib>
template<class T> LinkedList<T>::LinkedList()
{
node = NULL;
}
template<class T> LinkedList<T>::~LinkedList()
{
}
template<class T> bool LinkedList<T>::isEmpty(){
}
template<class T> int LinkedList<T>::size(){
if (node == NULL)
return 0;
}
template<class T> void LinkedList<T>::insert(T element){
Node *auxHead = node;
if (auxHead == NULL){
Node* newNode = new Node();
newNode->data = element;
node = newNode;
}else{
std::cout << auxHead->returnTest();
}
}
int main(){
LinkedList<int> *newLinked = new LinkedList<int>();
newLinked->insert(55);
newLinked->insert(55);
return 0;
}
LinkedList.hpp
#ifndef __LINKEDLIST_H_
#define __LINKEDLIST_H_
#include <stdio.h>
template <class T> class LinkedList {
private:
struct Node {
T data = NULL;
Node *next;
T getData(){
return data;
}
Node getNext(){
return next;
}
int returnTest(){
return -1;
}
T isNIL(){
return (data == NULL);
}
};
Node *node = NULL;
public:
LinkedList();
~LinkedList();
bool isEmpty();
int size();
void insert (T&);
};
#endif
My g++ version is 4.8.1. Please ignore the method size()
You cannot put to implementation of template class/function. just put the implementation (which is in .cpp) into header file.
This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 9 years ago.
Tried to make custom ArrayList ,
the first error told me to add Type Tamplate () to struct ListNode.
But after follow an error instruction , got new error instead.
" Symbols not found for architecture x86_64
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
#include <iostream>
#include <string>
using namespace std;
template<typename T>
struct ListNode<T>{
T value;
ListNode<T>* next;
ListNode(T d,ListNode<T> *n){
value = d;
next = n;
}
};
template<typename T>
class LinkedList
{
public :
LinkedList();
LinkedList(const LinkedList<T>& another);
~LinkedList();
void copy(const LinkedList<T>& another);
void add(T value);
void remove(int index);
int get(int index) const;
bool isEmpty() const;
int size() const;
string toString() const;
void clear();
LinkedList<T>& operator = (const LinkedList<T>& another);
private :
ListNode<T>* x_front;
int x_size;
};
#endif // LINKEDLIST_H
.CPP
#include "linkedlist.h"
#include "strlib.h"
#include <string>
using namespace std;
template<typename T>
LinkedList<T>::LinkedList(){
x_front = NULL;
x_size =0;
}
template<typename T>
LinkedList<T>::~LinkedList(){
clear();
}
template<typename T>
LinkedList<T>& LinkedList<T>::operator = (const LinkedList<T>& another){
delete x_front;
copy(another);
return *this;
}
template<typename T>
void LinkedList<T>::copy(const LinkedList<T>& another){
ListNode<T>* anotherCurrent = another.x_front;
while(anotherCurrent!=NULL){
this->add(anotherCurrent->value);
anotherCurrent = anotherCurrent->next;
}
}
template<typename T>
void LinkedList<T>::add(T value){
if(x_front == NULL){
x_front = new ListNode<T>(value,NULL);
}
else {
ListNode<T>*current = x_front;
while(current-> next != NULL){
current = current -> next;
}
current->next = new ListNode<T>(value,NULL);
}
x_size++;
}
template<typename T>
void LinkedList<T>::remove(int index){
if(index==0){
x_front = x_front->next;
}
else {
ListNode<T>* current = x_front;
for(int indexNow = 0 ; indexNow < index -1 ; indexNow++){
current = current->next;
}
current -> next = current -> next -> next;
}
x_size--;
}
template<typename T>
bool LinkedList<T>::isEmpty() const {
if(this->x_size == 0){
return true;
}
else {return false;}
}
template<typename T>
void LinkedList<T>::clear(){
while(this->isEmpty() ==false){
remove(x_size-1);
}
}
template<typename T>
string LinkedList<T>::toString() const{
string mystring;
for(ListNode<T>*p = x_front; p!=NULL ;p = p->next){
mystring = mystring + " " + integerToString(p->value);
}
return mystring;
}
template<typename T>
int LinkedList<T>::size() const{
return (this->x_size);
}
All of your template must be defined inside the header file
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.