【发布时间】:2021-04-30 07:04:54
【问题描述】:
您好,我想了解显式实例化。所以阅读不同的例子,但在一个例子中有一些疑问。下面给出了示例,我对这个特定示例有两个疑问。
文件 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;
}
我的问题如下:
- 正如您在 Application.cc 文件的第 2 行中看到的那样(作为注释)实例化将出现在其他地方。但是这里我们使用模板函数
int i = compare(a1[0], a2[0]);,我们知道每当我们使用模板函数时,编译器都会实例化它。那么为什么要写那条评论呢?同样在解释中写道
当编译器看到实例化定义(而不是声明)时,它 生成代码。因此,文件 templateBuild.o 将包含以下定义 将实例化与 int 进行比较。
所以我的问题是,如果编译器在看到实例化定义时生成代码,那么 templateBuild.o 将包含用 int 实例化的 compare 的定义,那么我们如何使用 compare(a1[0], a2[0]); 在 Application.cc 文件中使用 compare() ?我的意思是 compare() 模板还没有被实例化,那么在它被实例化之前我们如何使用它呢?
- 我的第二个问题是我应该在哪里写(放置) compare() 模板的内容。例如在头文件或 Application.cc 文件中? compare() 模板的内容是指我在示例中给出的第三个代码块。
【问题讨论】:
-
要使用(调用)一个函数,只需要在相应的翻译单元中出现一个声明。这是(
extern的部分)。该声明指示编译器如何为函数调用生成机器代码,包括传递参数和可选地读取返回值。不需要函数定义来完成这个任务。 -
“我们知道,每当我们使用模板函数时,编译器都会实例化它”——我认为这不是真的。只有看到函数模板的定义,编译器才能实例化函数模板。
-
“代码仅在我们使用模板时生成(而不是在我们定义它时)”这是一本 C++ 11 书中关于函数模板的部分的准确引用。 @DanielLangr
-
请注意来自en.cppreference.com/w/cpp/language/function_template 的以下引用:显式实例化声明(外部模板)防止隐式实例化:代码否则会导致隐式实例化必须使用程序中其他地方提供的显式实例化定义。 现场演示:godbolt.org/z/zxqozWMv7(未生成
f<int>的机器代码)。你的书似乎有点不准确。我猜这是因为在实践中的绝大多数情况下,模板都没有显式地实例化。顺便说一句,那是哪本书? -
这本书是标准书(我假设)“C++ Primer Fifth eidtion”。还有另外两件事写在那里(我觉得矛盾),我在下面引用。引用1:“只要我们从不使用该函数,我们就可以声明一个未定义的函数”。引用 2:“当我们调用函数时,编译器只需要查看函数的声明”。现在 Quote1 和 Quote2 不是相互矛盾吗?不是使用它调用函数吗? @DanielLangr
标签: c++ c++11 templates instantiation explicit-instantiation