Lingxi
Lingxi

Reputation: 14967

Confusions around explicit template instantiation

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.

Upvotes: 3

Views: 771

Answers (2)

T.C.
T.C.

Reputation: 137310

[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.

Upvotes: 1

SergeyA
SergeyA

Reputation: 62563

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.

Upvotes: 0

Related Questions