This question already has answers here:
Why can templates only be implemented in the header file?
(17 answers)
Closed 5 years ago.
I am creating my own stack and queues by using vectors, lists and dynamic arrays.
I have the following header files for my stack and queue:
miniStack.h
#ifndef MINISTACK_H
#define MINISTACK_H
#include <vector>
#include <list>
using namespace std;
template <typename T>
class miniStackVT {
private:
vector<T> content;
int elementCount;
public:
miniStackVT();
~miniStackVT();
int size() const;
bool IsEmpty() const;
void Push(const T& item);
void PrintStack();
void Pop();
T& TopStack();
};
template <typename T>
class miniStackLT {
private:
list<T> content;
int elementCount;
public:
miniStackLT();
~miniStackLT();
int size() const;
bool IsEmpty() const;
void Push(const T& item);
void PrintStack();
void Pop();
T& TopStack();
};
template <typename T>
class miniStackDA {
private:
T* content;
int elementCount;
void reserve(int n, bool copy);
int arrSize;
public:
miniStackDA();
~miniStackDA();
int size();
bool IsEmpty();
void Push(const T& item);
void PrintStack();
void Pop();
T& TopStack();
};
#endif
miniQueue.h
#ifndef MINIQUEUE_H
#define MINIQUEUE_H
#include <vector>
#include <list>
using namespace std;
template <typename T>
class miniQueueVT {
private:
vector<T> content;
int elementCount;
public:
miniQueueVT();
~miniQueueVT();
void enqueue(const T&);
void dequeue();
T& front();
void PrintQueue() const;
bool IsEmpty();
int size();
};
template <typename T>
class miniQueueLT {
private:
list<T> content;
int elementCount;
public:
miniQueueLT();
~miniQueueLT();
void enqueue(const T&);
void dequeue();
T& front();
void PrintQueue();
bool IsEmpty();
int size();
};
template <typename T>
class miniQueueDA {
private:
T *content;
int elementCount;
void reserve(int n, bool copy);
int arrSize;
public:
miniQueueDA();
~miniQueueDA();
void enqueue(const T&);
void dequeue();
T& front();
void PrintQueue();
bool IsEmpty();
int size();
};
#endif
Here are my .cpp files related to both of my header files:
miniStack.cpp:
#include "miniStack.h"
#include <vector>
#include <list>
#include <iostream>
//VECTOR MEMBER FUNCTIONS
template <typename T>
miniStackVT<T>::miniStackVT() {
elementCount = 0;
content.resize(0);
}
template <typename T>
int miniStackVT<T>::size() const{
return content.size();
}
template <typename T>
bool miniStackVT<T>::IsEmpty() const{
return content.empty();
}
template <typename T>
void miniStackVT<T>::Push(const T& item) {
content.push_back(item);
elementCount++;
}
template <typename T>
void miniStackVT<T>::PrintStack() {
for(int i = elementCount - 1; i >= 0; i--) {
cout << content[i] << " | ";
}
}
template <typename T>
void miniStackVT<T>::Pop() {
content.pop_back();
elementCount--;
}
template <typename T>
T& miniStackVT<T>::TopStack() {
return content.back();
}
//LIST MEMBER FUNCTIONS
template <typename T>
miniStackLT<T>::miniStackLT() {
elementCount = 0;
content.resize(0);
}
template <typename T>
miniStackLT<T>::~miniStackLT() {
}
template <typename T>
int miniStackLT<T>::size() const{
return content.size();
}
template <typename T>
bool miniStackLT<T>::IsEmpty() const{
return content.empty();
}
template <typename T>
void miniStackLT<T>::Push(const T& item) {
content.push_back(item);
elementCount++;
}
template <typename T>
void miniStackLT<T>::PrintStack() {
list<T>::iterator rit;
for (auto rit = content.rbegin(); rit != content.rend(); ++rit) {
cout << *rit << " | ";
}
}
template <typename T>
void miniStackLT<T>::Pop() {
content.pop_back();
elementCount--;
}
//DARRAY DATA MEMBERS
template <typename T>
miniStackDA<T>::miniStackDA() {
arrSize = 50;
content = new T[arrSize];
elementCount = 0;
}
template <typename T>
miniStackDA<T>::~miniStackDA() {
delete[] content;
}
template <typename T>
int miniStackDA<T>::size() {
return elementCount;
}
template <typename T>
bool miniStackDA<T>::IsEmpty() {
if (elementCount == 0)
return true;
else return false;
}
template <typename T>
void miniStackDA<T>::Push(const T& item) {
if (elementCount < arrSize) {
content[elementCount] = item;
elementCount++;
}
else {
reserve(arrSize * 2, true);
content[elementCount] = item;
elementCount++;
}
}
template <typename T>
void miniStackDA<T>::reserve(int n, bool copy) {
T *newArr;
int i;
newArr = new T[n];
if (copy)
for (i = 0; i < elementCount; i++)
newArr[i] = content[i];
if (content != NULL)
delete[] content;
content = newArr;
elementCount = n;
}
template <typename T>
void miniStackDA<T>::PrintStack() {
for (int i = elementCount - 1; i >= 0; i--) {
cout << content[i] << " | ";
}
}
template <typename T>
void miniStackDA<T>::Pop() {
elementCount--;
}
template <typename T>
T& miniStackDA<T>::TopStack() {
return content[elementCount - 1];
}
miniQueue.cpp:
#include "miniQueue.h"
#include "iostream"
#include <vector>
#include <list>
using namespace std;
//START VECTOR MEMBER FUNCTIONS
template <typename T>
miniQueueVT<T>::miniQueueVT() {
elementCount = 0;
content.resize(0);
}
template <typename T>
miniQueueVT<T>::~miniQueueVT() {
}
template <typename T>
void miniQueueVT<T>::enqueue(const T& item) {
content.push_back(item);
elementCount++;
}
template <typename T>
void miniQueueVT<T>::dequeue() {
content.pop_back();
elementCount--;
}
template <typename T>
T& miniQueueVT<T>::front() {
return content.front();
}
template <typename T>
void miniQueueVT<T>::PrintQueue() const {
for (int i = elementCount - 1; i >= 0; i--) {
cout << content[i] << " | ";
}
}
template <typename T>
bool miniQueueVT<T>::IsEmpty() {
return content.empty();
}
template <typename T>
int miniQueueVT<T>::size() {
return elementCount;
}
//START LIST MEMBER FUNCTIONS
template <typename T>
miniQueueLT<T>::miniQueueLT() {
elementCount = 0;
content.resize(0);
}
template <typename T>
miniQueueLT<T>::~miniQueueLT() {
}
template <typename T>
void miniQueueLT<T>::enqueue(const T& item) {
content.push_back(item);
elementCount++;
}
template <typename T>
void miniQueueLT<T>::dequeue() {
content.pop_front();
elementCount--;
}
template <typename T>
T& miniQueueLT<T>::front() {
return content.front();
}
template <typename T>
void miniQueueLT<T>::PrintQueue() {
list<T>::iterator iter;
for (iter = content.begin(); iter != content.end(); iter++) {
cout << *iter << " | ";
}
}
template <typename T>
bool miniQueueLT<T>::IsEmpty() {
return content.empty();
}
template <typename T>
int miniQueueLT<T>::size() {
return content.size();
}
//START DYNAMIC ARRAY MEMBER FUNCTIONS
template <typename T>
miniQueueDA<T>::miniQueueDA() {
arrSize = 50;
content = new T[arrSize];
elementCount = 0;
}
template <typename T>
miniQueueDA<T>::~miniQueueDA() {
}
template <typename T>
void miniQueueDA<T>::enqueue(const T& item) {
if (elementCount < arrSize) {
content[elementCount] = item;
}
else {
reserve(arrSize * 2, true);
content[elementCount] = item;
elementCount++;
}
}
template <typename T>
void miniQueueDA<T>::dequeue() {
elementCount--;
}
template <typename T>
void miniQueueDA<T>::reserve(int n, bool copy) {
T *newArr;
int i;
newArr = new T[n];
if (copy) {
for (i = 0; i < elementCount; i++) {
newArr[i] = content[i];
}
}
if (content != NULL)
delete[] content;
content = newArr;
elementCount = n;
}
template <typename T>
T& miniQueueDA<T>::front() {
return content[0];
}
template <typename T>
bool miniQueueDA<T>::IsEmpty() {
if (elementCount == 0)
return true;
else return false;
}
template <typename T>
int miniQueueDA<T>::size() {
return elementCount;
}
template <typename T>
void miniQueueDA<T>::PrintQueue() {
for (int i = elementCount - 1; i >= 0; i--) {
cout << content[i] << " | ";
}
}
I'm getting the following errors when I go to compile the program:
Error LNK2019 unresolved external symbol "public: __thiscall miniStackVT<int>::~miniStackVT<int>(void)" (??1?$miniStackVT#H##QAE#XZ) referenced in function "void __cdecl StackVTMenu<int>(class miniStackVT<int>)" (??$StackVTMenu#H##YAXV?$miniStackVT#H###Z) Project 2 E:\Project 2\Project 2\Driver.obj 1
Error LNK2019 unresolved external symbol "public: int & __thiscall miniStackLT<int>::TopStack(void)" (?TopStack#?$miniStackLT#H##QAEAAHXZ) referenced in function "void __cdecl StackLTMenu<int>(class miniStackLT<int>)" (??$StackLTMenu#H##YAXV?$miniStackLT#H###Z) Project 2 E:\Project 2\Project 2\Driver.obj 1
Error LNK1120 2 unresolved externals Project 2 E:\Project 2\Debug\Project 2.exe 1
I have tried changing around which files are included in the main and the .h files. Right now i haveminiStack.cpp and miniQueue.cpp included in the main.
Any help would be greatly appreciated.
If you use templates in C++, your header file must contain implementations. If you only implement in your source files the compiler will compile each file and will link later.
But this cannot work in the case of templates since the compiler has to observe the generic type by checking its concrete usage.
Related
i made some code about stack using template.
but right now, stuck with the little error.
i tried many times as i can but don't know what to do.
also, i see the a lot of same error question but my one is seems to be different.
I'm middle of the writing.
so, there is some uncompleted code.
if you see something wrong but not cause the error, ignore it please.
#ifndef STACKINTERFACE_H
#define STACKINTERFACE_H
using namespace std;
template <typename T>
class StackInterface {
public:
StackInterface() {};
virtual ~StackInterface() {};
virtual bool isEmpty() const = 0;
virtual bool isFull() const = 0;
virtual void push(T data) = 0;
virtual void pop() = 0;
virtual T top() const = 0;
};
#include "StackInterface.h"
#include <iostream>
template <typename T>
class Stack : public StackInterface {
private:
T * items;
const static int max = 10;
const static int GROWBY = 5;
size_t arrayCapacity;
size_t numItems;
int top_position;
public:
Stack();
virtual void push(T data);
virtual T top() const;
virtual void pop();
virtual bool isEmpty() const;
virtual bool isFull() const;
size_t getArrayCapacity();
size_t getNumItems();
Stack<T> operator=(const Stack<T>&Other);
~Stack();
Stack(const Stack<T>& other);
};
template <typename T>
Stack<T>::Stack()
{
items = new T[max];
numItems = 0;
top_position = -1;
}
template <typename T>
Stack<T>::~Stack() {
cout << "deleting..." << endl;
delete[] items;
}
template <typename T>
void Stack<T>::push(T data) {
cout << "inserting" << data << endl;
if (numItems < arrayCapacity) {
T[++top_position] = data;
}
numItems++;
}
template <typename T>
void Stack<T>::pop() {
if (isEmpty) {
cout << "The stack is empty. Returned value not reliable.\n";
}
else {
cout << "removing" << top() << endl;
retrun T[top_position--];
}
}
template <typename T>
bool Stack<T>::isEmpty() const
{
if (numItems == 0) {
return true;
}
else {
return false;
}
}
template <typename T>
bool Stack<T>::isFull() const
{
if (numItems == max) {
return true;
}
else {
return false;
}
}
template <typename T>
T Stack<T>::top() const
{
if (!isEmpty()) {
return T[top_position];
}
else {
throw exception;
}
}
template <typename T>
Stack <T> Stack<T>:: operator=(const Stack<T>&Other) {
if (&Other == this) {
return *this;
}
}
template <typename T>
Stack<T>::Stack(const Stack<T>& other) {
items = new items(other.items);
numItems = other.numItems;
top_position = other.top_position;
arrayCapacity = other.arrayCapacity;
}
template <typename T>
size_t Stack<T>::getArrayCapacity() {
return arrayCapacity;
}
template <typename T>
size_t Stack<T>::getNumItems() {
return numItems;
}
int main() {
Stack <int> S1;
system("pause");
return 0;
}
You need to give template arguments to your superclass. Instead of this:
template <typename T>
class Stack : public StackInterface {
Do this:
template <typename T>
class Stack : public StackInterface<T> {
(There's lots of other problems with your code too, but that's how you fix the specific one you asked about.)
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.
This question already has answers here:
std::vector::resize() vs. std::vector::reserve()
(5 answers)
Closed 7 years ago.
I have a class
template <class T>
class General_matrix : public Math_object<T>
{
public:
General_matrix(const size_t m, const size_t n);
~General_matrix();
void init();
void show();
T* operator()(const size_t, const size_t) const;
General_matrix<T> operator*(const General_matrix<T>&);
};
derived from
template <class T>
class Math_object
{
protected:
size_t size_m, size_n;
std::vector <T> field;
public:
Math_object(const size_t m, const size_t n);
virtual ~Math_object() = 0;
virtual void show() = 0;
virtual void init() = 0;
};
Operator * doesn't work properly. The building of auxiliary matrix within an operator is OK, but when it comes to returning it changes only the integer data fields in receiving matrix. It turned out that the problem is with operator= for std::vector. I don't want to override it. Has anyone else faced this problem? Why can't I assign vector to vector of the same size?
template <typename T>
General_matrix<T> General_matrix<T>::operator*(const General_matrix<T> &right_operand)
{
General_matrix<T> aux(this->size_m, right_operand.size_n);
T collector;
for (int i=0; i<this->size_m; i++)
{
for (int j=0; j<right_operand.size_n; j++)
{
collector = 0;
for (int k=0; k<this->size_n; k++)
{
collector += *((*this)(i,k)) * *(right_operand(k,j));
}
*(aux(i,j)) = collector;
}
}
return aux;
}
UPD: Here is a MCVE
There are 2 matrices with values {{0,1,2},{3,4,5}} and {{0,1},{2,3},{4,5}}. The result of their multiplication must be {{10,13},{28,40}} and it is {{0,0},{0,0}}.
#include <iostream>
#include <vector>
using namespace std;
template <class T>
class Math_object
{
protected:
size_t size_m, size_n;
std::vector <T> field;
public:
Math_object(const size_t m, const size_t n);
virtual ~Math_object() = 0;
virtual void show() = 0;
virtual void init() = 0;
};
template <class T>
class General_matrix : public Math_object<T>
{
public:
General_matrix(const size_t m, const size_t n);
~General_matrix();
void init();
void show();
T* operator()(const size_t, const size_t) const;
General_matrix<T> operator*(const General_matrix<T>&);
};
template <typename T>
Math_object<T>::Math_object(const size_t m, const size_t n/*=1*/)
{
cout << "Constructor MO"<<"\n";
size_m=m;
size_n=n;
field.reserve(m*n);
}
template <typename T>
Math_object<T>::~Math_object()
{
cout << "Destructor MO"<<"\n";
vector<T>().swap(this->field);
}
template <typename T>
void Math_object<T>::show() {};
template <typename T>
General_matrix<T>::General_matrix(const size_t m, const size_t n):Math_object<T>(m,n)
{
cout << "Constructor GM"<<"\n";
}
template <typename T>
General_matrix<T>::~General_matrix()
{
cout << "Destructor GM"<<"\n";
}
template <typename T>
void General_matrix<T>::init()
{
cout << "Input matrix"<<"\n";
for (int i=0; i<this->size_m*this->size_n; i++)
this->field[i] = i;
}
template <typename T>
T* General_matrix<T>::operator()(const size_t i, const size_t j) const
{
return const_cast<T*>(&(this->field[i*(this->size_n)+j]));
}
template <typename T>
void General_matrix<T>::show()
{
for (int i=0; i < this->size_m; i++)
{
for (int j=0; j < this->size_n; j++)
{
cout << *((*this)(i,j)) << " ";
}
cout << "\n";
}
}
template <typename T>
General_matrix<T> General_matrix<T>::operator*(const General_matrix<T> &right_operand)
{
General_matrix<T> aux(this->size_m, right_operand.size_n);
T collector;
for (int i=0; i<this->size_m; i++)
{
for (int j=0; j<right_operand.size_n; j++)
{
collector = 0;
for (int k=0; k<this->size_n; k++)
{
collector += *((*this)(i,k)) * *(right_operand(k,j));
}
*(aux(i,j)) = collector;
}
}
return aux;
}
template class Math_object<int>;
template class Math_object<float>;
template class General_matrix<int>;
template class General_matrix<float>;
int main()
{
General_matrix<int> k(2,3);
k.init();
General_matrix<int> p(3,2);
p.init();
General_matrix<int> t(2,2);
t=k*p;
t.show();
return 0;
}
One problem, as mentioned in the comments, is the use of reserve instead of resize in the constructor.
But you have also undefined behavior in operator(). Better implement a const and a non-const version.
I wrote things like that:
template <class T>
MyStack<T>::MyStack()
{
STACK_SIZE=20;
STACK_CURRENT=0;
data=new T[STACK_SIZE];
}
template <class T>
MyStack<T>::MyStack(int thesize)
{
STACK_SIZE=thesize;
STACK_CURRENT=0;
data=new T[STACK_SIZE];
}
template <class T>
MyStack<T>::MyStack(const MyStack& obj)
{
STACK_SIZE=obj.STACK_SIZE;
STACK_CURRENT=obj.STACK_CURRENT;
data=new T[STACK_SIZE];
for(int i=0; i<STACK_CURRENT; i++)
{
data[i]=obj.data[i];
}
}
template <class T>
MyStack<T>::~MyStack()
{
//do nothing
}
//--------------------Get Error below this line-------------------------
template <class T> MyStack& MyStack<T>::operator=(const MyStack& obj)
//--------------------Get Error in this line---------------------------
{
STACK_SIZE=obj.STACK_SIZE;
STACK_CURRENT=obj.STACK_CURRENT;
data=new T*[STACK_SIZE];
for(int i=0; i<STACK_CURRENT; i++)
{
data[i]=obj.data[i];
}
return *this;
}
template <class T>bool MyStack<T>::empty()
{
if(STACK_CURRENT==0) return true;
return false;
}
template <class T> T& MyStack<T>::top()
{
return data[STACK_CURRENT-1];
}
template <class T> void MyStack<T>::push(T& obj)
{
if(STACK_CURRENT>=STACK_SIZE-3)
{
T* tempdata=new T[STACK_SIZE*2];
for(int i=0; i<STACK_CURRENT; i++)
{
tempdata[i]=data[i];
}
delete[] data;
data=new T[STACK_SIZE*2];
for(int i=0; i<STACK_CURRENT; i++)
{
data[i]=tempdata[i];
}
STACK_SIZE+=STACK_SIZE;
}
data[STACK_CURRENT]=obj;
STACK_CURRENT++;
}
template <class T> void MyStack<T>::pop()
{
STACK_CURRENT--;
}
template <class T> int MyStack<T>::size()
{
return STACK_CURRENT;
}
My Header has declaration
template<class T> class MyStack
{
public:
MyStack();
MyStack(int);
MyStack(const MyStack&);
~MyStack();
MyStack& operator=(const MyStack&);
bool empty();
T& top();
void push(T&);
void pop();
int size();
private:
int STACK_SIZE;
int STACK_CURRENT;
T* data;
};
But I can't pass compiling, why? Thanks!
Out-class member function definitions should also mention type argument:
template <class T>
MyStack<T>& MyStack<T>::operator=(const MyStack<T>& obj)
// ^^^ you forgot this ^^^ this too!
Just see these demos:
http://www.ideone.com/BEMYn (error)
http://www.ideone.com/f6Qzu (fixed)
Templated classes must be fully instantiated at compilation time, not linking time. So,
Either you define all functions in the header,
Either you use that class only in the compilation unit that defines the functions (so: MyStack.cpp).
Your erroneous line should be
template <class T> MyStack<T>& MyStack<T>::operator=(const MyStack& obj)
instead of
template <class T> MyStack& MyStack<T>::operator=(const MyStack& obj)
error C2664 : 'void std::vector<_Ty>::push_back(_Ty&&)': cannot convert parameter 1 from 'Node *' to 'Node&&'
please I need help...
I created node.h & heap.h
node.h :
#ifndef __NODE_H_
#define __NODE_H_
#include <string>
#include <iostream>
using namespace std;
template <class T>
class Node {
private:
Node<T>* m_brother;
int m_index;
T m_data;
public:
Node (T data);
~Node ();
int GetIndex () const;
int GetBrother () const;
void SetIndex (const int index);
void SetBrother (const Node<T>* brother);
void SetData (const T& data);
bool operator<(const Node<T>& other) const;
};
template <class T>
Node<T>::Node(T data) {
SetData(data);
}
template <class T>
int Node<T>::GetIndex () const {
return m_index;
}
template <class T>
int Node<T>::GetBrother () const {
return m_brother->GetIndex();
}
template <class T>
void Node<T>::SetData (const T& data) {
m_data = data;
}
template <class T>
void Node<T>::SetBrother(const Node<T>* brother) {
m_brother = brother;
}
template <class T>
void Node<T>::SetIndex(const int index) {
if (index > 0)
m_index = index;
else
cout <<"ERROR: Index Can't be negative number!"<<endl;
}
template <class T>
bool Node<T>:: operator<(const Node<T>& other)const
{
return *(this->GetData()) > *(other.GetData());
}
#endif
heap.h:
#ifndef __HEAP_H_
#define __HEAP_H_
#pragma once
#include <vector>
#include "Node.h"
using namespace std;
template<class T> class Heap {
public:
Heap();
virtual ~Heap();
Node<T> * CreateNode (T data);
bool IsEmpty() const;
Node<T>* RemoveNode(int indexNode);
Node<T>* ExtractMin ();
//void AddToHeap(Node<T>* newNode);
//void Add(int indexNode);
void Insert(Node<T>* newNode);
void DecreaseKey (Node<T>* newNode);
void Exchange (int indexNode1, int indexNode2);
void MinHeapify (int indexNode);
private:
vector<Node<T>> m_heap;
int num;
};
template<class T>
Heap<T>::Heap() {
}
template<class T>
Heap<T>::~Heap() {
}
template<class T>
Node<T>* Heap<T>::CreateNode(T data) {
Node<T*>* node(T);
return node;
}
template<class T>
bool Heap<T>::IsEmpty() const {
return (m_heap.size() == 0);
}
template<class T>
Node<T>* Heap<T>::RemoveNode (int indexNum) {
Node<T>* nodeToRemove=NULL;
if (indexNum > 0 && indexNum < m_heap.size()) {
nodeToRemove = m_heap[indexNum];
m_heap [indexNum] = m_heap [ m_heap.size()-1];
m_heap [m_heap.size()-1] = nodeToRemove;
m_heap.pop_back();
MinHeapify(nodeToRemove->GetIndex());
}
return nodeToRemove;
}
template<class T>
void Heap<T>::Insert(Node<T>* newNode) {
if (m_heap.size() == 0) {
m_heap.push_back(newNode);
}
else
DecreaseKey(newNode);
}
template<class T>
void Heap<T>::DecreaseKey(Node<T>* newNode) {
m_heap.push_back(newNode);
int index = m_heap.size();
while ((index > 0) && (m_heap[(index/2)-1] > m_heap[index-1])) {
Exchange(index,index/2);
index = index/2;
}
}
template<class T>
Node<T>* Heap<T>::ExtractMin () {
Node<T>* minNode;
minNode = m_heap[0];
m_heap[0] = m_heap[m_heap.size()-1];
m_heap.erase(m_heap[m_heap.size()-1]);
MinHeapify (0);
return minNode;
}
template<class T>
void Heap<T>::Exchange (int indexNode1, int indexNode2) {
Node<T>* tmp = m_heap[indexNode1-1];
m_heap[indexNode1-1] = m_heap [indexNode2-1];
m_heap[indexNode2-1] = tmp;
}
template<class T>
void Heap<T>::MinHeapify (int indexNode) {
int leftNode = 2*indexNode;
int rightNode = 2*indexNode+1;
int smallest = indexNode;
if ((leftNode < m_heap.size()-1) && (m_heap[leftNode-1]<m_heap[smallest-1]))
smallest = leftNode;
if ((rightNode < m_heap.size()-1) && (m_heap[rightNode-1]<m_heap[smallest-1]))
smallest = rightNode;
if (smallest != indexNode) {
Exchange (indexNode,smallest);
MinHeapify(smallest);
}
}
#endif;
In the main, I tried to check and it didn't compiled.
int main () {
Node<Vehicle*> a(car1);
Heap<Vehicle*> heap;
Node<Vehicle*>* p = &a;
heap.Insert(p);
return 0;
}
why?
Your Heap<T>::Insert function takes a Node<T*>*.
m_heap is defined as a vector<Node<T>>. You need to insert a Node<T*>, not a Node<T*>*. Heap<T>::Insert should take its parameter by const reference, not by pointer.
Your code uses a lot of pointers unnecessarily; it would be much simpler if you dealt with references and returned things by value rather than tangling with pointers all over the place.