函数的匹配类型const T&和T [英] Function Matching for parameters of type const T& and T

查看:242
本文介绍了函数的匹配类型const T&和T的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于类型 T const T& 的参数的c ++函数匹配的问题。假设我有以下两个函数:

  void f(int i){} 
void如果我调用 f

/ code>的类型为 const int 的参数,那么这个调用当然是模糊的。但是为什么调用 f 的类型为 int 的参数也不明确?不会是 f 的第一个版本是完全匹配,而第二个版本更糟糕的匹配,因为 int 参数必须转换为 const int

  const int ci = 0; 
int i = 0;
f(ci); //当然不明确
f(i); //为什么还有歧义?

我知道这种重载没有什么意义,因为调用 f 几乎总是含糊的,除非参数类型T没有可访问的拷贝构造函数。但我只是研究函数匹配的规则。



注意,
Kevin



:让我的问题更清楚。如果我有两个函数:

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

然后,以下调用不含糊:

  int i = 0; 
f(& i); //不明确,第一个版本f(int *)选择

可以使用& i 调用第一个版本的c> f ,因为 f 将包括转换为 const。也就是说,第一个版本是一个更好的匹配。但是在两个函数中:

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

这另外转换为 const 似乎由于某种原因被忽略。再次,可以使用 int 调用 f 的两个版本。但是,再次, f 的第二个版本需要转换为 const ,这将使它比第一个版本 f(int)。

  int i = 
// f(int)不需要转换
// f(const int&)需要一个const转换
//为什么两个版本都被视为同等好的匹配?
// isnt这类似于f(int *)和f(const int *)example?
f(i); //为什么这个时候不明确?


解决方案

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



>





但是,标准中有一条特殊规则,第13.3.3.2节,只适用于两个候选人


标准转换序列 S1 是更好的转换序列比标准转换序列 S2 如果... S1 S2 是引用绑定(8.5.3),引用引用的类型除顶层 cv-qualifiers 之外是相同类型,引用初始化为 S2 是指比 S1 引用的引用所引用的类型更多的cv限定的。


指针有相同的规则。



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

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

,但没有偏好 f(int) vs f(const int) vs f(const int&),因为lvalue到rvalue变换






同样与第13.3.3.1.4节相关:


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



I have a question regarding the c++ function matching for parameters of types T and const T&. Let's say I have the following two functions:

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

If I call f with an argument of type const int then this call is of course ambiguous. But why is a call of f with an argument of type int also ambiguous? Wouldn't be the first version of f be an exact match and the second one a worse match, because the int argument must be converted to a const int?

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

I know that such kind of overloading doesn't make much sense, because calls of f are almost always ambiguous unless the parameter type T doesn't have an accessible copy constructor. But I'm just studying the rules of function matching.

Regards, Kevin

EDIT: To make my question more clear. If I have the two functions:

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

Then the following call is not ambiguous:

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

Although both versions of f could be called with &i the first version is chosen, because the second version of f would include a conversion to const. That is, the first version is a "better match". But in the two functions:

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

This additional conversion to const seems to be ignored for some reason. Again both versions of f could be called with an int. But again, the second version of f would require a conversion to const which would make it a worse match than the first version 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?

解决方案

One call involves an "lvalue-to-rvalue conversion", the other requires an identity conversion (for references) or a "qualification adjustment" (for pointers), and according to the Standard these are treated equally when it comes to overload resolution.

So, neither is better on the basis of differing conversions.

There is, however, a special rule in the Standard, section 13.3.3.2, that applies only if both candidates being compared take the parameter by reference.

Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if ... S1 and S2 are reference bindings (8.5.3), and the types to which the references refer are the same type except for top-level cv-qualifiers, and the type to which the reference initialized by S2 refers is more cv-qualified than the type to which the reference initialized by S1 refers.

There's an identical rule for pointers.

Therefore the compiler will prefer

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

over

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

respectively, but there's no preference for f(int) vs f(const int) vs f(const int&), because lvalue-to-rvalue transformation and qualification adjustment are both considered "Exact Match".


Also relevant, from section 13.3.3.1.4:

When a parameter of reference type binds directly to an argument expression, the implicit conversion sequence is the identity conversion, unless the argument expression has a type that is a derived class of the parameter type, in which case the implicit conversion sequence is a derived-to-base Conversion.

这篇关于函数的匹配类型const T&和T的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆