Обтекание шаблонной функции C++
Я пытаюсь обернуть шаблонную функцию с помощью опции компоновки GNU. Код выглядит так:
// 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();
}
Показанный выше код связан со следующей командой:
g++ -Xlinker -wrap=_Z1fIiEvT_ -o test test.o bar.o
К сожалению, это не работает, и всегда вызывается оригинальная функция f вместо моей завернутой версии __wrap__Z1fIiEvT_. Ты видишь ошибки, которые я сделал?
Отредактировано: как рекомендовано, я добавляю вывод nm здесь, чтобы убедиться, что я не сделал никаких ошибок с искаженным именем функции шаблона:
$ g++ -c bar.cpp -o bar.o
$ nm bar.o
0000000000000000 W _Z1fIiEvT_
2 ответа
С http://linux.die.net/man/1/ld:
--wrap = символ
Используйте функцию-обертку для символа. Любая неопределенная ссылка на символ будет преобразована в "_wrap symbol". Любая неопределенная ссылка на "_реальный символ" будет преобразована в символ.
Я думаю, что слово "неопределенный" может быть ключевым здесь. Ваш символ интереса определенно определен в bar.o, а nm
выходные данные подтверждают это, поскольку неопределенные символы помечены "U", а не "W".
Обновить:
Я думаю, поэтому не возможно обернуть функции шаблона?
Я думаю, что это зависит больше от того, где функция определена (или создана), и если это определение доступно для компоновщика. В вашем случае, если вы определили не шаблонную функцию в bar.cpp, где она используется, результат будет таким же. Даже если вы определили функцию в bar.cpp, но использовали ее в main.cpp, я думаю, она будет такой же, хотя и не совсем уверенной (вы можете попробовать). И я уверен, что если вы связали bar.cpp и main.cpp в разные модули (совместно используемую библиотеку и исполняемый файл), то вы сможете обернуть функцию из bar.cpp, используемую в main.cpp, опять же, независимо от того, это шаблон или нет.
Обновление 2: я не был уверен, но Майк подтвердил экспериментом (см. Его собственный ответ и комментарии там), что перенос работает, если символ не определен в объектном файле, даже если этот объектный файл связан вместе с другим объектным файлом, содержащим определение символа Большой!
Комментарии были полезны, но я не думаю, что необходимо разделять их на исполняемый файл и (разделяемую) библиотеку. Ключ должен иметь предварительное объявление для функции шаблона в вызывающем источнике и создать экземпляр функции шаблона с используемым типом в отдельной единице перевода. Это гарантирует, что f не определено в 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