Привет!
Пробую слинковаьб два файла:
// 1.cc:
template<class T>
void f (T);
// #include"2.cc"
int
main (void)
{
int i = 1;
f (i);
return 0;
}
и второй:
// 2юссЖ
template<class T>
void f(T tt) {};
[etv@pcf004]$ g++ 1.cc 2.cc -o test
/tmp/ccDmwGJP.o: In function `main':
/tmp/ccDmwGJP.o(.text+0x15): undefined reference to `void f<int>(int)'
collect2: ld returned 1 exit status
Если же я включаю определение 2.cc в 1.сс (убираю коментарий перед
#include) и не компилирую 2.сс, то все нормально:
[etv@pcf004]$ g++ 1.cc -o test
[etv@pcf004]$
Почему?
Спасибо!
Так и должно быть.
Темплеты используются для генерации кода по мере надобности.
В 2.cc никто не использует f(). => код не генерится, хотя описание есть
в 1.cc нужен код, но нет описания темплеты а только ее декларация
компилер видит декларацию и думает что код уже есть где то в
другом месте и передает программу на линковку.
в результате линкер выдает :
/tmp/ccDmwGJP.o: In function `main':
/tmp/ccDmwGJP.o(.text+0x15): undefined reference to `void f<int>(int)'
collect2: ld returned 1 exit status
Вывод:
храните темплеты в h - файлах.
Замечательно, а как тогда проектировалась STL? Все STL-контейнеры
_скомпилированы_ в отдельном модуле независимо от меня и давно, а я теперь
могу зосовывать туда любые объекты! Я вчера у Страуструпа нашел про
раздельную комиляцию с шаблонами, там сказано, что в этом случае надо
перед определением шаблона указывать слово 'export'.
Однако, g++ (2.95.4) говорит:
warning: keyword 'export' not implemented and will be ignored
хотя редактор даже подсвечивает 'export' :-)
Но все-таки, стандартные шаблоны компилировались ведь им же! В чем дело?
Спасибо.
Export есть в стандарте, но насколько я знаю еще ни один компилятор
его не реализовал :-(
Все STL-контейнеры генерируются при компиляции. И хранятся в h-файлах.
За счет этого достигается гибкость (и скорость)
при работе с любыми типами,
но теряется время на компиляцию да и выполняемый код может при неразумном
использовании вырасти до неприличных размеров.