1

假设我有一个在中声明和定义的非类型模板函数f(int)(参数<int dim>)。在我进一步添加了一个特化 for ,然后我显式地实例化了and的模板函数。template.htemplate.cpptemplate.cppdim = 2dim = 1dim = 2

文件编译正常,但在链接过程中出现错误:

Undefined symbols for architecture x86_64:
  "void f<2>(int)", referenced from:
      _main in main-2AW7ED.o
ld: symbol(s) not found for architecture x86_64

但是,如果我inline从模板专业化中删除关键字(见下面的标记),整个事情就会按预期工作。所以我的问题来了:

inline当它适用于基本模板时,为什么它不适用于专用模板,而其他所有东西都可以编译并正常工作?

主文件

#include <iostream>
#include "template.h"

using namespace std;

int main(int, char** )
{
  f<1>(456); 
  f<2>(789);
}

模板.h

template <int dim> void f(int src);

模板.cpp

#include <iostream>
#include "template.h"

using namespace std;

template <int dim> inline
void f(int src)
{
  cout << "src = " << src << endl;
  cout << "dim (template) = " << dim << endl;
}

template <> inline // <== if I remove this "inline", everything works as expected
void f<2>(int src)
{
  cout << "src = " << src << endl;
  cout << "dim (fixed) = " << 2 << endl;
}

template void f<1>(int);
template void f<2>(int);

PS:我用g++和clang++的命令clang++ -o tmpl template.cpp main.cpp编译。

4

1 回答 1

3

如果函数被声明inline,编译器必须不生成非内联版本,除非请求指向函数的指针,或者它决定在某些调用站点最好不要内联它(编译器不需要总是内联甚至如果你声明inline)。

现在要内联函数,编译器需要在编译调用站点时查看函数的定义。但是您在 a 中定义了函数.cpp并试图从不同的.cpp. 因此编译器不到定义并尝试调用非内联版本。但它没有生成,因为您告诉编译器内联函数并且它没有看到需要非内联版本的任何用途,所以它没有生成它。如果您不声明inline,则始终会生成默认值,extern并且始终会生成非内联版本。并且您声明了要生成的显式实例,因此将是。

正如编译器不必内联一样,它也不必生成 extern 版本。我怀疑存在一些随机差异导致编译器在一种情况下生成非内联实例,而不是在另一种情况下生成。在任何一种情况下,如果您声明内联的内容,则必须在标头中定义它,除非您实际上只是从一个源中使用它(例如,有时私有方法可以内联并在实现中定义,因为您只在那个源中使用它们文件)。

于 2013-02-07T10:08:48.243 回答