I was reading about template functions and got confused by this problem:
#include <iostream>
void f(int) {
std::cout << "f(int)\n";
}
template<typename T>
void g(T val) {
std::cout << typeid(val).name() << " ";
f(val);
}
void f(double) {
std::cout << "f(double)\n";
}
template void g<double>(double);
int main() {
f(1.0); // f(double)
f(1); // f(int)
g(1.0); // d f(int), this is surprising
g(1); // i f(int)
}
The results are the same if I don't write template void g<double>(double);
.
I think g<double>
should be instantiated after f(double)
, and therefore the call to f
in g
should call f(double)
. Surprisingly, it still calls f(int)
in g<double>
. Can anyone help me understand this?
After reading the answers, I figured out what my confusion really is.
Here is an updated example. It is mostly unchanged except that I added a specialization for g<double>
:
#include <iostream>
void f(int){cout << "f(int)" << endl;}
template<typename T>
void g(T val)
{
cout << typeid(val).name() << " ";
f(val);
}
void f(double){cout << "f(double)" << endl;}
//Now use user specialization to replace
//template void g<double>(double);
template<>
void g<double>(double val)
{
cout << typeid(val).name() << " ";
f(val);
}
int main() {
f(1.0); // f(double)
f(1); // f(int)
g(1.0); // now d f(double)
g(1); // i f(int)
}
With the user specialization, g(1.0)
behaves as I expected.
Should the compiler not automatically do this same instantiation for g<double>
in the same place (or even after main()
, as described in section 26.3.3 of The C++ Programming Language, 4th edition)?
g(1)
, givesi f(int)
for me. You wroted f(double)
. Was this a typo? – Meridith