模板实例化对编译持续时间的影响

时间:2013-09-24 16:01:33

标签: c++ instantiation

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

档案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

好。在Test<float>上进行任何修改后,此技术是否有效减少了谁使用func()的编译时间?

1 个答案:

答案 0 :(得分:2)

由于成员函数的定义都在cpp内部,因此不能用于其他转换单元,因此函数不会被隐式实例化,因此编译代码的成本仅限于单个cpp。

该方法的问题在于您将模板的使用限制为您提供手动实例化的类型(或类型)。外部用户无法将其实例化为其他类型,如果必须这样做,则需要记住手动专门针对您要使用的每种类型。

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

// .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>或包含标题但根本不实例化模板的翻译单元,会有一些额外的成本(解析器需要处理定义)但是赢了不是生成代码(二进制),或浪费在优化器和/或链接器上的时间丢弃重复符号。

如您所述,它还意味着,如果标题的内容发生变化,则重新编译包含该标题的所有用户代码。