Clang ++ hace que el vinculador falle en las clases de plantilla (pero funciona con g ++)
Tengo un programa que funciona bien con GCC, pero compilarlo con Clang hace que el enlazador falle.
Creo que mi problema es con las clases de plantilla, así que implementé este pequeño ejemplo.
test.cpp
:
#include "Point.h"
int main()
{
Point<int> p1;
Point<int> p2{ 3, 6 };
}
Point.h
:
#ifndef POINT_H
#define POINT_H
template<typename T>
class Point {
T x, y;
public:
Point();
Point(T, T);
};
template class Point<int>;
template class Point<float>;
#endif
Point.cpp
:
#include "Point.h"
template<typename T>
Point<T>::Point()
: x{0}, y{0}
{}
template<typename T>
Point<T>::Point(T t_x, T t_y)
: x{t_x}, y{t_y}
{}
Cuando lo construyo g++ Point.cpp test.cpp
, funciona sin problemas.
Pero con Clang, da los siguientes errores:
$ clang++ Point.cpp test.cpp
/usr/bin/ld: /tmp/test-8ab886.o: in function `main':
test.cpp:(.text+0x1a): undefined reference to `Point<int>::Point()'
/usr/bin/ld: test.cpp:(.text+0x2d): undefined reference to `Point<int>::Point(int, int)'
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)
O, usando lld:
$ clang++ -fuse-ld=lld Point.cpp test.cpp
ld.lld: error: undefined symbol: Point<int>::Point()
>>> referenced by test.cpp
>>> /tmp/test-f95759.o:(main)
ld.lld: error: undefined symbol: Point<int>::Point(int, int)
>>> referenced by test.cpp
>>> /tmp/test-f95759.o:(main)
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)
Supongo que mis instancias explícitas en Point.h
no son lo suficientemente buenas para Clang, pero no puedo imaginar lo que quiere.
Respuestas
Su instanciación explícita debe ser donde las definiciones sean visibles, por lo que al final de Points.cpp
Desde class_template # Explicit_instantiation :
Una definición de instanciación explícita fuerza la instanciación de la clase, estructura o unión a la que se refieren. Puede aparecer en el programa en cualquier lugar después de la definición de la plantilla, y para una lista de argumentos determinada, solo se permite que aparezca una vez en todo el programa, no se requiere diagnóstico.