Possible Duplicate:
Why can templates only be implemented in the header file?
When I put my Stack.cpp into Stack.h it works just fine but, when I separate Stack.h,.cpp files it gives this error.
I have also a main.cpp file which does nothing but includes AlgebraicExpression.h
I use this command to compile : “g++ -o main main.cpp AlgebraicExpression.cpp Stack.cpp”
Undefined symbols for architecture x86_64: "Stack<char>::pop()", referenced from:
infix2postfix(char*) in ccKgncmm.o "Stack<char>::top()", referenced from:
infix2postfix(char*) in ccKgncmm.o "Stack<char>::push(char)", referenced from:
infix2postfix(char*) in ccKgncmm.o "Stack<char>::size()", referenced from:
infix2postfix(char*) in ccKgncmm.o "Stack<char>::Stack()", referenced from:
infix2postfix(char*) in ccKgncmm.o "Stack<double>::pop()", referenced from:
evaluatePostfix(char*) in ccKgncmm.o "Stack<double>::top()", referenced from:
evaluatePostfix(char*) in ccKgncmm.o "Stack<double>::push(double)", referenced from:
evaluatePostfix(char*) in ccKgncmm.o "Stack<double>::Stack()", referenced from:
evaluatePostfix(char*) in ccKgncmm.o ld: symbol(s) not found for architecture x86_64 collect2: ld returned 1 exit status
AlgebraicExpression.h
char* infix2postfix(char *infix);
double evaluatePostfix(char*);
Stack.h
#ifndef STACK_H
#define STACK_H
template <class T>
class Stack
{
public:
Stack();
void pop();
T top();
void push(T val);
int size();
T *values;
int maxSize;
int length;
};
#endif
AlgebraicExpression.cpp
#include "AlgebraicExpression.h"
#include "Stack.h"
using namespace std;
bool isOperator(char c)
{
if(c=='+' || c=='-' ||
c=='*' || c=='/')
return true;
return false;
}
bool isDigit(char c)
{
if(c=='0'||(c>='1'&&c<='9'))
return true;
return false;
}
int compareOperators(char c1,char c2)
{
int v1,v2;
if(!isOperator(c1) || !isOperator(c2))
return -1;
if(c1 == '*' || c1 =='/')v1 = 1;
else v1 = 0;
if(c2 == '*' || c2 == '/')v2 = 1;
else v2 = 0;
return v1-v2;
}
char *infix2postfix(char *infix)
{
int lenIn,lenPost;
for(lenIn=0,lenPost=0;infix[lenIn];++lenIn)
if(infix[lenIn]!='('&&infix[lenIn]!=')')
++lenPost;
char *postfix = new char[lenPost+1];
int i,j;
Stack<char> operations;
for(i=0,j=0;i<lenIn&&j<lenPost;++i)
if(isDigit(infix[i]))
postfix[j++] = infix[i];
else if(isOperator(infix[i]))
{
while(operations.size()&&
compareOperators(operations.top(),infix[i])>-1)
{
postfix[j++] = operations.top();
operations.pop();
}
operations.push(infix[i]);
}
else
{
if(infix[i] == '(')
operations.push(infix[i]);
else if(infix[i] ==')')
{
while(operations.size()&&operations.top()!='(')
{
postfix[j++] = operations.top();
operations.pop();
}
operations.pop();
}
}
while(operations.size())
{
postfix[j++] = operations.top();
operations.pop();
}
postfix[j] = '\0';
return postfix;
}
double evaluatePostfix(char *postfix)
{
Stack<double> result;
for(int i=0;postfix[i];++i)
if(isDigit(postfix[i]))
result.push(postfix[i]-'0');
else
{
double n1,n2,r;
n1 = result.top();
result.pop();
n2 = result.top();
result.pop();
if(postfix[i] == '+')
r = n1+n2;
else if(postfix[i] == '-')
r = n2-n1;
else if(postfix[i] == '*')
r = n1*n2;
else if(postfix[i] == '/')
r = n1/n2;
result.push(r);
}
return result.top();
}
Stack.cpp
#include "Stack.h"
template <class T>
Stack<T>::Stack()
{
maxSize = 100;
length =0;
values = new T[maxSize];
}
template <class T>
T Stack<T>::top()
{
return values[length-1];
}
template <class T>
void Stack<T>::push(T val)
{
if(maxSize==length)
{
T *temp = new T[length*2];
for(int i=0;i<length;++i)
temp[i] = values[i];
values = temp;
maxSize = length*2;
}
values[length++] = val;
}
template <class T>
void Stack<T>::pop()
{
if(length>0)
length--;
}
template <class T>
int Stack<T>::size()
{
return length;
}
With class templates all the definitions need to be in the header itself.
C++ FAQ is a good read.
Basically when a template class is instantiated, it needs to be able to see the entire definition of the class and not just the header.
If you know all the types your class is going to be used with, you could instantiate the template with all those types and then leave the definition in the cpp, as explained in this C++ FAQ entry
As mentioned, this is also covered in Why can templates only be implemented in the header file?