24

我一直在浏览 C++0x 的 N3291 工作草案。我对外部模板很好奇。第 14.7.3 节规定:

除了内联函数和类模板特化,显式实例化声明具有抑制它们所引用实体的隐式实例化的效果。

仅供参考:术语“显式实例化声明”是extern template. 这是在第 14.7.2 节中定义的。

这听起来像是在说,如果你使用extern template std::vector<int>,那么做任何通常会隐式实例化的事情std::vector<int>都不会这样做。

下一段更有趣:

如果一个实体是同一翻译单元中的显式实例化声明和显式实例化定义的主题,则定义应遵循声明。作为显式实例化声明的主体并且也以其他方式在翻译单元中导致隐式实例化(14.7.1)的实体应是程序中某处显式实例化定义的主体;否则程序格式错误,不需要诊断。

仅供参考:术语“显式实例化定义”是这些事情的标准说法:template std::vector<int>. 也就是说,没有extern.

对我来说,这两件事可以extern template防止隐式实例化,但不会阻止显式实例化。所以如果你这样做:

extern template std::vector<int>;
template std::vector<int>;

第二行通过明确地执行第一行阻止隐式发生的事情来有效地否定第一行。

问题是这样的:Visual Studio 2008 似乎不同意。我想使用的方式extern template是防止用户隐式实例化某些常用模板,以便我可以在 .cpp 文件中显式实例化它们以减少编译时间。模板只会被实例化一次。

问题是我必须在 VS2008 中围绕它们进行基本的#ifdef。因为如果单个翻译单元看到了版本extern和非extern版本,它将使extern版本获胜,并且没有人会实例化它。然后是链接器错误。

所以,我的问题是:

  1. 根据 C++0x 的正确行为是什么?是否应该extern template防止显式实例化?
  2. 如果上一个问题的答案是不应该,那么 VS2008 是错误的(当然,它是在规范之前编写的,所以这不是他们的错)。VS2010如何处理这个?它是否实现了正确的extern template行为?
4

1 回答 1

7

它说

除了...类模板特化

所以它不适用于std::vector<int>,但适用于它的成员(不是内联成员函数并且可能不是嵌套类的成员。不幸的是,没有一个术语可以同时涵盖“类模板特化和成员特化”类模板的类”。所以有些地方只使用前者,但意味着也包括后者)。因此,如果需要std::vector<int>,它的嵌套类(例如std::vector<int>::iterator,如果它被定义为嵌套类)仍将被隐式实例化。

于 2011-07-29T13:11:38.863 回答