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.
template <typename>
struct S
{
void f() { /* ... */ }
void g() { /* ... */ }
};
template <>
void S<int>::g();
extern template struct S<int>;
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 for S<int>::g
, you need to declare the specialization in advance.
But let's just be thankful we aren't on fire.