Home > Articles > Programming > C/C++

C++ Reference Guide

Hosted by

Toggle Open Guide Table of ContentsGuide Contents

Close Table of ContentsGuide Contents

Close Table of Contents

The extern template Proposal

Last updated Jan 1, 2003.

Unlike the controversy of exported templates, whose de facto status is still uncertain, extern templates are a new core language feature accepted into the Working Paper of C++09 and are here to stay. Find out what extern templates are, what they're good for and how they are used.

The Problem

In many C++ projects and libraries, a common technique is used for implementing automatic instantiation, namely: the compiler instantiates a function in each translation unit in which that function is referenced. Next, the linker eliminates redundant copies of the said instantiation. Thus, multiple .obj files of the same program may contain the object code of the same template specialization, say

swap(int&, int&);

During linkage, the linker removes all redundant copies of swap(int&, int&) from the program, resolving all references to this specialization to a single implementation. This process of removing redundant copies of the same specialization is both slow and imperfect. In some cases, the linker can't eliminate every redundant copy from the resulting executable. As a result, you still get duplicate instances of the same specialization within the same program (hence, a bloated executable file), not to mention the longer compilation time required for generating the object code for the same specialization in multiple object files.

A number of implementations overcome this problem by using extern declarations for templates. This technique was originally introduced as a non-standard extension. In April 2003, it was proposed as new C++09 feature. After a few revisions, this proposal became document number N1987 which was incorporated into the Working Paper recently.

extern Templates

Recall that a C++98 explicit template instantiation consists of the keyword template followed by a template declaration. For example, to explicitly instantiate every member function of std::vector<int>, you can use the following explicit instantiation directive:

template vector<int>; //instantiate every member function of vector<int>

When the compiler sees this directive, it generates every member function of vector<int>—not just the member functions that are directly referred to in the current translation unit (however, member functions inherited from base class(es) are not generated). By contrast, the following code (which uses no explicit instantiation directives):

void fun()
{
vector<int> vi;

}

Causes the compiler to generate only two member functions of vector<int>—the default constructor and the destructor.

The same rule applies to function templates and member functions of a class template—you can explicitly instantiate in the following manner:

template void swap<char&, char&>;
template void std::vector<int>::push_back(const int&); //instantiate only push_back()
template std::vector<double>;//instantiate every member function of vector<double>

The extern templates proposal splits explicit template instantiations into two new categories:

  • Explicit instantiation definition
  • Explicit instantiation declaration

The C++98 explicit template instantiations that I've just demonstrated are now considered explicit instantiation definitions. When the compiler encounters an explicit instantiation definition, it is forced to generate the code for it. By contrast, an explicit instantiation declaration has the following form:

extern template template-declaration;

In other words, an explicit instantiation preceded by extern template is an explicit instantiation declaration. Examples:

extern template void swap<char&, char&>;
extern template void std::vector::push_back(const int&); 
extern template std::vector<double>;

When the compiler encounters an extern template directive, it suppresses the generation of code for that particular specialization. However, an explicit instantiation of the entity must appear in another translation unit, or later in the same translation unit. An explicit instantiation definition of a given entity shall appear at most once in the program.

In this respect, extern template works very much like extern declarations of a data object: the extern declaration doesn't instantiate the declared object; that object still needs to be defined elsewhere in the program.

extern template Rules

The extern template proposal differs in some aspects from current implementations that support this feature. While some compilers use extern template declarations as a means for providing greater control over the point of instantiation of a template, this proposal provides no such guarantees. The authors also propose the following rules:

  • An extern template directive may not name a static function (it may, however, name a static class member).
  • An extern template directive that names a class applies to the members of the class, not the class itself. If the class includes nested classes, the extern template directive also applies to the members of the nested class, recursively.
  • If a translation unit contains both an explicit instantiation declaration and an explicit instantiation definition, the definition shall appear after the declaration.

extern template and inline

Some existing implementations use extern template directives to control the instantiation of inline functions. The proposal however makes no such guarantees. It only says that "implementations are encouraged to suppress out-of-line copies of inline functions that were declared with extern template." Such inline functions are still instantiated though—otherwise they cannot be inlined.