Оптимизация компилятора устраняет неявную реализацию шаблона, приводящую к ошибкам компоновщика - PullRequest
1 голос
/ 31 мая 2019

Я пытаюсь переместить определение функции шаблона из файла заголовка.

Я знаю, что для этого я могу явно создать экземпляр этой функции со всеми типами, которые я хочу видеть снаружи (во время связывания). Однако внутри исходного файла (вместе с определением функции) у меня есть использование (неявная реализация) функции со всеми необходимыми типами. Этот код работает и прекрасно связывается с -O0, но не связывается с -O2.

Мне удалось минимизировать проблему:

// a.cpp
#include "b.h"

int main() {
  bar<int>();
  return 0;
}
// b.h
template <class T> void bar();
// b.cpp
#include "b.h"

template <class T> void bar() {}

void foo() { bar<int>(); }

Если я скомпилирую b.cpp с -O0 и с -O2, я получу другой набор символов, доступный в объектном файле:

> clang++ -c b.cpp -o b.o && nm -A b.o

b.o:0000000000000000 W _Z3barIiEvv
b.o:0000000000000000 T _Z3foov

> clang++ -c b.cpp -O2 -o b.o && nm -A b.o

b.o:0000000000000000 T _Z3foov

То же самое происходит и с gcc .

Похоже, что компиляторы встраивают инстанцированную функцию и удаляют ее, так как они не видят ее другого использования.

Можно ли предотвратить неявное создание экземпляров шаблонных функций без явного их создания?

Заранее спасибо!

UPD : этот ответ на связанный вопрос (как указано @ Jarod42) также отвечает на мой вопрос: согласно стандарту это невозможно сделать без явного конкретизации.

1 Ответ

0 голосов
/ 31 мая 2019

Из того, что я могу получить из ваших фрагментов кода, вам не хватает фактического определения функции вашего шаблона.Все, что вы делаете, это вызываете его.

Вам просто нужно определить функцию шаблона.Это может выглядеть так (скорее всего, в вашем случае это b.cpp:

tempate <class T>
void bar()
{
  // My function
  std::cout << "bar()" << std::endl;
}
...