Czytałem o funkcjach szablonów i ten problem mnie pomieszał:
#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)
}
Wyniki są takie same, jeśli nie piszę template void g<double>(double);
.
Myślę, że g<double>
powinien zostać f(double)
utworzony później , a zatem wezwanie do f
w g
powinno zadzwonić f(double)
. Zaskakująco, to nadal nazywa f(int)
się g<double>
. Czy ktoś może mi pomóc to zrozumieć?
Po przeczytaniu odpowiedzi zorientowałem się, jakie jest moje zamieszanie.
Oto zaktualizowany przykład. Jest to w większości niezmienione oprócz tego, że dodałem specjalizację dla 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)
}
Dzięki specjalizacji użytkownika g(1.0)
zachowuje się tak , jak się spodziewałem.
Czy kompilator nie powinien automatycznie wykonywać tej samej instancji g<double>
w tym samym miejscu (lub nawet później main()
, jak opisano w sekcji 26.3.3 języka programowania C ++ , wydanie 4)?
g(1)
dajei f(int)
mi. Napisałeśd f(double)
. Czy to była literówka?