Eu estava lendo sobre funções de modelo e fiquei confuso com este problema:
#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)
}
Os resultados são os mesmos se eu não escrever template void g<double>(double);
.
Eu acho que g<double>
deveria ser instanciado depois f(double)
e, portanto, a chamada para f
in g
deveria chamar f(double)
. Surpreendentemente, ele ainda chama f(int)
no g<double>
. Alguém pode me ajudar a entender isso?
Depois de ler as respostas, descobri qual é realmente a minha confusão.
Aqui está um exemplo atualizado. É praticamente inalterado, exceto que eu adicionei uma especialização para 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)
}
Com a especialização do usuário, g(1.0)
comporta-se como eu esperava.
O compilador não deve fazer automaticamente essa mesma instanciação g<double>
no mesmo local (ou mesmo depois main()
, conforme descrito na seção 26.3.3 da Linguagem de programação C ++ , 4ª edição)?
g(1)
, dái f(int)
para mim. Você escreveud f(double)
. Isso foi um erro de digitação?