如何使用外部模板
我一直在浏览 C++0x 的 N3291 工作草案。我对外部模板很好奇。第 14.7.3 节规定:
除了内联函数和类模板特化之外,显式实例化声明具有抑制它们所引用的实体的隐式实例化的效果。
仅供参考:术语“显式实例化声明”是 extern template
的标准说法。这是在 14.7.2 节中定义的。
这听起来像是在说,如果您使用 extern template std::vector
,则执行通常会隐式实例化 std::vector
的任何操作> 不会这样做。
下一段更有趣:
如果一个实体是同一翻译单元中显式实例化声明和显式实例化定义的主题,则定义应位于声明之后。作为显式实例化声明的主题的实体,并且其使用方式也会导致翻译单元中的隐式实例化(14.7.1),该实体应成为程序中某处显式实例化定义的主题;否则程序格式错误,无需诊断。
仅供参考:术语“显式实例化定义”是这些事物的标准说法:template std::vector
。也就是说,没有 extern
。
对我来说,这两件事表明 extern template
可以防止隐式实例化,但它确实不会防止显式实例化。因此,如果您这样做:
extern template std::vector<int>;
template std::vector<int>;
第二行通过显式执行第一行阻止隐式发生的操作,有效地否定了第一行。
问题是这样的:Visual Studio 2008 似乎不同意。我想要使用 extern template 的方式是防止用户隐式实例化某些常用模板,以便我可以在 .cpp 文件中显式实例化它们以减少编译时间。模板只会被实例化一次。
问题是我必须在 VS2008 中基本上#ifdef 围绕它们。因为如果单个翻译单元看到 extern
和非 extern
版本,它将使 extern
版本获胜,并且没有人会实例化它。然后出现链接器错误。
所以,我的问题是:
- 根据 C++0x,正确的行为是什么?
extern template
是否应该阻止显式实例化? - 如果上一个问题的答案是不应该,那么 VS2008 就有错误(当然,它是在规范之前写好的,所以这并不是他们的错)。 VS2010如何处理这个问题?它是否实现了正确的
外部模板
行为?
I've been looking through the N3291 working draft of C++0x. And I was curious about extern template. Section 14.7.3 states:
Except for inline functions and class template specializations, explicit instantiation declarations have the effect of suppressing the implicit instantiation of the entity to which they refer.
FYI: the term "explicit instantiation declaration" is standard-speak for extern template
. That was defined back in section 14.7.2.
This sounds like it's saying that if you use extern template std::vector<int>
, then doing any of the things that would normally implicitly instantiate std::vector<int>
will not do so.
The next paragraph is more interesting:
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.
FYI: the term "explicit instantiation definition" is standard speak for these things: template std::vector<int>
. That is, without the extern
.
To me, these two things say that extern template
prevents implicit instantiation, but it does not prevent explicit instantiation. So if you do this:
extern template std::vector<int>;
template std::vector<int>;
The second line effectively negates the first by explicitly doing what the first line prevented from happening implicitly.
The problem is this: Visual Studio 2008 doesn't seem to agree. The way I want to use extern template
is to prevent users from implicitly instantiating certain commonly-used templates, so that I can explicitly instantiate them in the .cpp files to cut down on compile time. The templates would only be instantiated once.
The problem is that I have to basically #ifdef around them in VS2008. Because if a single translation unit sees the extern
and non-extern
version, it will make the extern
version win and nobody would ever instantiate it. And then come the linker errors.
So, my questions are:
- What is the correct behavior according to C++0x? Should
extern template
prevent explicit instantiation or not? - If the answer to the previous question is that it should not, then VS2008 is in error (granted, it was written well before the spec, so it's not like it's their fault). How does VS2010 handle this? Does it implement the correct
extern template
behavior?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
它说
,因此它不适用于及其嵌套类(如
std::vector
,而是适用于其成员(不是内联成员函数并且可能不是嵌套类的成员)不幸的是,没有一个术语可以同时涵盖“类模板专业化和类模板成员类的专业化”,因此有些地方只使用前者,但也包含后者。因此 std::vectorstd::vector::iterator
,如果它被定义为嵌套类)仍然会如果需要的话可以隐式实例化。It says
So it does not apply to
std::vector<int>
, but to its members (members that aren't inline member functions and presumably that aren't nested classes. Unfortunately, there isn't a one term that catches both of "class template specialization and specializations of member classes of class templates". So there are some places that use only the former but mean to also include the latter). Sostd::vector<int>
and its nested classes (likestd::vector<int>::iterator
, if it is defined as a nested class) will still be implicitly instantiated if needed.