【问题标题】:Is an identity conversion of pointer type be considered as qualification conversion when ranking排名时指针类型的恒等转换是否视为资格转换
【发布时间】:2020-12-14 02:11:03
【问题描述】:
void fun(int*);  // #1
void fun(int const*);  //#2
int main(){
  int* ptr = nullptr;
  fun(ptr);
}

考虑上面的例子,重载决议应该在#1#2中选择最好的可行函数。这是this question的一个分支,即[over.ics.rank#3.2.1]和[over.ics.rank#3.2.5]之间的模糊。

相关规则为:

over.ics.rank#3.2.1

S1是S2的一个真子序列(比较[over.ics.scs]定义的规范形式的转换序列,不包括任何左值变换;恒等转换序列被认为是任何非- 身份转换序列)或者,如果不是那个

IMO,S1#1 有一个身份转换,而 S2#2 有一个资格转换,上面的规则似乎是说Identity conversion 比任何有一个非身份转换更好完全匹配排名。

不过,还有一条相关规则对应本案,即:
over.ics.rank#3.2.5

S1 和 S2 的区别仅在于它们的限定转换 ([conv.qual]) 并分别产生相似的类型 T1 和 T2,其中 T1 可以通过限定转换转换为 T2。

IMO,这条规则似乎说S1S2 都有资格转换,但这些转换不同,T1 可以通过资格转换转换为T2

在我的示例中,从int*int const* 绝对是资格转换。但是,一个极端情况是从int*int*,这种转换是身份转换还是资格转换?根据conv.qual#3的定义,可以。不过严格来说应该叫身份转换

问题一:

我对规则 [over.ics.rank#3.2.5] 的理解正确吗?或者,这是否意味着,T1 可以通过资格转换转换为T2 时,S1 可能有一个空转换(例如身份转换)? (包括指针的身份转换)

Q问题2:

指针类型的恒等转换被认为是限定转换还是只是恒等转换?换句话说,[over.ics.rank#3.2.1] 或 [over.ics.rank#3.2.5] 是否适用于我的示例?

【问题讨论】:

  • 我建议链接到激发您的问题的Q&A。一般而言,这种归因是良好的做法。它为读者提供了有用的上下文来理解您的问题,并且可以帮助澄清您难以理解的标准规则的哪些部分。这可以带来更量身定制、质量更高的答案,从而提高整个问答的质量。
  • @cigien 是的,一个很好的建议。我打算这样做。
  • 感谢您的编辑,它大大改善了问题。
  • @cigien 我认为这个问题是一个极端情况。也许,[over.ics.rank#3.2.1] 和 [over.ics.rank#3.2.5] 都可以处理这种重载决议。只是,[over.ics.rank#3.2.1] 首先适用于这种情况。这是我对你和我之间的讨论的看法Q&A

标签: c++ language-lawyer


【解决方案1】:

int*int* 的标准转换序列包含限定转换。

[over.ics.best.general]/8 明确说明了这一点:

如果不需要转换来将参数与参数类型匹配,则隐式转换序列是由恒等转换 ([over.ics.scs]) 组成的标准转换序列。

也可以从其他段落中推断出来。例如,参见[over.best.ics.general]/1:

隐式转换序列是用于将函数调用中的参数转换为被调用函数的相应参数类型的转换序列。 转换序列是 [conv] 中定义的隐式转换,这意味着它受用于初始化对象或单个表达式([dcl.init]、[dcl.init.ref])的引用的规则控制。

和[over.ics.best.general]/6:

当参数类型不是引用时,隐式转换序列模拟参数表达式中参数的复制初始化。 隐式转换序列是将参数表达式转换为参数类型的纯右值所需的序列。
...

也就是说,int* -> int* 的正确隐式转换序列是根据语言规则,通常在 int*int* 复制初始化时形成的。在这种情况下,[dcl.init.general]/16.9 适用:

否则,被初始化对象的初始值是初始化表达式的(可能转换的)值。 如有必要,将使用标准转换序列 ([conv]) 将初始化表达式转换为目标类型的 cv 非限定版本;不考虑用户定义的转换。 如果无法完成转换,则初始化格式错误。 当使用无法表示的值初始化位域时,位域的结果值是实现定义的。

没有转换是必要的,因为int*int* 已经是相同的类型,所以没有进行转换。这不是从int* 到自身的资格转换。

这意味着 [over.ics.rank]/3.2.1 肯定是决定性的:S1 是身份转换序列(不是由冗余限定转换组成的隐式转换序列),因此它是 S2 的子序列。

【讨论】:

  • 谢谢,你的理解跟我差不多。但是,对于[dcl.init.general]/16.9,即使目标类型与源类型相同,我认为lvalue-to-rvalue转换仍然适用于源初始化程序以便读取值(评估prvalue将初始化结果目的 )。或int* constint*。(左值到右值仍然适用)。但是,正如 [over.ics.rank#3.2.1] 所说,lvalue-to-rvalue 不参与排名的评估。所以,lvalue-to-rvalue 不影响排名
猜你喜欢
  • 2021-09-20
  • 2019-08-21
  • 2013-04-07
  • 2011-12-29
  • 2020-11-17
  • 1970-01-01
  • 2020-06-15
  • 1970-01-01
相关资源
最近更新 更多