2

好吧,我想我对显式模板实例化感到非常困惑~>_<~

  1. 显式实例化声明能否利用隐式实例化定义?
  2. 如果程序中同时存在显式和隐式实例化定义怎么办?他们最终会崩溃成一个单一的吗?
  3. 显式实例化声明放在隐式实例化定义之后是否有任何影响?

另外,请参见以下代码:

#include <iostream>
#include <vector>

std::vector<int> a;  // Implicit instantiation definition.

// Explicit instantiation declaration.
extern template class std::vector<int>; 

int main() {
  std::cout << std::vector<int>().size();  // So what?
}

导致链接错误

/tmp/ccQld7ol.o: In function `_GLOBAL__sub_I_a':
main.cpp:(.text.startup+0x6e): undefined reference to `std::vector<int, std::allocator<int> >::~vector()'
collect2: error: ld returned 1 exit status

使用 GCC 5.2,但使用 clang 3.6 构建良好。根据标准,哪一个是正确的?

我希望有一种有见地的方法来理解显式模板实例化,以便可以从逻辑上推断和解释上述所有问题的答案。

4

2 回答 2

1

[temp.explicit]/p11:

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

于 2015-10-02T01:15:47.253 回答
0

首先,您似乎在考虑显式实例化。它没有什么特别之处。它所做的一切,它允许某人使用模板化的函数或类,而无需看到模板定义。它通过创建指定模板的函数或类的实例来实现这一点,因此它不再是模板,而是实际可用的东西。例如,当您有一个模板类时,可以使用它,但确实想隐藏 .cpp 文件中的实际代码,而您从未提供给用户 - 而是给他们编译后的 .o 文件。为了使其工作,您可以使用您认为用户将需要模板参数的类型显式实例化您的模板。(当然,当类型集像这样已知时,这种情况很少见)。仅此而已。

同一类型的隐式和显式实例可以同时存在。隐式实例化将产生弱符号,显式实例化将产生“强”符号。强符号覆盖弱符号,并且不违反 ODR。一切都会变好。

至于您遇到的错误,您需要从显式实例中删除“extern”。

于 2015-10-01T19:35:58.797 回答