简体   繁体   English

是否在C ++中的不同编译单元中多次编译模板类?

[英]Is a template class compiled more than once in different compilation units in C++?

Let's say I have the following code: 假设我有以下代码:

// templateClass.h
#ifndef TEMPLATE_CLASS_H
#define TEMPLATE_CLASS_H

template <typename T>
class tClass
{
public:
  tClass();
};

#endif

// templateClassDef.inl
#ifndef TEMPLATE_CLASS_DEF_INL
#define TEMPLATE_CLASS_DEF_INL

template <typename T>
tClass<T>::tClass()
{
}

#endif

// normalClass.h
#include "templateClass.h"

class normal
{
public:
  normal();
};

// normalClass.cpp
#include "normalClass.h"
#include "templateClassDef.inl"

normal::normal()
{
  tClass<int> a;
}

// main.cpp
#include "templateClass.h"
#include "templateClassDef.inl"

#include "normalClass.h"

int main()
{
  tClass<int> a;
  normal b;

  return 0;
}

Note that the inl file is NOT being included in the header as it normally is, but is instead included in the source files (I am aware that is not the standard way... this is just an example). 请注意, inl文件不像通常那样包含在标头中,而是包含在源文件中(我知道这不是标准方式......这只是一个例子)。 Notice that normalcClass.cpp is instantiating tClass<int> and so is main.cpp . 请注意, normalcClass.cpp正在实例化tClass<int> ,因此是main.cpp

I am curious as to whether the compiler has to construct the instantiation from the template class every time it encounters an explicit instantiation, considering it is the same type (ie tClass<int> ) even though both instantiations occur in separate translation units ( normalClass.cpp and main.cpp )? 我很好奇编译器是否必须在每次遇到显式实例化时都从模板类构造实例化,考虑到它是相同的类型(即tClass<int> ), 即使两个实例都发生在单独的转换单元中( normalClass.cppmain.cpp )? Also, will this increase in compile time (If the answer to the previous question is yes it will instantiate it again then this should also be yes )? 此外,这将增加编译时间(如果上一个问题的答案是肯定的,它将再次实例化,那么这也应该是肯定的 )?

Basically, templates are instantiated per compile unit, which increases compile time. 基本上,模板是按编译单元实例化的,这会增加编译时间。 There are some extensions and features in the new C++ standard to handle this issue, like explicit instantiation and externalization. 新的C ++标准中有一些扩展和功能可以处理这个问题,比如显式实例化和外部化。 See this doc for some explanations and optimization techniques: 请参阅此文档以获取一些解释和优化技巧:

http://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html http://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html

通常,是的,模板类通常在每次编译器遇到时编译。

How the compiler implements the template instantiation mechanism is up to the compiler. 编译器如何实现模板实例化机制取决于编译器。 Practically, the needed and visible function template definitions are created when it is used in a translation unit. 实际上,在翻译单元中使用时,会创建所需的和可见的函数模板定义。 This can create quite a bit of unnecessary work. 这可能会造成相当多的不必要的工作。 For example, every time you use IOstreams in a translation unit all the correspondung functions from the stream and locale classes are instantiated. 例如,每次在转换单元中使用IOstream时,都会实例化流和语言环境类中的所有相应函数。 ... always with the same two types! ......总是有两种类型!

Depending on what the template is for it may be viable to put the implementation into a source file rather than into a header and explicitly instantiate the template in the source. 根据模板的用途,将实现放入源文件而不是标头并在源中显式实例化模板可能是可行的。 When there are lots of different instantiations being used this isn't viable. 当使用大量不同的实例时,这是不可行的。 In this case it may be reasonable to to predefine commonly use instantiations. 在这种情况下,预定义常用实例化可能是合理的。 For this you can declare instantiations to be extern in C++2011. 为此,您可以在C ++ 2011中将实例化声明为extern。 Of course, you then need to explicitly instantiate the corresponding functions or classes somewhere. 当然,您需要在某处显式实例化相应的函数或类。

Yes, compilation units are compiled independently from each other. 是的,编译单元是相互独立编译的。

However, many toolchains support pre-compiled headers which circumvent this, and allow the compiler to reuse already processed code in another compilation unit. 但是,许多工具链支持预先编译的头文件,以避免这种情况,并允许编译器在另一个编译单元中重用已经处理的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM