Voy a suponer que la función main se encuentra en un archivo main.cpp, hasta aquí tienes 3 archivos que serán traducidos a código objeto por el compilador; esto es: main.cpp, Board.cpp y BoardBase.cpp. Pues bien, al momento de compilar main.cpp el compilador trata de crear una instancia para BoardBase<int>::print(), pero solo logra ver la declaración del template y no su definición puesto que se encuentra en otra unidad de código (BoardBase.cpp), por lo que no se genera dicha instancia. Entonces, cuando el enlazador(linker) busca la definición de la función en las diferentes unidades de código objeto tampoco la encuentra, porque solo se tiene la definición del template en BoardBase.cpp y no hay ningún código que le indique al compilador que haya que crear una instancia de BoardBase<int>::print() , luego entonces no la encuentra y se muestra el error. Recuerda que tu defines los templates y el compilador se encarga de crear las instancias necesarias. La buena, es que también podemos crear instancias de forma explícita.
Para este caso tienes 2 soluciones:
1. Te basta con mover la definición a su archivo de cabecera (olvidate de BoardBase.cpp), es común que tengas tanto declaraciones como definiciones de templates en los archivos de cabecera.
BoardBase.h
Código C++:
Ver original#ifndef BOARDBASE_H
#define BOARDBASE_H
#include <iostream>
template<class T>
class BoardBase
{
T value;
public:
void print();
};
template<class T> void BoardBase<T>::print()
{
std::cout << "Probando print" << std::endl;
}
#endif // BOARDBASE_H
2. Crear una instancia para BoardBase<int>::print() de forma explícita en BoardBase.cpp
BoardBase.cpp
Código C++:
Ver original#include "BoardBase.h"
#include <iostream>
using namespace std;
template<class T> void BoardBase<T>::print()
{
cout << "Probando print" << endl;
}
template void BoardBase<int>::print();
// o tambien puedes usar: template BoardBase<int>;
Observa la declaración seguida de la palabra "template". De hecho puedes crear una instancia para la clase completa y no solo para un método, pero podrías estar creando instancias de métodos que resulten innecesarias, pros y contras, pero bueno.
Por último, ten cuidado con el namespace std para cout y endl, y la otra utiliza las directivas #ifndef y #define del preprocesador para evitar inclusiones múltiples de tus archivos de cabecera.