#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(所包含转换的排名)?