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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8130602/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:04:12  来源:igfitidea点击:

using extern template (C++11)

c++templatesc++11extern

提问by codekiddy

Figure 1: function templates

图 1:函数模板

TemplHeader.h

模板头文件

template<typename T>
void f();

TemplCpp.cpp

模板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;
}

Is this the correct way to use extern template, or do I use this keyword only for class templates as in Figure 2?

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

Figure 2: class templates

图 2:类模板

TemplHeader.h

模板头文件

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

TemplCpp.cpp

模板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;
}

I know it is good to put all of this in one header file, but if we instantiate templates with the same parameters in multiple files, then we got multiple same definitions and the compiler will remove them all (except one) to avoid errors. How do I use extern template? Can we use it only for classes, or can we use it for functions too?

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

Also, Figure 1 and Figure 2 may be expanded to a solution where templates are in a single header file . In that case, we need to use the extern templatekeyword to avoid multiple same instantations. Is this only for classes or functions too?

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

回答by Dani

You should only use extern templateto force the compiler to notinstantiate a template when you knowthat it will be instantiated somewhere else. It is used to reduce compile time and object file size.

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

For example:

例如:

// 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>();
}

This will result in the following object files:

这将产生以下目标文件:

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

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

If both files are linked together, one void ReallyBigFunction<int>()will be discarded, resulting in wasted compile time and object file size.

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

To not waste compile time and object file size, there is an externkeyword which makes the compiler not compile a template function. You should use this if and only if you knowit is used in the same binary somewhere else.

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

Changing source2.cppto:

更改source2.cpp为:

// source2.cpp

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

Will result in the following object files:

将产生以下目标文件:

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

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

When both of these will be linked together, the second object file will just use the symbol from the first object file. No need for discard and no wasted compile time and object file size.

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

This should only be used within a project, like in times when you use a template like vector<int>multiple times, you should use externin all but one source file.

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

This also applies to classes and function as one, and even template member functions.

这也适用于类和函数合二为一,甚至模板成员函数。

回答by sehe

Wikipedia has the best description

维基百科有最好的描述

In C++03, the compiler must instantiate a template whenever a fully specified template is encountered in a translation unit. If the template is instantiated with the same types in many translation units, this can dramatically increase compile times. There is no way to prevent this in C++03, so C++11 introduced extern template declarations, analogous to extern data declarations.

C++03 has this syntax to oblige the compiler to instantiate a template:

  template class std::vector<MyClass>;

C++11 now provides this syntax:

  extern template class std::vector<MyClass>;

which tells the compiler not to instantiate the template in this translation unit.

在 C++03 中,只要在翻译单元中遇到完全指定的模板,编译器就必须实例化模板。如果模板在许多翻译单元中使用相同的类型进行实例化,这会显着增加编译时间。在 C++03 中没有办法阻止这种情况,因此 C++11 引入了 extern 模板声明,类似于 extern 数据声明。

C++03 有这样的语法强制编译器实例化一个模板:

  template class std::vector<MyClass>;

C++11 现在提供以下语法:

  extern template class std::vector<MyClass>;

它告诉编译器不要在这个翻译单元中实例化模板。

The warning: nonstandard extension used...

警告: nonstandard extension used...

Microsoft VC++ used to have a non-standardversion of this featurefor some years already (in C++03). The compiler warns about that to prevent portability issues with code that needed to compile on different compilers as well.

多年来,Microsoft VC++ 曾经拥有此功能的非标准版本(在 C++03 中)。编译器对此发出警告,以防止需要在不同编译器上编译的代码出现可移植性问题。

Look at the sample in the linked pageto see that it works roughly the same way. You can expect the message to go away with future versions of MSVC, except of course when using othernon-standard compiler extensions at the same time.

查看链接页面中的示例,看看它的工作方式大致相同。您可以预期该消息会随着 MSVC 的未来版本而消失,当然,同时使用其他非标准编译器扩展时除外。

回答by damirlj

The known problem with the templates is code bloating, which is consequence of generating the class definition in each and every module which invokes the class template specialization. To prevent this, starting with C++0x, one could use the keyword externin front of the class template specialization

模板的已知问题是代码膨胀,这是在调用类模板特化的每个模块中生成类定义的结果。为了防止这种情况,从 C++0x 开始,可以在类模板特化前使用关键字extern

#include <MyClass>
extern template class CMyClass<int>;

The explicit instantion of the template class should happen only in a single translation unit, preferable the one with template definition (MyClass.cpp)

模板类的显式实例应该只发生在单个翻译单元中,最好是带有模板定义的那个 (MyClass.cpp)

template class CMyClass<int>;
template class CMyClass<float>;

回答by qqqqq

If you have used extern for functions before, exactly same philosophy is followed for templates. if not, going though extern for simple functions may help. Also, you may want to put the extern(s) in header file and include the header when you need it.

如果您之前对函数使用过 extern,那么模板遵循完全相同的原理。如果没有,通过 extern 获取简单的功能可能会有所帮助。此外,您可能希望将 extern(s) 放在头文件中,并在需要时包含头文件。