围绕显式模板实例化的混淆

时间:2015-10-01 19:23:37

标签: c++ templates c++11 language-lawyer explicit-instantiation

好吧,我想我只是因显式模板实例化而非常困惑〜> _<〜

  1. 显式实例化声明是否可以利用隐式实例 实例化定义?
  2. 如果存在显式和隐式实例化定义,该怎么办? 在一个程序?他们最终会崩溃成一个吗?
  3. 显式实例化声明在放置后是否有效 隐式实例化定义?
  4. 另外,请参阅以下代码:

    #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构建正常。根据标准哪一个是正确的?

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

2 个答案:

答案 0 :(得分:1)

[temp.explicit] / P11:

  

作为显式实例化声明主题的实体   并且这也以一种否则会导致隐含的方式使用   翻译单元中的实例化(14.7.1)应为   程序中某处的显式实例化定义;   否则程序结构不合理,无需诊断。

答案 1 :(得分:0)

首先,你似乎正在过度思考明确的立场。没什么特别的。它所做的一切,它允许某人使用模板化的函数或类,而无需显示模板定义。它通过创建一个带有指定模板的函数或类的实例来实现,因此它不再是模板而是实际可用的东西。例如,当你有一个模板类,但是想要隐藏你从未提供给用户的.​​cpp文件中的实际代码时,可以使用它 - 而不是给它们编译的.o文件。要使其工作,您可以使用您认为用户对模板参数所需的类型显式实例化模板。 (当然,这是一种罕见的情况,因为这种类型的集合是这样的)。没有更多的东西了。

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

至于你的错误,你需要从你的显式实例中删除'extern'。