'Function template in header: implicit instantiation duplicated or shared?

Following function template is defined in Foo.h.

#include <array>
using namespace std;

template<unsigned N>
array<int, N> gen_arr() {
  array<int, N> arr = {0};
  return arr;
}

Assuming A.cpp & B.cpp both include Foo.h and incur implicit instantiation of gen_arr<3>(), will a distinct copy of gen_arr<3> be created for each of the .cpp files? Is there a way to create a single implicit instantiation of a function template (in order to reduce executable size)? Thank you :)



Solution 1:[1]

Assuming A.cpp & B.cpp both include Foo.h and incur implicit instantiation of gen_arr<3>(), will a distinct copy of gen_arr<3> be created for each of the .cpp files?

Yes, when a non-inline function template is instantiated in different translation units(TUs) with the exact same template argument(s), it creates a new copy of the function.[Source] This is an automatic process and it may happen that a compiler end up creating two copies in two different files and it is also possible that some linker produces error for these two distinct definitions of the same function.

Nevertheless, this is a problem with the C++ compilation system and should not be a concern of ours. Meaning it is upto the implementation how to resolve this problem. Below are some of the typical solutions to the problem. As Dan Saks said in the above linked source, C++ linkers are now smart enough to keep just one copy and throw out the others.


This is a well known problem related to linkable entities generated by template instantiation(including instantiated function templates).

In your given example, the compiler needs to make sure that it generates code only for one of two point of instantiation's(aka POI) present the the two translation unit. There are 3 broadly categorised solutions implemented by different compiler vendors.

Greedy Instantiation

This scheme assumes that the linker is aware that these(linkable) entities may be duplicated across different object files. So the compiler simply mark these entities in a special way. And so when the linker finds more than one instance it just keeps only one of them and discards all the others.

Queried Instantiation

This scheme keeps a database that is shared by the compilations of all the translation units. This database is used to keep track of which specializations have been instantiated etc. So when a new specialization is encountered and if there is no entry in the database corresponding to that specialization, then this is entered into the database. On the other hand, if there is an entry corresponding to a specialization in the database, nothing is done.

So as the name suggests, the database is queried for a given specialization.

There are different schemes as well like iterated instantiation that can be used.


Is there a way to create a single implicit instantiation of a function template (in order to reduce executable size)?

Note "implicit" means automatic.You can use explicit instantiation for reducing/minimizing this problem/issue.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1