模板的编译是如何工作的?

2022-06-21 00:00:00 templates c++

我正在阅读一本关于模板如何工作的书,我无法理解有关模板的说明。

上面写着

当编译器看到模板定义时,它不会生成代码。它仅在我们实例化模板的特定实例时生成代码。只有在使用模板时(而不是在定义模板时)才会生成代码,这一事实会影响我们如何组织源代码以及在检测到错误时……要生成实例化,编译器需要具有定义函数模板或类模板成员函数的代码。因此,与非模板代码不同,模板的标头通常包括定义和声明。

生成代码到底是什么意思?我不明白编译函数模板或类模板与常规函数或类有什么不同。


解决方案

编译器为模板类实例化中给定的特定类型生成代码。

如果您将模板类声明为

template<typename T>
class Foo
{
public:
     T& bar()
     {
         return subject; 
     }
private:
     T subject;
};

例如,一旦您有了以下实例化

Foo<int> fooInt;
Foo<double> fooDouble;

这些将有效地生成与您定义的类相同的可链接代码

class FooInt
{
public:
     int& bar()
     {
         return subject; 
     }
private:
     int subject;
}

class FooDouble
{
public:
     double& bar()
     {
         return subject; 
     }
private:
     double subject;
}

并实例化变量,如

FooInt fooInt;
FooDouble fooDouble;
关于模板definitions(不要与declarations混淆,不管是什么模板)需要与头文件(包括)一起看到这一点,原因非常清楚: 如果没有看到definition,编译器无法生成此代码。但它可以引用最先出现在链接阶段的匹配实例化。

非模板成员函数具有什么使其能够 在标头外部定义,而模板函数不定义 有吗?

非模板类/成员/函数的声明为链接器提供了预定义的入口点。该定义可以从编译的目标文件(==.cpp==compilation unit)中看到的单个实现中提取。 相反,模板化类/成员/函数的声明可以从给定相同或不同模板参数的任意编译单元实例化。这些模板参数的定义需要至少查看一次。它可以是通用的,也可以是专用的。

请注意,您可以为特定类型专门化模板实现(包括在标题中或在特定的compilation unit中)。 如果您希望在compilation units之一中为模板类提供专门化,并且不将模板类与专门化以外的类型一起使用,那么这也足以将它们链接在一起。

我希望此示例有助于澄清编译器所做的努力和区别。

相关文章