tipos programacion plantillas plantilla las funciones ats c++ linker gnu wrap template-function

programacion - tipos de plantillas en c++



Envoltura de la funciĆ³n de plantilla de C++ (2)

Desde http://linux.die.net/man/1/ld :

--wrap = símbolo
Use una función de envoltura para el símbolo. Cualquier referencia indefinida al símbolo se resolverá a "_ wrap symbol". Cualquier referencia indefinida a "_ símbolo real " se resolverá en símbolo.

Creo que la palabra "indefinido" podría ser la clave aquí. Su símbolo de interés se define ciertamente en bar.o, y la salida nm confirma, ya que los símbolos indefinidos están marcados con "U", no "W".

Actualizar:

Supongo que, por lo tanto, no es posible ajustar las funciones de la plantilla.

Creo que depende más de dónde se define (o instancia) la función, y si esta definición está disponible para el vinculador. En su caso, si definió una función que no sea de plantilla en bar.cpp donde se usa, el resultado sería el mismo. Incluso si definió la función en bar.cpp pero la usó en main.cpp, supongo que sería la misma, aunque no del todo segura (puede intentarlo). Y estoy seguro de que si vinculó bar.cpp y main.cpp en diferentes módulos (una biblioteca compartida y un ejecutable), entonces sería capaz de ajustar una función de bar.cpp utilizada en main.cpp, de nuevo sin importar si es plantilla o no.

Actualización 2: No estaba seguro, pero Mike confirmó con el experimento (ver su propia respuesta y los comentarios allí) que el ajuste funciona si el símbolo no está definido en un archivo objeto, incluso si el archivo objeto está vinculado junto con otro archivo objeto que contiene el definición de símbolo. ¡Estupendo!

Intento ajustar una función de plantilla con la ayuda de la opción de ajuste del enlazador de GNU. El código se ve así:

// f.h template<typename T> void f(T t) { } // bar.h void bar(); // bar.cpp #include "bar.h" #include "f.h" void bar() { f(42); } // test.cpp extern "C" { extern void __real__Z1fIiEvT_(int i); void __wrap__Z1fIiEvT_(int i) { __real__Z1fIiEvT_(i); } } int main() { bar(); }

El código que se muestra arriba está vinculado con el siguiente comando:

g++ -Xlinker -wrap=_Z1fIiEvT_ -o test test.o bar.o

Desafortunadamente, esto no funciona y siempre se llama a la función original f en lugar de mi versión envuelta __wrap__Z1fIiEvT_ . ¿Ves algún error que haya cometido?

Editado: como se recomienda, agrego la salida de nm aquí para asegurarme de que no he cometido ningún error con el nombre destrozado de la función de plantilla:

$ g++ -c bar.cpp -o bar.o $ nm bar.o 0000000000000000 W _Z1fIiEvT_


Los comentarios fueron útiles, pero no creo que sea necesario dividirlo en un ejecutable y una biblioteca (compartida). La clave es tener una declaración directa para la función de plantilla en el origen de la llamada y crear una instancia de la función de plantilla con el tipo utilizado en una unidad de traducción separada. Esto garantiza que f no está definido en bar.o:

//bar.cpp #include "bar.h" template<typename T> void f(T); void bar() { f(42); } //f.h template<typename T> void f(T t) { } //f.cpp #include "f.h" template void f(int); $ nm bar.o U _Z1fIiEvT_ 0000000000000000 T _Z3barv