C++ Templates Explicit instantiation


An explicit instantiation definition creates and declares a concrete class, function, or variable from a template, without using it just yet. An explicit instantiation can be referenced from other translation units. This can be used to avoid defining a template in a header file, if it will only be instantiated with a finite set of arguments. For example:

// print_string.h
template <class T>
void print_string(const T* str);

// print_string.cpp
#include "print_string.h"
template void print_string(const char*);
template void print_string(const wchar_t*);

Because print_string<char> and print_string<wchar_t> are explicitly instantiated in print_string.cpp, the linker will be able to find them even though the print_string template is not defined in the header. If these explicit instantiation declarations were not present, a linker error would likely occur. See Why can templates only be implemented in the header file?


If an explicit instantiation definition is preceded by the extern keyword, it becomes an explicit instantiation declaration instead. The presence of an explicit instantiation declaration for a given specialization prevents the implicit instantiation of the given specialization within the current translation unit. Instead, a reference to that specialization that would otherwise cause an implicit instantiation can refer to an explicit instantiation definition in the same or another TU.


#ifndef FOO_H
#define FOO_H
template <class T> void foo(T x) {
    // complicated implementation


#include "foo.h"
// explicit instantiation definitions for common cases
template void foo(int);
template void foo(double);


#include "foo.h"
// we already know foo.cpp has explicit instantiation definitions for these
extern template void foo(double);
int main() {
    foo(42);   // instantiates foo<int> here;
               // wasteful since foo.cpp provides an explicit instantiation already!
    foo(3.14); // does not instantiate foo<double> here;
               // uses instantiation of foo<double> in foo.cpp instead