0

I'm working with a code base that has the following declarations in a.cpp:

template <int num_dim = 2>
int register_parameters();
extern template int register_parameters<2>(); // why is extern required here?

In b.cpp, we define

template <int num_dim = 2> int register_parameters() {
  // define stuff
}

template int register_parameters<2>();

When I remove the extern keyword, I get the following error at compile time

error: explicit instantiation of ‘int register_parameters() [with int num_dim = 2]’ but no definition available [-fpermissive]
  template int register_parameters<2>();

I am wondering why the extern keyword is required in this case?

24n8
  • 1,898
  • 1
  • 12
  • 25
  • `extern` tells the compiler this symbol is defined, just not in this file, so you need the linker to figure that part out. – NathanOliver May 09 '22 at 19:27

1 Answers1

0

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.

user17732522
  • 53,019
  • 2
  • 56
  • 105
  • Isn't the first one a template function declaration and not a specialization? I'm a bit fuzzy with template terminology – 24n8 May 09 '22 at 19:43
  • @24n8 No, A declaration of a template begins with `template<...>` where `...` is non-empty. `template int register_parameters();` is a declaration of a template, but `extern template int register_parameters<2>();` is not. – user17732522 May 09 '22 at 19:44
  • @24n8 I had forgotten a very important word in the first sentence. It should have said "_not_". Sorry if that caused confusion! – user17732522 May 09 '22 at 19:45