Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Почему я получаю отсутствующие символы для явной специализации шаблона в статической библиотеке?

Автор вопроса: jkpОтветов: 1

Если я скомпилирую следующий код:

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

Я не получаю совпадающих символов. По какой-то причине компилятор не создает экземпляр шаблона, хотя я явно просил его об этом.

Может кто-нибудь объяснить мне, что здесь происходит?

c++templatesg++explicit-specialization

Ответы

Ответ 1 · рейтинг 6 · aschepler

У вас есть определения функций-членов в определениях классов (шаблонов). Это приводит к тому, что функции-члены (шаблоны) становятся 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;
}

И когда вы определяете явную специализацию, вам, вероятно, также не требуется явное создание экземпляра (если это вообще законно).

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы