Consider a class template S:
[s.hpp]
template <typename>
struct S
{
void f() { /* ... */ }
void g() { /* ... */ }
};
This class template also comes with a source file containing a specialization of S<int>::g():
[s.cpp]
template <>
void S<int>::g() { /* ... */ }
S is instantiated a lot of times as S<int>. In order to speed up compilation times by avoiding multiple instantiations of S<int>, I want to introduce an explicit instantiation declaration (extern template) in the header file s.hpp, and a corresponding explicit instantiation definition in the source file s.cpp:
[s.hpp] (modified)
template <typename>
struct S
{
void f() { /* ... */ }
void g() { /* ... */ }
};
extern template struct S<int>;
[s.cpp] (modified)
template <>
void S<int>::g() { /* ... */ }
template struct S<int>;
Doing so, however, results in the following compilation error:
<source>:11:14: error: explicit specialization of 'g' after instantiation
void S<int>::g() { /* ... */ }
^
<source>:8:23: note: explicit instantiation first required here
extern template class S<int>;
^
I presume that the error happens because extern template is still considered an instantiation, even thought it is just a declaration.
How can I achieve a possible compilation speedup by providing an extern template declaration in the client-facing header for S, while still retaining an explicit specialization of S<int>::g in the source file?
Declare the explicit specialisation in the header as well.
To distill the rules: a declaration of an explicit specialization must appear before an entity is the subject of explicit instantiation - definition or declaration. Because the explicit instantiation of
S<int>recursively constitutes the same forS<int>::g, you need to declare the specialization in advance.But let's just be thankful we aren't on fire.