C++如何链接模板实例

2021-12-13 00:00:00 hyperlink templates c++

如果我在包含两个不同翻译单元的头文件中定义一个函数(可能是一个类成员函数但未内联),我会收到链接错误,因为该函数是多重定义的.模板并非如此,因为在编译器解析模板化类型的对象声明之前,它们不是可编译的类型.这让我意识到我不知道编译的模板代码在哪里以及它是如何链接的,因为 C++ 不只是创建代码的多个副本来定义 SomeTemplateClass.任何信息,将不胜感激.谢谢!

If I define a function (maybe a class member function but not inlined) in a header file that is included by two different translation units I get a link error since that function is multiply defined. Not so with templates since they are not compilable types until the compiler resolves a declaration of an object of a templatized type. This made me realize I don't know where compiled template code resides and how it is linked since C++ does not just create multiple copies of code to define SomeTemplateClass. Any info would be appreciated. Thanks!

推荐答案

C++编译器使用了3种实现方案:

There are 3 implementation schemes used by C++ compilers:

  • 贪婪实例化,编译器在每个使用它的编译单元中生成一个实例化,然后链接器丢弃除其中一个之外的所有实例化(这不仅仅是代码大小优化,它是必需的,以便函数地址、static 变量等都是唯一的).这是最常见的模型.

  • greedy instantiation, where the compiler generates an instantiation in each compilation unit that uses it, then the linker throws away all but one of them (this is not just a code-size optimization, it's required so that function addresses, static variables, and the like are unique). This is the most common model.

查询实例化,其中编译器有一个已经完成的实例化数据库.当需要实例化时,会检查并更新数据库.我知道的唯一使用它的编译器是 Sun 的,默认情况下不再使用它.

queried instantiation, where the compiler has a database of instantiations already done. When an instantiation is needed, the DB is checked and updated. The only compiler I know which uses this is Sun's, and it isn't used by default anymore.

迭代实例化,其中实例化由链接器进行(直接或通过将它们分配给编译单元,然后重新编译).这是 CFront 使用的模型 - 即历史上它是第一个使用的模型 - 以及使用 EDG 前端的编译器(与 CFront 相比进行了一些优化).

iterated instantiation, where the instantiations are made by the linker (either directly or by assigning them to a compilation unit, which will then be recompiled). This is the model used by CFront -- i.e. historically it was the first one used -- and also by compilers using the EDG front-end (with some optimisations compared to CFront).

(参见 C++ 模板,David Vandevoorde 和 Nicolai Josuttis 的完整指南.另一个在线参考是 http://www.bourguet.org/v2/cpplang/export.pdf,更关注编译模型,但仍然有实例化机制的描述).

(See C++ Templates, The Complete Guide by David Vandevoorde and Nicolai Josuttis. Another online reference is http://www.bourguet.org/v2/cpplang/export.pdf, which is more concerned about the compilation model but still has descriptions of the instantiation mechanisms).

相关文章