我有以下代码,我试图理解为什么在第一次调用 fun() 时,编译器选择模板而不是非模板重载 void fun(const int*)。
#include <iostream>
struct test
{
void fun(const int*)
{
std::cout<<"const int * overload\n";
}
template<typename T>
void fun(const T&)
{
std::cout<<"template"<<'\n';
}
};
int main(){
test t{};
int * int_ptr;
t.fun(int_ptr);
const int * const_int_ptr;
t.fun(const_int_ptr);
}
在您的代码中,您有两个
fun
函数的重载:
void fun(const int*)
template<typename T> void fun(const T&)
当您调用
t.fun(int_ptr);
时,编译器需要决定使用哪个重载。这是关键点:仅当没有非模板函数提供更好的匹配时才考虑模板函数。
在本例中,
int_ptr
的类型为 int*
。非模板重载 void fun(const int*)
需要一个 const int*
,从编译器的角度来看,与 int*
相比, 是不同的类型。编译器需要执行从 int*
到 const int*
的转换,这是允许的,但不是最佳匹配。
另一方面,模板函数
template<typename T> void fun(const T&)
可以实例化为T
为int*
,使参数类型为const int*&
。这是一个更好的匹配,因为它不需要任何转换。
因此,编译器为第一次调用选择模板重载,因为它更匹配
int*
。
对于第二次调用,
t.fun(const_int_ptr);
,const_int_ptr
的类型为const int*
,与非模板重载void fun(const int*)
完全匹配。因此,选择非模板重载。
为了进一步说明不同类型之间的差异,请考虑使用
float
和 double
的示例:
struct test
{
void fun(double)
{
std::cout << "double overload\n";
}
template<typename T>
void fun(T)
{
std::cout << "template\n";
}
};
int main(){
test t{};
float f = 1.0f;
double d = 1.0;
t.fun(f); // Calls the template because float and double are different types
t.fun(d); // Calls the non-template overload because it matches exactly
}
在此示例中:
t.fun(f);
调用模板,因为 float
和 double
是不同的类型,而模板更适合 float
。t.fun(d);
调用非模板重载,因为 double
完全匹配。以下是代码中调用的摘要:
t.fun(int_ptr);
与 template<typename T> void fun(const T&)
搭配更佳。t.fun(const_int_ptr);
与 void fun(const int*)
完全匹配。我希望这能澄清编译器做出这些选择的原因!如果您还有任何疑问,请随时提问。