函数模板的显式实例化何时发生



嗨,我正在学习显式实例化。因此,阅读不同的例子,但在一个例子中有一些疑问。下面给出了这个例子,我对这个例子有两个疑问。

文件Application.cc包含:

extern template int compare(const int&, const int&);
int i = compare(a1[0], a2[0]);// instantiation will appear elsewhere

文件templateBuild.cc包含:

template int compare(const int&, const int&);

还要注意的是,功能模板比较是:

template<typename T, typename F = less<T>>
int compare(const T &v1, const T &v2, F f = F())
{
if (f(v1,v2)) return -1;
if (f(v2,v1)) return 1;
return 0;
}

我的问题如下:

  1. 正如您在Application.cc文件的第二行中看到的,它被写为(作为注释(实例化将出现在其他地方。但这里我们使用的模板函数是int i = compare(a1[0], a2[0]);,我们知道每当我们使用模板函数时,编译器都会实例化它。那么为什么要在那里写注释呢?解释中还写道

当编译器看到实例化定义(与声明相反(时生成代码。因此,文件templateBuild.o将包含将实例化与int.进行比较

所以我的问题是,如果编译器在看到实例化定义时生成代码,那么templateBuild.o将包含用int实例化的compare的定义,那么我们如何使用compare(a1[0], a2[0]);在Application.cc文件中使用compare((?我的意思是compare((模板还没有实例化,那么在实例化之前我们如何使用它呢?

  1. 我的第二个问题是我应该把compare((模板的内容写(放(在哪里。例如在头文件或Application.cc文件中?compare((模板的内容是指我在示例中给出的第三块代码

我想您正在处理一个案例,其中函数模板在头文件中定义,然后将其包含在两个源文件中。比如(为了简单起见,我去掉了函数参数(:

// compare.h
template<typename T>
int compare(const T &v1, const T &v2)
{
if (v1 < v2) return -1;
if (v2 < v1) return 1;
return 0;
}
// Application.cc
#include <compare.h>
extern template int compare(const int&, const int&);
int i = compare(1, 2); 
// templateBuild.cc
#include <compare.h>
template int compare(const int&, const int&);

现在,可视化这两个源文件的翻译单元的样子是很有用的。

  1. Application.cc的翻译单元:
template<typename T>
int compare(const T &v1, const T &v2)
{
if (v1 < v2) return -1;
if (v2 < v1) return 1;
return 0;
}
extern template int compare(const int&, const int&);
int i = compare(1, 2);

当编译器翻译(编译(此翻译单元时,它只看到显式实例化声明。如果不存在,compare函数调用将导致隐式定义实例化。但由于它在那里,所以避免了这种隐含的实例化,如下所述:

显式实例化声明(外部模板(阻止隐式实例化:否则会导致隐式实例化的代码必须使用程序中其他地方提供的显式实例化定义。

因此,编译器只生成用于调用compare<int>的机器代码,因为它是一个正常(非模板(函数,在翻译单元中有声明,但没有定义。

现场演示:https://godbolt.org/z/1c8jvvcv1

请注意,没有为compare<int>生成机器代码。

  1. templateBuild.cc的翻译单元:
template<typename T>
int compare(const T &v1, const T &v2)
{
if (v1 < v2) return -1;
if (v2 < v1) return 1;
return 0;
}
template int compare(const int&, const int&);

这里,我们有一个显式的实例化定义,它导致函数模板被实例化为compare<int>

现场演示:https://godbolt.org/z/o9vxPvP75

现在,compare<int>的机器代码已经生成。

问题1(

extern template int compare(const int&, const int&);

通过这一行,您可以抑制模板专门化或其成员的隐式实例化。这就是第二行的评论的意思。在当前示例中,显式实例化定义位于templateBuild.cc文件中。你可以在这里找到详细的解释。

问题2(

您必须将模板类定义和声明放在同一个(头(文件中。有关更多详细信息,请查看此页面。

最新更新