2

Well, I think I just get extremely confused by explicit template instantiation ~>_<~

  1. Could an explicit instantiation declaration exploit an implicit instantiation definition?
  2. What if both explicit and implicit instantiation definitions exist in a program? Will they ultimately collapse into a single one?
  3. Does an explicit instantiation declaration have any effect when placed after an implicit instantiation definition?

Also, see the following code:

#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?
}

It causes the link error

/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

with GCC 5.2, but builds fine with clang 3.6. Which one is correct according to the standard?

I hope there is an insightful way to understand explicit template instantiation so that answers to all the questions above can be logically deduced and explained.

Lingxi
  • 14,579
  • 2
  • 37
  • 93

2 Answers2

1

[temp.explicit]/p11:

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.

T.C.
  • 133,968
  • 17
  • 288
  • 421
  • Does this mean that explicit instantiation declaration can only exploit explicit instantiation definition, and that GCC is correct for the second use of `std::vector` after the explicit instantiation declaration should only try to link to the explicit instantiation definition which is absent in the example? Then how about question 2? – Lingxi Oct 02 '15 at 02:28
  • If the above interpretation is correct, the standard seems to make a clear distinction between implicit and explicit instantiation definitions, and the answer to question 2 is not obvious. – Lingxi Oct 02 '15 at 02:39
0

First of all, it seems like you are overthinking explicit instantion. There is nothing special about it. All it does, it allows someone to use the templated function or class without having the template definition visible. It makes it so by creating an instance of function or class with template specified, so that it is no longer template but the actual usable thing. It can be used, for example, when you have a template class, but do want to hide the actual code in .cpp file which you never provide to the users - instead you give them the compiled .o file. To make it work, you can explicitly instantiate your template with the types you believe your users are going to need for the template arguments. (of course, this is a rare case when the set of types is known like this). There is nothing more to that.

Implicit and explicit instantions for the same type can live together. Implicit instantiation will produce weak symbol, explicit one will produce the 'strong' symbol. Strong symbols override weaks symbols, and there is no violation of ODR. Everything will be OK.

As for the error you have, you need to remove 'extern' from your explicit instantion.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
  • What's wrong with `extern` if a weak symbol is provided by the implicit instantiation definition? – Lingxi Oct 01 '15 at 19:45
  • 1
    I am no language lawyer, so I can't comment on legaility of this, but obviously, when g++ sees an explicit template instantion, and does not attempt implicit (makes sense to me), it expect to find all the symbols it needs without doing any instantiations. Since it is extern, it expects them to be provided by someone else. – SergeyA Oct 01 '15 at 20:08