c++ - 使用外部模板 (C++11)

标签 c++ templates c++11 extern

图 1:函数模板

TemplHeader.h

template<typename T>
void f();

TemplCpp.cpp

template<typename T>
void f(){
   //...
}    
//explicit instantation
template void f<T>();

main.cpp

#include "TemplHeader.h"
extern template void f<T>(); //is this correct?
int main() {
    f<char>();
    return 0;
}

这是使用 extern template 的正确方法,还是我只将此关键字用于类模板,如图 2 所示?

图 2:类模板

TemplHeader.h

template<typename T>
class foo {
    T f();
};

TemplCpp.cpp

template<typename T>
void foo<T>::f() {
    //...
}
//explicit instantation
template class foo<int>;

main.cpp

#include "TemplHeader.h"
extern template class foo<int>();
int main() {
    foo<int> test;
    return 0;
}

我知道将所有这些都放在一个头文件中是很好的,但是如果我们在多个文件中使用相同的参数实例化模板,那么我们会得到多个相同的定义并且编译器将删除它们(除了一个)以避免错误。如何使用 extern template?我们可以只将它用于类,还是也可以将它用于函数?

此外,图 1 和图 2 可以扩展为模板位于单个头文件中的解决方案。在这种情况下,我们需要使用 extern template 关键字来避免多个相同的实例化。这也只适用于类或函数吗?

最佳答案

你应该只使用 extern template您知道模板将在其他地方实例化时,强制编译器实例化模板。它用于减少编译时间和目标文件大小。

例如:

// header.h

template<typename T>
void ReallyBigFunction()
{
    // Body
}

// source1.cpp

#include "header.h"
void something1()
{
    ReallyBigFunction<int>();
}

// source2.cpp

#include "header.h"
void something2()
{
    ReallyBigFunction<int>();
}

这将产生以下目标文件:

source1.o
    void something1()
    void ReallyBigFunction<int>()    // Compiled first time

source2.o
    void something2()
    void ReallyBigFunction<int>()    // Compiled second time

如果两个文件链接在一起,一个void ReallyBigFunction<int>()将被丢弃,导致编译时间和目标文件大小的浪费。

为了不浪费编译时间和目标文件大小,有一个 extern使编译器不编译模板函数的关键字。 当且仅当您知道它在其他地方的相同二进制文件中使用时,您才应该使用它。

改变 source2.cpp到:

// source2.cpp

#include "header.h"
extern template void ReallyBigFunction<int>();
void something2()
{
    ReallyBigFunction<int>();
}

将产生以下目标文件:

source1.o
    void something1()
    void ReallyBigFunction<int>() // compiled just one time

source2.o
    void something2()
    // No ReallyBigFunction<int> here because of the extern

当这两个链接在一起时,第二个目标文件将只使用第一个目标文件中的符号。不需要丢弃,也不会浪费编译时间和目标文件大小。

这应该只在项目中使用,就像在使用 vector<int> 这样的模板时一样。多次,你应该使用 extern在除一个源文件之外的所有文件中。

这也适用于类和函数作为一个整体,甚至模板成员函数。

关于c++ - 使用外部模板 (C++11),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44205599/

相关文章:

c++ - 如何使用 avr-gcc 在 C/C++ 中执行预主初始化?

c++ - 需要一个好的方法来在 Google Test 中测试工厂类

c++ - 再次关于 enable_if_t 中的 C++ SFINAE

c++ - 不支持基本模板的概念专用模板

c++ - 为什么这个类型转换模棱两可?

c++ - thread_local C++11,VS2015 中的错误 C2492

c++ - 在析构函数和后续析构函数中引发异常

c++ - 关联容器的迭代器不依赖于比较器模板参数

c++ - 使用一个数字数据成员为类定义所有比较运算符的便捷方法?

c++ - 如何编写可以专门用于对象或 int N 的模板