繁体   English   中英

C ++中的模板函数重载

[英]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*它是一个指针转换,但从lvalueconst 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM