Home > Articles > Programming > C/C++

C++ Reference Guide

Hosted by

<code>export</code>ed Templates

Last updated Jan 1, 2003.

exported Templates

The separate compilation model enables us to define functions, types and objects in one translation unit and refer to them from other translation units. After compiling all the translation units of a program, the linker subsequently resolves all the references to extern symbols, producing a single executable file. When dealing with ordinary functions and classes, the separate compilation model works neatly.

Templates, however are a different beast. When you instantiate a template, the compiler must see its definition. This is an explicit requirement in the C++ standard, which states that dependent names (names that depend on the type of a template parameter) shall be looked up in both the current context (i.e., the place of instantiation) and the context of the template's definition. The compiler cannot generate the code of a specialization without looking at the template's definition — even if the definition appears in a separate translation unit. If the template is defined in several source files, all the definitions must comply with the One Definition Rule. As I explained elsewhere, the common approach is to define the template in a header file and #include it in every source file that uses that template.

If you have used templates before, you already know that. However, standard C++ defines another compilation model for templates known as the separation model.

export: How it All Began

Right from the start, C++ creators called for separate compilation of templates. However, they didn't specify how this could be accomplished. Unlike most other C++ features, which were standardized only after being implemented by one vendor at least, exported templates were added to C++ in 1996 with no existing implementation whatsoever.

In 1996, many compilers hardly supported ordinary templates and the C++ community had gained little experience with advanced template techniques such as meta-programming. Therefore, the implications of implementing export weren't fully recognized. The very few people who have implemented exported templates since agree that this is an arduous task indeed.

State of the Art

The most popular C++ compilers (Microsoft's Visual C++ .NET, Borland's C++ BuilderX, GNU's GCC and others) don't support export. Even vendors who have expressed their commitment to "100% ISO compliance" exclude export from their checklist. The frequently-cited reason for this is "lack of demand." Could it be that users don't demand this features because they've never had a chance to use it?

Which compilers support export?

In addition to Comeau C/C++, Intel's 7.x compiler also supports export, although by default, it's disabled and "currently undocumented and unsupported". Other EDG-derived implementations may also support this feature.

export and User Expectations

If judged by the amount of questions pertaining to linkage errors due to the use of templates, C++ programmers indeed expect compilers to support separate template compilation. However, my impression is that they are looking for something quite different from what export actually does.

One might naively assume that by declaring a template export in a header file, it would be possible to define it in a .cpp file that gets compiled only once, and then #include only the header file in other translation units:

//func.h
export template <class T> void func(T t); //only a declaration
//func.cpp 
 template <class T> void func(T t) {//implementation
//...
} 
//main.cpp
#include "func.h" 
int main()
{
 func(5); //instantiate void func(int) here
}

Indeed, compilers that support exported templates allow this. However, when the compiler sees the call to func(), it has to look at the template's definition, not just its declaration. How do export-enabled compilers accomplish this? When a file containing definitions of exported templates is compiled, Comeau C/C++ for instance creates a file with an .et suffix. Then, when the template in question is instantiated, the compiler uses the .et files to find the translation unit that defines a given exported template. The sources containing the exported template definitions must therefore be made available at the time of instantiation. The export facility is not a mechanism for avoiding the publication of template definitions in source form.

In my opinion, this is the most crucial point in the debate about the usefulness of export. Many users mistakenly believe that export enables them to ship compiled .obj, .lib, or .dll files without having to provide the templates' definitions. This isn't the case.

Future Directions

Considering the strict requirements of the Standard, would it possible, at least theoretically, to avoid shipping the template definitions in source form? Vendors may come up with a technology for compiling a template's definition into a pseudo-code or some other intermediary language.

However, such a compiler must be able to reconstruct the original template's definition from the intermediary code. .NET and Java already offer such a technology, with the obvious advantage of portability. In C++, I can't think of a compelling reason to adopt this approach. For developers who wish to protect their intellectual property by hiding templates' definitions, this solution is pretty useless since customers would be able to reconstruct the definitions from the intermediary code. Worse yet, compiling a template's definition into intermediary code and then decompiling it back during instantiation will increase build time considerably.

Conclusions

Considering its inherent complexities (both from an implementer's point of view and a user's point of view), export is expensive. Yet, it doesn't offer any breathtaking advantages. Worse, it incurs a few undesirable side-effects, such as delayed compilation errors and semantic differences from the inclusion model with respect to overload resolution and the "externalization" of file-scope identifiers. Then again, export is in the Standard (a proposal to remove it was recently rejected). Will this feature ever become a widely-used feature? My impression is that vendors will continue to ignore it, as they have been doing in the past eight years.

Books

C++ Templates: The Complete Guide, by David Vandevoorde and Nicolai M. Josuttis, is in my opinion the best template guide yet. In addition to covering state-of-the-art template programming techniques (which is why you should read this book in the first place), the authors also dedicate a few pages to the somewhat confusing template terminology, such as explaining the difference between a specialization and instantiation, or the difference between a template parameter and a template argument. Even export gets its share in chapter 6, where the authors discuss its semantics and usage.