Почему я получаю недостающие символы для явной специализации шаблона в статической библиотеке?
Если я скомпилирую следующий код:
//
// g++ static.cpp -o static.o
// ar rcs libstatic.a static.o
//
#include <iostream>
template < typename T >
struct TemplatedClass
{
void Test( T value )
{
std::cout << "Foobar was: " << value << std::endl;
}
};
template struct TemplatedClass < long >;
Я получаю статическую библиотеку, и если я запускаю nm в библиотеке, я получаю следующие результаты:
testcase% nm libstatic.a | c++filt | grep TemplatedClass
0000000000000207 s global constructors keyed to _ZN14TemplatedClassIlE4TestEl
0000000000000300 s global constructors keyed to _ZN14TemplatedClassIlE4TestEl.eh
0000000000000118 T TemplatedClass<long>::Test(long)
00000000000002a0 S __ZN14TemplatedClassIlE4TestEl.eh
Однако, если я скомпилирую следующий код, который такой же, за исключением того, что я добавил явную специализацию шаблонного класса...
//
// g++ static.cpp -o static.o
// ar rcs libstatic.a static.o
//
#include <iostream>
template < typename T >
struct TemplatedClass
{
void Test( T value )
{
std::cout << "Foobar was: " << value << std::endl;
}
};
template <>
struct TemplatedClass < long >
{
void Test( long value )
{
std::cout << "Value was: " << value << std::endl;
}
};
template struct TemplatedClass < long >;
... и повторите команду:
testcase% nm libstatic.a | c++filt| grep TemplatedClass
testcase%
Я не получаю подходящих символов. По какой-то причине компилятор не создает экземпляр шаблона, хотя я явно просил его об этом.
Может кто-нибудь объяснить мне, что здесь происходит?
1 ответ
У вас есть определения функций-членов в определениях классов (шаблонов). Это заставляет функции-члены (шаблоны) быть inline
, Это не имеет большого значения для функции-члена класса шаблона, так как его требования к связыванию в большей степени определяются характером его реализации.
Но во втором примере функция-член void TemplatedClass<long>::Test(long)
не является шаблоном функции и все еще inline
, Поэтому компилятору не требуется ничего с ним делать, если он не используется, и он должен быть определен во всех файлах, где он используется. Поскольку вы утверждаете, что это в файле static.cpp, встроенная функция, вероятно, не то, что вам нужно.
Я думаю, что вы получите больше результатов, чем ожидаете, если вы измените вещи на:
template <>
struct TemplatedClass < long >
{
void Test( long value );
};
void TemplatedClass<long>::Test( long value )
{
std::cout << "Value was: " << value << std::endl;
}
И когда вы определяете явную специализацию, вам, вероятно, также не требуется явная реализация (если это даже законно).