为什么我在静态库中获得显式模板特化的缺失符号?

jkp*_*jkp 2 c++ templates g++ explicit-specialization

如果我编译以下代码:

//
// 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 >;
Run Code Online (Sandbox Code Playgroud)

我得到一个静态库,如果我在库上运行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
Run Code Online (Sandbox Code Playgroud)

但是,如果我编译以下代码,除了我添加了模板化类的显式特化之外,它是相同的...

//
// 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 >;
Run Code Online (Sandbox Code Playgroud)

...并重新运行相同的命令:

testcase% nm libstatic.a | c++filt| grep TemplatedClass
testcase% 
Run Code Online (Sandbox Code Playgroud)

我没有匹配的符号.由于某种原因,即使我明确要求,编译器也不会实例化模板.

有人可以向我解释这里发生了什么吗?

asc*_*ler 6

您在类(模板)定义中有成员函数定义.这会导致成员函数(模板)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;
}
Run Code Online (Sandbox Code Playgroud)

当您定义显式特化时,您可能不需要显式实例化(如果这甚至是合法的).