Hopefully someone who’s better at C++ than me can help me figure this out.
I’ve found something pretty confusing. Today I wanted to experiment with implementing template classes on Particle. I keep running into a linking error if I include Particle.h. If I don’t include Particle.h it links fine.
I’m building for the photon on 1.4.0 in Workbench.
../../../build/target/user/platform-6-m/template-test//libuser.a(template-test.o): In function `setup':
/Users/nrobinson/projects/template-test//src/template-test.cpp:13: undefined reference to `Stack<int>::Stack(int)'
collect2: error: ld returned 1 exit status
make[2]: *** [/Users/nrobinson/projects/template-test/target/1.4.0/photon/template-test.elf] Error 1
make[1]: *** [modules/photon/user-part] Error 2
make: *** [compile-user] Error 2
The terminal process terminated with exit code: 2
template-test.cpp
// Linking will fail if Particle.h is included
// #include "Particle.h"
#include "Stack.h"
// The following also fails to link
// Stack<double> doubleStack(100);
Stack<int> *intStack;
void setup()
{
intStack = new Stack<int>(100);
}
void loop()
{
}
Stack.h
// Adapted from:
// http://users.cis.fiu.edu/~weiss/Deltoid/vcstl/templates
#ifndef STACK_H
#define STACK_H
template <class T>
class Stack
{
public:
Stack(int = 10) ;
~Stack() { delete [] stackPtr ; }
int push(const T&);
int pop(T&) ; // pop an element off the stack
int isEmpty()const { return top == -1 ; }
int isFull() const { return top == size - 1 ; }
private:
int size ; // Number of elements on Stack
int top ;
T* stackPtr ;
} ;
#endif // STACK_H
Stack.cpp
#include "Stack.h"
//constructor with the default size 10
template <class T>
Stack<T>::Stack(int s)
{
size = s > 0 && s < 1000 ? s : 10 ;
top = -1 ; // initialize stack
stackPtr = new T[size] ;
}
// push an element onto the Stack
template <class T>
int Stack<T>::push(const T& item)
{
if (!isFull())
{
stackPtr[++top] = item ;
return 1 ; // push successful
}
return 0 ; // push unsuccessful
}
// pop an element off the Stack
template <class T>
int Stack<T>::pop(T& popValue)
{
if (!isEmpty())
{
popValue = stackPtr[top--] ;
return 1 ; // pop successful
}
return 0 ; // pop unsuccessful
}