[英]Template function overloading in C++
我有以下定义。
using namespace std;
template <typename T>
void foo(const T &s) {
cout << 1;
}
template <typename T>
void foo(const T *s) {
cout << 2;
}
int main(int argc, const char * argv[]) {
char str[] = "ss";
char *s = str;
foo(s);
return 0;
}
然后输出
1
根据我的理解,两个版本都必须经过const转换。 然后void foo(const T *s)
更专业,应该被调用。 但是编译器选择了void foo(const T& s)
。 解释是什么?
有人指出编译器选择的模板参数
void f(char * const&)
void f(const char *);
在这里,请注意编译器需要一个指向char, char*
的指针作为第一个函数,它是一个const引用。 可能会出乎意料,如果您发现对于您的情况它更喜欢第一个模板,但对于以下两个模板, 它会更喜欢第二个模板
template <typename T>
void foo(const T& s) {
cout << 1;
}
template <typename T>
void foo(T &s) {
cout << 2;
}
所以,当然,它有时会看到const。 为什么不在你的情况下呢? 因为如果另一个函数也有引用,它只会查看const
作为引用。
在你的情况下,从char*
到const char*
它是一个指针转换,但从lvalue
到const lvalue
,它实际上不是转换。 通过const引用添加const将被重载决策忽略,除非两个函数都具有上述情况中的引用参数。
原因是因为s是非const指针,所以int * const&实际上是比int const *更好的匹配,因为它不必将const添加到指针类型。
如果s是const限定的,那么它将与T const *版本完全匹配。
我已经移动了const
而没有改变代码的语义,所以当const
的位置稍后“改变”时你不会感到惊讶。
template <typename T>
void foo(T const &s) {
cout << 1;
}
template <typename T>
void foo(T const *s) {
cout << 2;
}
char *x = "x";
foo(x);
重载1必须将T
推导为char*
因此s
的类型将是char * const &
(引用指向非const char
const指针)。 这样的引用可以绑定到参数类型( char *
;指向非const char
指针)而不进行任何转换。
重载2必须将T
推导为char
因此s
的类型将是char const *
(指向const char
指针)。 这会导致从参数类型( char *
;指向非const char
指针)到参数类型( char const *
;指向const char
指针)的限定转换。
过载1中的原理的更多说明性示例如下:
int n = 42;
int const &i = n;
将const引用绑定到非const实体不涉及转换,因为它是添加限定条件的引用,它不是为了将它与引用类型匹配而添加到实体的限定条件。
两个版本都必须经过const转换。
第一个不需要转换。 对于模板参数const T&
with template argument char *
, T
将推导为char*
,然后函数参数的类型将为char* const &
,因此它是完美匹配。 函数参数将被绑定为引用const( T
- > const T&
,即char*
到char* const&
),const qualified不是转换。
对于第二个,模板参数const T*
与模板参数char *
, T
将推导为char
,然后函数参数的类型将是const char*
,并且需要限定转换以将char*
转换为const char*
。
从你的评论
这两个例程都为
s
添加了低级const。
第一个是向s
添加const
,但第二个不是。 它将const
添加到s
指向的内容,而不是s
本身。 这是不同的。
原因是因为当参数是一个指针时,你必须传入一个指针..像这样:
// Example program
#include <iostream>
#include <string>
using std::cout;
using std::endl;
void foo(int *a)
{
cout << *a << endl;
}
int main()
{
int a = 5;
foo(&a);
}
但是如果你的参数是一个参考,你可以传递参数,如下所示:
// Example program
#include <iostream>
#include <string>
using std::cout;
using std::endl;
void foo(int &a)
{
cout << a << endl;
}
int main()
{
int a = 5;
foo(a);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.