我有以下代码:
void A(const int*)
{
cout << "const int*" << endl;
}
void A(const int&)
{
cout << "const int&" << endl;
}
template <typename T>
void B(const T*)
{
cout << "const T*" << endl;
}
template <typename T>
void B(const T&)
{
cout << "const T&" << endl;
}
int main()
{
int* a = nullptr;
A(a); //output: const int*
int* b = nullptr;
B(b); //output: const T&
return 0;
}
A(a)
正在调用函数A(const int*)
B(b)
正在调用模板函数B(const T&)
由于重载解析的工作方式,我对模板行为并不感到惊讶。但我无法解释为什么非模板化函数返回相反的结果(这有点更直观)。
是否因为使用非模板化函数不需要推导出类型并且被认为是完全匹配(添加常量是否被允许?)?
我不是元编程的专家和编译器正在做的事情(比如重载解析),这就是我有点困惑的原因。
答案 0 :(得分:4)
在对非模板的调用中,您正在传递指向int的指针。那怎么能调用期望引用int的函数呢?这两种是完全不同的类型。是的,允许添加const。如果你在constness上超载了:
void A(const int*)
{
cout << "const int*" << endl;
}
void A(int*)
{
cout << "int*" << endl;
}
非const版本将被选为更好的匹配。
使用模板,情况有所不同。请记住,指针也是类型。将T
推导为指针类型同样有效。当您调用B(b)
时,编译器可以使用此函数:
template <typename T>
void B(const T*)
{
cout << "const T*" << endl;
}
在这种情况下,T
必须推断为int
,const T*
变为const int*
,指向const int的指针。
或者编译器可以选择此功能:
template <typename T>
void B(const T&)
{
cout << "const T&" << endl;
}
在这种情况下,T
推断为int*
。然后const T&
变为int* const&
,即对指向int的const指针的引用。
因为,在第二种情况下,T
完全映射到实际传入的内容(指向int的指针),这是更好的匹配。
答案 1 :(得分:0)
不,行为没有区别。
使用B,T解析为int*
,第二次重载
int* const&
是比第一次重载更好的匹配
int const*
请注意,两者都是可行的,只是第一个更好。所以基本上模板可以让你获得最多的访问权限。
对于A,实际上只有一个选项,因为指针不能转换为引用,那就是删除const。