微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

您好,我正在学习显式实例化。所以阅读不同的例子,但在一个例子中会有一些疑问。下面给出了这个例子,我对这个特定的例子有两个疑问。

文件 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 文件的第 2 行中看到的那样(作为注释),实例化将出现在别处。但是这里我们使用模板函数作为 int i = compare(a1[0],a2[0]); 并且我们知道无论何时我们使用模板函数编译器都会实例化它。那么为什么要在那里写这条评论呢?在解释中还写道

当编译器看到实例化定义(而不是声明)时,它 生成代码。因此,文件 templateBuild.o 将包含以下定义 与 int 实例化比较。

所以我的问题是,如果编译器在看到实例化定义时生成代码,因此 templateBuild.o 将包含用 int 实例化的 compare 的定义,那么我们如何在 Application.cc 文件中使用 compare() 使用 {{1 }}?我的意思是 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&,2);

当编译器翻译(编译)这个翻译单元时,它只会看到显式实例化声明。如果它不存在,compare 函数调用将导致隐式定义实例化。但是因为它在那里,所以避免了这种隐式实例化,如here

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

因此,编译器只生成用于调用 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 文件中。 您可以找到详细说明here

问题 2)

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。