如何使用extern模板

时间:2011-07-29 09:02:28

标签: c++ visual-studio-2008 templates c++11 explicit-instantiation

我一直在查看C ++ 0x的N3291工作草案。我对extern模板感到好奇。第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行为?

1 个答案:

答案 0 :(得分:7)

它说

  

除了...类模板专业化

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