Обтекание шаблонной функции C ++ - PullRequest
6 голосов
/ 17 января 2012

Я пытаюсь обернуть шаблонную функцию с помощью опции компоновщика GNU wrap . Код выглядит так:

// 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 ]

1 голос
/ 24 января 2012

Комментарии были полезны, но я не думаю, что необходимо разделять их на исполняемый файл и (разделяемую) библиотеку.Ключ должен иметь предварительное объявление для функции шаблона в вызывающем источнике и создать экземпляр функции шаблона с используемым типом в отдельной единице перевода.Это гарантирует, что 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
1 голос
/ 18 января 2012

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

- упаковка = символ
Используйте функцию-обертку для символа. Любая неопределенная ссылка на символ будет преобразована в «_ wrap symbol». Любая неопределенная ссылка на «_ real symbol» будет преобразована в символ.

Я думаю, что слово «неопределенный» может быть ключевым здесь. Ваш интересующий символ определенно определен в bar.o, и вывод nm подтверждает это, так как неопределенные символы отмечены «U», а не «W».


Обновление:

Полагаю, поэтому невозможно обернуть функции шаблона?

Я думаю, это зависит больше от того, где функция определена (или создана), и доступно ли это определение для компоновщика. В вашем случае, если вы определили не шаблонную функцию в bar.cpp, где она используется, результат будет таким же. Даже если вы определили функцию в bar.cpp, но использовали ее в main.cpp, я думаю, что она будет такой же, хотя и не совсем уверенной (вы можете попробовать). И я уверен, что если вы связали bar.cpp и main.cpp в разные модули (совместно используемую библиотеку и исполняемый файл), то вы сможете обернуть функцию из bar.cpp, используемую в main.cpp, опять же, независимо от того, шаблон это или нет.


Обновление 2: я не был уверен, но Майк подтвердил экспериментом (см. Его собственный ответ и комментарии там), что перенос работает, если символ не определен в объектном файле, даже если этот объектный файл связан вместе с другим объектом файл, содержащий определение символа. Отлично!

...