模板实例化对编译持续时间的影响 [英] Template instantiation effect on compile duration

查看:207
本文介绍了模板实例化对编译持续时间的影响的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编写模板类,我们必须内联通常在.h文件中的方法主体(除非在.cpp文件中实例化它们). 我们知道修改 inlined 方法需要重新编译包含它们的单元.这样会使编译时间变长. 实现模板类的另一种技术是在.cpp文件中实例化它.

Writing template classes we have to inline the method bodies usually in .h files (unless instantiating them in .cpp files). We know modifying an inlined method requires recompiling the units which included them. It'll make compiling long. Another technique to implement a template class is instantiating it in a .cpp file.

文件Test.h:

template <typename T>
class Test
{
public:
    T data;
    void func();
};

文件Test.cpp:

template <typename T>
void Test<T>::func()
{
}

template class Test<float>; // explicit instantiation

好吧.对于在func()上进行任何修改后使用Test<float>的人员,这种技术是否有效地减少了编译时间?

Well. Is this technique effective to reduce compilation time for who uses Test<float> after any modification on func()?

推荐答案

由于成员函数的定义都在cpp中,因此对其他翻译单元不可用,因此不会隐式实例化这些函数,因此成本也很高代码的编译仅限于单个cpp.

Since the definitions of the member functions are all inside the cpp and thus not available to other translation units, the functions won't be implicitly instantiated and thus the cost of compiling the code is limited to the single cpp.

该方法的问题是您将模板的使用限制为提供手动实例化的类型.外部用户无法为其他类型实例化它,如果必须这样做,则需要记住手动针对要使用的每种类型进行专门化处理.

The problem with that approach is that you are limiting the use of your template to the type (or types) for which you provide the manual instantiations. External users cannot instantiate it for other types, if you have to do it, you need to remember to manually specialize for each type you want to use.

有一种替代方法,其成本略高(不多),但它是通用的,比幼稚的方法编译速度更快.您可以在标头中提供模板定义,但指示编译器不要针对一组常见类型隐式实例化它,然后在单个翻译单元中为其提供手动实例化:

There is an alternative, with slightly more cost (not much), but that is generic and faster to compile than the naïve approach. You can provide the template definitions in the header, but instruct the compiler not to implicitly instantiate it for a set of common types, then provide manual instantiations for it in a single translation unit:

// .h
#ifndef TEST_H
#define TEST_H
template <typename T>
class Test
{
public:
    T data;
    void func() { ... }  // definition here
};
extern template class Test<float>;   // Declare explicit instantiation for float
extern template class Test<int>;     //                                for int
#endif /* TEST_H */

// cpp
#include "test.h"
template class Test<float>;          // explicit instantiation
template class Test<int>;

在这种方法中,对于用户可能要使用的任何类型的实例化,模板都是可见的.但是,您明确地告诉编译器不要为提供专业化的类型的已知子集进行工作.如果用户想要Test<std::string>,则编译器将隐式实例化它,而该翻译单元将为此付出代价.对于仅实例化Test<float>Test<int>或包含标头但根本不实例化模板的翻译单元,会产生一些额外费用(解析器需要处理定义),但不会生成代码(二进制),或者在优化器和/或链接器上浪费时间,丢弃重复的符号.

In this approach the template is visible for instantiations with any type that the user might want to use. But you explicitly tell the compiler not to do the work for a known subset of types for which you provide the specializations. If the user wants Test<std::string> then the compiler will instantiate it implicitly, and that translation unit will pay the price. For translation units that only instantiate Test<float>, Test<int> or that include the header but don't instantiate the template at all, there will be some additional cost (the parser needs to handle the definitions) but there won't be generated code (binary), or time wasted on the optimizer and/or the linker discarding duplicate symbols.

正如您提到的,它还意味着,如果标头的内容发生更改,则重新编译包含该标头的所有用户代码.

It also implies, as you mention, recompiling all user code that included that header if the contents of the header change.

这篇关于模板实例化对编译持续时间的影响的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆