Following code generate no compilation/linker error/warning:
// A.h
#include<iostream>
struct A
{
template<typename T>
static void foo (T t)
{
std::cout << "A::foo(T)\n";
}
};
void other ();
// main.cpp
#include"A.h"
int main ()
{
A::foo(4.7);
other();
}
// other.cpp
#include"A.h"
template<>
void A::foo (double d)
{
cout << "A::foo(double)\n";
}
int other ()
{
A::foo(4.7);
}
The output surprisingly is:
A::foo(T)
A::foo(double)
Why compiler is not able to pick up the correct A::foo(double) in case of main.cpp ?
Agree that, there is no issue as expected, if there is a declaration in A.h like below:
template<> void A::foo (double);
But that’s not the concern, because at link time, compiler has the specialized version.
Also, is having 2 different version of the same function an Undefined Behavior ?
All explicit specialization declarations must be visible at the time of the template instantiation. Since your explicit specialization declaration for
A::foo<double>is visible in one translation unit but not the other, the program is ill-formed.(In practice, the compiler will instantiate the primary template in
main.cppand the explicitly-specialized one inother.cpp. That would still an ODR violation anyway.)