These are not specialization declarations. Explicit specialization declarations/definitions use template<>
instead of template
and extern
can't be used on them like this.
extern template int register_parameters<2>();
is an explicit instantiation declaration.
template int register_parameters<2>();
is an explicit instantiation definition.
Normally, when the definition of a template is available, and a template specialization like register_parameters<2>
is used in a way that would require a definition of that specialization to exist (e.g. a function call register_parameters<2>()
), the compiler would implicitly instantiate the template definition into the definition for the specific specialization (i.e. the actual body of the function that register_parameters<2>
refers to with 2
substituted for ndims
from the template definition). For it to be able to do that it is usually required that the template is defined in a header file available at the point requiring the implicit instantiation.
The explicit instantiation definition instructs the compiler to explicitly instantiate the template specialization in this translation unit and guarantee that the instantiation is available to other translation units as well (so that these do not actually need an instantiation/definition).
If there is no definition for the template available, then this can of course not work. Hence your error message at the end of the question.
The explicit instantiation declaration instructs the compiler that there is a corresponding definition somewhere (else) in the program and that implicit instantiation of the template specialization should not be done and is not needed in this translation unit. It could not be done in a.cpp
anyway though, since it lacks the definition of the template.
So together these two make sure that there will be exactly one single instantiation of the template specialization in the program, coming from translation unit b.cpp
with the explicit instantiation definition, instead of the more common approach of having the template be defined in a header and implicitly instantiated in each translation unit.