如何使用包含的转换的排名来比较两个标准转换序列

2024-05-13

#include <iostream>
void g(int*);  //#1
void g(int (&arr)[2]);  //#2

void f(int*);  //#3
void f(int const*);  //#4
int main(){
  int arr[2] ={0};
  f(arr);    // choose #3
  g(arr);  //ambiguous
}

考虑上面的代码,#3被选择为f(ptr), 然而,g(arr)给出一个ambiguous诊断。

选择最佳函数的规则定义为:

标准转换序列 S1 是比标准转换序列 S2 更好的转换序列,如果

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

所以看看over.ics.scs#3 https://timsong-cpp.github.io/cppwp/n4659/over.ics.scs#3

这些用于对标准转换序列进行排名。转换序列的等级是通过考虑序列中每个转换的等级和任何参考绑定的等级来确定的。

根据我对上述规则的理解,我可以理解为什么#3是最好的过载f(ptr), 那是:

给定 S1 为 (arr => int*):

Array-to-pointer conversion -> (identity conversion)  
^^^^^^^^^^^^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^^^^^^^                   
     int[2] => int*             int* => int* 

而给定 S2 为 (ptr => int const*)

Array-to-pointer conversion -> Qualification conversions ->  identity conversion   
^^^^^^^^^^^^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^^^^^^^^^^^     ^^^^^^^^^^^^^^^^^^^ 
     int[2] => int*               int* => int const*           int const* => int const* 

Since identity conversion是一个真子序列Qualification conversions,因此 S1 优于 S2。所以,#3由重载决议选择f(ptr).

当我使用类似的过程来确定哪个最适合时g(arr),我遇到一个问题。

再次,将 S1 指定为 (arr => int*)

Array-to-pointer conversion -> identity conversion  
^^^^^^^^^^^^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^^^^^^^ 
      int[2] => int*              int* => int*

而给定 S2 as(arr => int (&arr)[2])

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

identity conversion
^^^^^^^^^^^^^^^^^^^
  bind to reference   

Here, identity conversion of S2是一个真子序列Array-to-pointer conversion of S1,因此它应该比S1,为什么编译器会抱怨g(arr)是一个不明确的调用?

我对如何对标准转换序列进行排名有任何误读吗?如何比较两个标准ICS(所包含转换的排名)?


关键点就在这里:

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

这意味着,对于函数调用g(arr), all 数组到指针的转换不用于确定排名。换句话说,从类型int[2]输入int*,只有一个身份转换用于确定排名。因此,S1为void g(int*);和S2void g(int (&arr)[2]);是无法区分的 ICS,因此编译器会给出一个不明确的错误。

作为对比,转换为void f(int*); and void f(int const*);用于比较排名的是identity conversion and qualification conversion, 分别。

根据规则:

身份转换序列被认为是任何非身份转换序列的子序列

Hence, Qualification conversion被认为排名比identity conversion. So, void f(int*)赢得了比赛。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用包含的转换的排名来比较两个标准转换序列 的相关文章

随机推荐