Does extern template prevent inlining of functions?

The idea behind extern templates is to make explicit template instantiations more useful.

As you know, in C++03, you can explicitly instantiate a template using this syntax:

template class SomeTemplateClass<int>;
template void foo<bool>();

This tells the compiler to instantiate the template in the current translation unit. However, this doesn’t stop implicit instantiations from happening: the compiler still has to perform all implicit instantiations and then merge them together again during linking.

Example:

// a.h
template <typename> void foo() { /* ... */ }

// a.cpp
#include "a.h"
template void foo<int>();

// b.cpp
#include "a.h"
int main()
{
    foo<int>();
    return 0;
} 

Here, a.cpp explicitly instantiates foo<int>(), but once we go to compile b.cpp, it will instantiate it again because b.cpp has no idea that a.cpp is going to instantiate it anyway. For large functions with many different translation units doing implicit instantiations, this can add quite significantly to compile and link time. It may also cause the function to be unnecessarily inlined, which can lead to significant code bloat.

With extern templates, you can let other source files know that you plan to instantiate the template explicitly:

// a.h
template <typename> void foo() { /* ... */ }
extern template void foo<int>();

This way, b.cpp won’t cause an instantiation of foo<int>(). The function will be instantiated in a.cpp and will be linked like any normal function. It’s also much less likely to be inlined.

Note that this doesn’t prevent inlining — the function could still be inlined at link time in exactly the same way that a normal non-inline function can still be inlined.

EDIT: For those that are curious, I just did a quick test to see how much time g++ spends instantiating templates. I tried instantiating std::sort<int*> in a varying number of translation units, with and without the instantiation being suppressed. The result was conclusive: 30ms per instantiation of std::sort. There’s definitely time to be saved here in a large project.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)