Consider the following minimal example which reproduces a problem in a much bigger project:
spec.h:
#include <iostream>
class A
{
public:
template<typename T>
T test(const std::string& a)
{
std::cout << "DEFAULT CALLED WITH " << a << "\n";
return T();
}
};
other.cpp:
#include "spec.h"
template<>
float A::test<float>(const std::string& a)
{
std::cout << "SPECIAL CALLED WITH " << a << "\n";
return float();
}
spec.cpp:
#include <iostream>
#include "spec.h"
int main()
{
A a;
a.test<int>("int");
a.test<float>("float");
return 0;
}
compilation:
$ make
rm -f *.o lib.a output
clang++ -g other.cpp -c
clang++ -g spec.cpp -c
ar cr lib.a other.o
clang++ -g -o output lib.a spec.o
rm -f *.o output2
clang++ -g other.cpp -c
clang++ -g spec.cpp -c
clang++ -g -o output2 other.o spec.o
$ ./output
DEFAULT CALLED WITH int
DEFAULT CALLED WITH float
$ ./output2
DEFAULT CALLED WITH int
SPECIAL CALLED WITH float
question:
Why is this happening? is it getting stripped somehow? what is the difference between lib.a and direct object file usage? 🙂
Thanks!
From section 14.7.3p6:
Your program is ill-formed because you used the specialization in spec.cpp without declaring it first in that translation unit. Or, as the following paragraph says:
which I vote for as the awesomest
paragraphlimerick in the whole Standard.