关于C++模板和显式声明

lol*_*f37 1 c++ c++11

我花了大约20分钟试图找出为什么我的一些模板方法通过编译而不是链接.

事实证明我需要明确声明我的模板方法.

这是这样的事情:

class Test {
   template<class Source> void Save(Source& obj);
};
Run Code Online (Sandbox Code Playgroud)

然后我会在某处使用它:

Test t;
ClassDerivedFromInterface obj;
t.Save(obj);
Run Code Online (Sandbox Code Playgroud)

它编译得很好,但没有链接.直到我补充:

template void Test::Save(ClassDerivedFromInterface);
Run Code Online (Sandbox Code Playgroud)

我想了解在哪种情况下需要明确的声明.

谢谢

Ker*_* SB 5

简而言之,您需要让实例化模板的翻译单元可以看到模板函数的整个主体(定义).所以当你说t.Save(obj);,那个翻译单元应该可以访问定义Save.通常,您可以通过在头文件本身中包含函数模板的定义来实现此目的.

这样做的原因是模板不是可以编译的普通代码,以后可以随意链接.相反,模板是一种代码生成工具,可以按需生成必要的代码 - 如果愿意,可以自动复制/粘贴,然后搜索和替换.

因此,在Save(ClassDerivedFromInterface&)您编写该行之前,函数的实际可编译代码不会存在.如果只有函数模板的声明是可见的,那么模板只生成具体函数的声明,但不生成它的正文,因此在链接时你会注意到函数丢失了.

回顾一下,模板本身无法编译,只有它们的具体实例可以,并且您必须注意确保在实例化时具体实例始终可用.显式实例化,因为它有效并允许您将一些特定实例打包到一个单独的TU中,但通常难以维护且不可伸缩,并且当您让编译器隐式实例化时,您可以避免显式实例化的其他缺点.因此,通常最好将整个定义打包到头文件中.