template specialization, explicit instantiation and forward declarations

Viewed 64

I have some doubts about what the standard says about the following case:

//foo.hpp

#pragma once
#include<iostream>

template<typename T>
void foo(){
  std::cout << "generic\n";
}

#ifdef FWD
template<>
void foo<int>();
#endif
//foo.cpp

#include "foo.hpp"

template<>
void foo<int>(){
  std::cout << "specialization\n";
}
\\main.cpp

#include "foo.hpp"

int main(){
  foo<int>();
}

The result of this code is the same no matter the definition of FWD (print "specialization"). However, if I check symbols in main.o, results are different:

  • FWD defined : undefined symbol to specialization of foo
  • FWD undefined : the symbol to foo exists

Is there a standard way of dealing with this? Is there any risk that the general implementation is taken at link-time when no forward declaration is done?

1 Answers

Is there any risk that the general implementation is taken at link-time when no forward declaration is done?

[temp.expl.spec]/7 says as follows:

If a template, a member template or a member of a class template is explicitly specialized, a declaration of that specialization shall be reachable from every use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required.

Thus without having the explicit specialization at least forward declared I would expect UB and inconsistency between compilers.

Moreover, here you can see that the same compiler (in this case clang) works differently depending on optimisation options.


TLDR: either include definition of the explicit specialization or at least forward declare its existence.

Related