How function overload resolution proceeds when function template instantiations, function template specializations, and ordinary functions of the same name are involved:
#include <iostream>
template <class T>
void foo(T, int){
std::cout << "Version 1" << std::endl;
}
void foo(double, double){
std::cout << "Version 2" << std::endl;
};
int main(){
// Calls "Version 1"
foo(2.0, 1);
return 0;
}
#include <iostream>
template <class T>
void foo(T*, int){
std::cout << "Version 1" << std::endl;
}
void foo(double, double){
std::cout << "Version 2" << std::endl;
};
int main(){
// Calls "Version 2"
// Since we fail to decuce T in "Version 1"
foo(2.0, 1);
return 0;
}
#include <iostream>
template <class T>
void foo(T, int){
std::cout << "Version 1" << std::endl;
}
template<>
void foo<double>(double, int){
std::cout << "Version 2" << std::endl;
}
void foo(double, double){
std::cout << "Version 3" << std::endl;
};
int main(){
// Calls "Version 2"
// Priority of specializd template is higher than generic template
foo(2.0, 1);
return 0;
}
#include <iostream>
template <class T>
void foo(T, T){
std::cout << "Version 1" << std::endl;
}
template<>
void foo<double>(double, double){
std::cout << "Version 2" << std::endl;
}
void foo(double, double){
std::cout << "Version 3" << std::endl;
};
int main(){
// Calls "Version 3"
foo(2.0, 1);
return 0;
}
#include <iostream>
template <class T>
void foo(T){
std::cout << "Version 1" << std::endl;
}
void foo(double){
std::cout << "Version 2" << std::endl;
};
int main(){
// Calls "Version 2"
foo(2.0);
return 0;
}
#include <iostream>
template <class T>
void foo(T){
std::cout << "Version 1" << std::endl;
}
void foo(double);
int main(){
// Error: undefined reference
foo(2.0);
return 0;
}
foo<int>(int,int) and we want this function to be invoked when foo() is called with arguments of any integer type, whether or not the arguments have the same type.
#include <iostream>
template <class T>
void foo(T, int){
std::cout << "Version 1" << std::endl;
}
void foo(int a, int b){
foo<int>(a, b);
}
int main(){
short s = 1;
// Calls "Version 1"
// Note that there are no candidate functions for this call
foo(2, s);
return 0;
}