c++templateslanguage-lawyerfunction-templatesexplicit-instantiation

Are explicit template instantiation definition for a function template allowed in header files


I was reading about explicit template instantiation when i came across the following answer:

Assuming by "explicit template instantiation" you mean something like

   template class Foo<int>; // explicit type instantiation
   // or
   template void Foo<int>(); // explicit function instantiation

then these must go in source files as they considered definitions and are consequently subject to the ODR.


My question is that is the above claim that explicit template instantiation definition cannot be put into header files(and must be put into source files) technically correct. I am looking for an exact reference from the standard(or equivalent source) where it is specified that these ETI definitions cannot be put into header files.

I also tried this in a sample program which compiles and links fine without giving any multiple definition error(demo) in both gcc and clang even though i have put the ETIs into the header. Is the below given program well-formed according to the standard?

Header.h

#ifndef MYHEADER_H
#define MYHEADER_H
#include <string>

template<class T>
int func( const T& str)
{
  return 4;
}
template int func<std::string>( const std::string& str); //first ETI in header. Will the program be well formed if this header is included in multiple source files?
template int func<double>(const double& d);              //second ETI in header


#endif

source2.cpp

#include "Header.h"

source3.cpp

#include "Header.h"

main.cpp


#include <iostream>
#include "Header.h"
int main(){
  std::string input = "123";

  auto result = func(input);
    std::cout<<result<<std::endl;

}

Demo


Solution

  • From explicit instantiation's documentation:

    An explicit instantiation definition forces instantiation of the class, struct, or union they refer to. It may appear in the program anywhere after the template definition, and for a given argument-list, is only allowed to appear once in the entire program, no diagnostic required.

    (emphasis mine)

    This means that the shown program in question is in violation of the above quoted statement and thus ill-formed no diagnostic required.


    The same can be found in temp.spec:

    For a given template and a given set of template-arguments,

    • an explicit instantiation definition shall appear at most once in a program

    An implementation is not required to diagnose a violation of this rule.

    (emphasis mine)

    This again leads to the conclusion that the given example program is ill-formed NDR.


    Thus as long as the ETI definition occurs only once in the entire program the program is valid. For example, if you have a header that has the ETI definitions, then the program will be ill-formed if that header is included in more than one source file(note a possible workaround for this here). But if the header is included in exactly one source file then the program will be well-formed. The point is that they should appear at most once in the program. From where they come from(like header or a source file) is irrelevant.