Linking problems with template class

argon
photon
Tags: #<Tag:0x00007fe21f537498> #<Tag:0x00007fe21f537330>

#1

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
}

#2

Put your implementation of the templated functions into the header file and see whether this works

The answer to this question provides the rationale behand that


#3

That fixed all the problems. Thanks.