函数匹配const类型和参数类型的参数和T

时间:2013-08-23 18:12:49

标签: c++ c++11

我对类型Tconst T&的参数的c ++函数匹配有疑问。 假设我有以下两个函数:

void f(int i) {}
void f(const int &ri) {}

如果我使用f类型的参数调用const int,那么此调用当然是不明确的。但是为什么fint类型的参数的调用也不明确? f的第一个版本不是完全匹配而第二个版本不匹配,因为int参数必须转换为const int吗?

const int ci = 0;
int i = 0;
f(ci); // of course ambiguous
f(i); // why also ambiguous?

我知道这种重载没有多大意义,因为f的调用几乎总是不明确的,除非参数类型T没有可访问的复制构造函数。但我只是研究功能匹配的规则。

此致 凯文

编辑:让我的问题更清楚。如果我有两个功能:

void f(int *pi) {}
void f(const int *pi) {}

然后以下调用不明确:

int i = 0;
f(&i); // not ambiguous, first version f(int*) chosen

虽然可以使用f调用&i的两个版本,但是选择了第一个版本,因为f的第二个版本将包含到const.的转换,即第一个版本是“更好的匹配”。但在两个功能中:

void f(int i) {} and
void f(const int &ri) {}

由于某种原因,这种对const的额外转换似乎被忽略了。同样,f的两个版本都可以使用int进行调用。但同样,f的第二个版本需要转换为const,这会使其与第一个版本f(int).

相比更糟糕
int i = 1;
// f(int) requires no conversion
// f(const int &) does require a const conversion
// so why are both versions treated as "equally good" matches?
// isnt this analogous to the f(int*) and f(const int*) example?
f(i); // why ambiguous this time?

3 个答案:

答案 0 :(得分:3)

一个调用涉及“左值到右值转换”,另一个调用需要身份转换(用于引用)或“资格调整”(用于指针),并且根据标准,这些被同等对待重载决议。

enter image description here

因此,基于不同的转换,两者都不是更好。

然而,标准第13.3.3.2节中有一条特殊规则,只有在被比较的两个候选人都通过参考获取参数时才适用。

  

如果...... S1S2是参考绑定(8.5.3),则标准转换序列S1是比标准转换序列S2更好的转换序列,并且引用引用的类型与顶级 cv-qualifiers 相同,类型相同,S2引用的引用引用的类型更多 cv-qualified S1初始化的引用所引用的类型。

指针有一个相同的规则。

因此编译器会更喜欢

f(int*);
f(int&);

f(const int*);
f(const int&);

分别对f(int) vs f(const int) vs f(const int&)没有偏好,因为左值到右值的转换和资格调整都被视为“完全匹配”。


同样相关,来自第13.3.3.1.4节:

  

当引用类型的参数直接绑定到参数表达式时,隐式转换序列是标识转换,除非参数表达式的类型是参数类型的派生类,在这种情况下隐式转换序列是派生到基础的转换。

答案 1 :(得分:1)

第二个电话f(i)也不明确,因为void f(const int &ri)表示ri是对i的引用,并且是一个常量。这意味着它不会修改传递给该函数的原始i

是否修改传递的参数的选择权在函数的实现者手中,而不是客户程序员使用该函数。

答案 2 :(得分:0)

第二个调用f(i)不明确的原因是因为对编译器来说,这两个函数都是可以接受的。 const-ness不能用于重载函数,因为函数的不同const版本可以用于单个原因。所以在你的例子中:

int i = 0;
fi(i);

编译器如何知道您打算调用哪个函数? const限定符仅与函数定义相关。

有关更详细的说明,请参阅const function overloading