为什么静态库中的显式模板专业化缺少符号?

发布于 2024-09-28 15:21:43 字数 1474 浏览 5 评论 0原文

如果我编译以下代码:

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

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

有人可以向我解释一下这是怎么回事吗?

If I compile the following code:

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

I get a static library and if I run nm on the library I get the following results:

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

If however I compile the following code, which is the same except that I have added an explicit specialization of the templated class...

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

... and rerun the same command:

testcase% nm libstatic.a | c++filt| grep TemplatedClass
testcase% 

I get no matching symbols. For some reason the compiler does not instantiate the template even though I explicitly asked it to.

Can someone explain to me what is going on here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

金橙橙 2024-10-05 15:21:43

您在类(模板)定义中有成员函数定义。这会导致成员函数(模板)内联。这对于模板类的成员函数来说并不重要,因为它的链接要求更多地由其实例化的性质决定。

但在第二个示例中,成员函数 void TemplatedClass::Test(long) 不是函数模板,并且仍然是内联。因此,除非使用它,否则编译器不需要对它执行任何操作,并且必须在使用它的所有文件中定义它。由于您声称这是在 static.cpp 文件中,因此内联函数可能不是您想要的。

您会得到更像您所期望的结果。

template <>
struct TemplatedClass < long >
{
  void Test( long value );
};

void TemplatedClass<long>::Test( long value )
{
  std::cout << "Value was: " << value << std::endl;
}

我认为如果将事情更改为:并且当您定义显式专业化时,您可能不需要显式实例化(如果这甚至是合法的),

You have member function definitions within class (template) definitions. This causes the member functions (templates) to be inline. That doesn't matter so much for the member function of the template class, since its linkage requirements are determined more by the nature of its instantiation(s).

But in the second example, the member function void TemplatedClass<long>::Test(long) is not a function template and is still inline. So the compiler is not required to do anything with it unless it's used, and it must be defined in all files where it's used. Since you claim this is in a static.cpp file, an inline function is probably not what you want.

I think you'll get results more like you're expecting if you change things to:

template <>
struct TemplatedClass < long >
{
  void Test( long value );
};

void TemplatedClass<long>::Test( long value )
{
  std::cout << "Value was: " << value << std::endl;
}

And when you define an explicit specialization, you probably don't also need an explicit instantiation (if that's even legal).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文