2012-02-19 15 views
6

Quiero utilizar iteradores en el método de clase de plantilla. Aquí está mi código: (testclass.h)Referencias no definidas a funciones miembro de una plantilla de clase

template<typename T, typename container> 
class TestClassX 
{ 
public: 
    void gen(typename container::iterator first); 
}; 

y el archivo testclass.cpp:

template<typename T, typename container> 
void TestClassX<T, container>::gen(typename container::iterator first) 
{ 

} 

Cuando trato de ejecutarlo:

TestClassX<unsigned, std::vector<unsigned> > testx; 
testx.gen(it); 

consigo un error:

Error:undefined reference to `TestClassX<unsigned int, std::vector<unsigned int, std::allocator<unsigned int> > >::gen(__gnu_cxx::__normal_iterator<unsigned int*, std::vector<unsigned int, std::allocator<unsigned int> > >)' 

Yo uso mingw32 4.4

Quiero tener una clase que pueda escribir en diferentes contenedores como std :: vector, std :: list, QVector o QList, todos los que tienen iteradores de estilo STL.

+0

posible duplicado de [Referencia no definida a miembros de plantilla] (http://stackoverflow.com/questions/4100893/undefined-reference-to-template-members) – kennytm

Respuesta

10

Los métodos de clase de plantilla deben estar definidos en el archivo de encabezado. Cuando utiliza una clase de plantilla, el compilador realmente compila una versión de esa clase para los parámetros de plantilla dados. Por lo tanto, es un requisito que el cuerpo de cada método esté disponible cuando se incluye el archivo de encabezado.

se quita archivo de origen e incluyen el cuerpo en testclass.h: métodos de clase

template<typename T, typename container> 
class TestClassX 
{ 
public: 
    void gen(typename container::iterator first) { 

    } 
}; 
+0

Los métodos de clase de plantilla no necesitan definirse en el encabezado archivo. Solo tienes que dejar que el enlazador lo encuentre. De acuerdo con @Thaddeus –

1

plantilla no tienen que ser definidos en los archivos de cabecera. Pero si hace esto, necesita definir una unidad de compilación separada (por ejemplo, templates.cpp) y en la que incluya el archivo de código fuente de la clase de plantilla (por ejemplo, #include "container.cpp" // el .cpp NO el archivo .hpp) , entonces necesita definir las instancias de las plantillas que está utilizando (por ejemplo, clase de plantilla Container;). También necesita definir el objeto para la clase de plantilla (por ejemplo, Enlace). En este caso particular, dado que estamos usando un puntero a este objeto (por ejemplo, Link *, en Containter) simplemente necesitamos 'reenviar declarar' ese objeto.

Aquí está el archivo template.cpp completo. Que compilarías y vincularías con el resto del código.

class Link; 
#include "Container.cpp" // use the source code, not the header 
template class Container<Link*>; 

me gusta usar este método, ya que evita que el compilador de generar instancias de la clase de plantilla automagicamente y le permite saber cuando no puede encontrarlo.

Compilar con gcc usando la opción -fno-implicit-templates.

Al compilar todo se compilará de forma normal, pero luego el recopilador volverá a compilar el archivo templates.cpp para todos los objetos que usen la plantilla.

Cuestiones relacionadas