首页 > 解决方案 > 如何比较两个标准转换序列使用包含转换的等级

问题描述

#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] 定义的规范形式的转换序列,不包括任何 Lvalue 转换;恒等转换序列被认为是任何非恒等转换序列的子序列)或,如果不是这样

所以看看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* 

由于 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   

在这里,identity conversionof是ofS2的正确子序列,因此它应该比 更好,为什么编译器抱怨是一个模棱两可的调用?Array-to-pointer conversionS1S1g(arr)

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

标签: c++language-lawyer

解决方案


关键点在这里:

S1 是 S2 的适当子序列(比较 [over.ics.scs] 定义的规范形式的转换序列,不包括任何 Lvalue Transformation;恒等转换序列被认为是任何非恒等转换序列的子序列)或,如果不是这样

这意味着,对于函数调用g(arr),所有数组到指针的转换都不会用于确定排名。换句话说,从 typeint[2]到 type int*,只有一个用于确定排名的身份转换。因此,S1 ofvoid g(int*);和 S2 ofvoid g(int (&arr)[2]);是无法区分的 ICS,因此编译器给出了一个模棱两可的错误。

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

根据规则:

恒等转换序列被认为是任何非恒等转换序列的子序列

因此,Qualification conversion被认为比 的排名更差identity conversion。所以,void f(int*)赢得了比赛。


推荐阅读