这是 C++11 中 extern 模板的正确用法吗? (难道 extern template class
和相应的 template class
在同一个翻译单元中可见吗?)
// example.hpp:
#pragma once
template< typename T >
class C {
void f(T);
};
// question is about the next two lines
extern template class C< float >;
extern template class C< double >;
// example_def.hpp:
#include "example.hpp"
template< typename T >
void C< T >::f(T) {
//... smth. practicable
}
// example.cpp:
#include "example_def.hpp"
template class C< float >;
template class C< double >;
// other.hpp:
#pragma once
void g();
// other.cpp:
#include "other.hpp"
#include "example.hpp"
// maybe those two lines should be here instead?
void g() {
C< float >();
C< double >();
}
// main.cpp:
#include "example.hpp"
#include "other.hpp"
// ...and here?
int main() {
C< float >();
C< double >();
g();
return 0;
}
最佳答案
是的,外部模板类
规范(标准称为显式实例化声明)和模板类
规范(被标准称为显式实例化定义)可以在同一个翻译单元中,如果定义(没有extern
)遵循声明(使用 extern
):
(§14.7.2/11) If an entity is the subject of both an explicit instantiation declaration and an explicit instantiation definition in the same translation unit, the definition shall follow the declaration. An entity that is the subject of an explicit instantiation declaration and that is also used in a way that would otherwise cause an implicit instantiation (14.7.1) in the translation unit shall be the subject of an explicit instantiation definition somewhere in the program; otherwise the program is ill-formed, no diagnostic required. [ Note: This rule does apply to inline functions even though an explicit instantiation declaration of such an entity has no other normative effect. This is needed to ensure that if the address of an inline function is taken in a translation unit in which the implementation chose to suppress the out-of-line body, another translation unit will supply the body. — end note ] An explicit instantiation declaration shall not name a specialization of a template with internal linkage.
(强调我的)。术语显式实例化声明 和显式实例化定义 定义如下:
(§14.7.2/2) The syntax for explicit instantiation is:
explicit-instantiation:
extern
opttemplate
declarationThere are two forms of explicit instantiation: an explicit instantiation definition and an explicit instantiation declaration. An explicit instantiation declaration begins with the extern keyword.
这些显式实例化的效果如下:
显式实例化声明(使用
extern
)阻止所有隐式实例化生效(除了内联函数和类模板特化,§14.7.2/10)。显式实例化定义(没有
extern
)导致实例化发生无论如何,即它覆盖显式实例化声明(这也遵循§ 14.7.2/10).
一般评论
您的显式实例化声明位于定义模板的头文件中这一事实意味着任何人包含头文件以使用模板的人都必须同时添加一个显式实例化< em>定义,或者需要链接到另一个包含此类显式实例化定义的 .cpp
文件的代码。
当您期望许多不同的用户为许多不同类型实例化模板时,这可能会造成混淆并且可能不是一个好主意。但是,如果不同类型的实例化数量很少并且您可以预料到它们,那么这可能是明智的。当然,您必须确保有一个(或多个).cpp
文件包含所有所需实例化的显式实例化定义,并且其对应的对象文件在构建时与项目链接。
关于c++ - 同一翻译单元中的模板类和各自的外部模板类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14021243/