3

如果我编译以下代码:

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

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

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

4

1 回答 1

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;
}

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

于 2010-10-21T16:46:29.583 回答