jac*_*k X 8 c++ language-lawyer
#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
}
Run Code Online (Sandbox Code Playgroud)
考虑上面的代码,#3被选择为f(ptr),但是,g(arr)给出了一个ambiguous诊断。
选择最佳函数的规则定义为:
标准转换序列 S1 是比标准转换序列 S2 更好的转换序列,如果
- S1是S2的真子序列(比较[over.ics.scs]定义的规范形式的转换序列,不包括任何左值转换;恒等转换序列被认为是任何非恒等转换序列的子序列)或,如果不是这样
所以看看over.ics.scs#3
这些用于对标准转换序列进行排名。转换序列的等级是通过考虑序列中每个转换的等级和任何参考绑定的等级来确定的。
根据我对上述规则的理解,我可以理解为什么#3是最好的重载 for f(ptr),即:
将 S1 设为 (arr => int*):
Array-to-pointer conversion -> (identity conversion)
^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
int[2] => int* int* => int*
Run Code Online (Sandbox Code Playgroud)
将 S2 设为 (ptr => int const*)
Array-to-pointer conversion -> Qualification conversions -> identity conversion
^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
int[2] => int* int* => int const* int const* => int const*
Run Code Online (Sandbox Code Playgroud)
由于 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*
Run Code Online (Sandbox Code Playgroud)
而给定 S2 as(arr => int (&arr)[2])
当引用类型的参数直接绑定到参数表达式时,隐式转换序列是恒等转换,除非参数表达式的类型是参数类型的派生类,在这种情况下,隐式转换序列是派生的 -到基转换
identity conversion
^^^^^^^^^^^^^^^^^^^
bind to reference
Run Code Online (Sandbox Code Playgroud)
在这里,identity conversion的S2是一个正确的序列Array-to-pointer conversion中S1,因此它应该比S1,为什么编译器抱怨g(arr)是一个模糊的调用?
我对如何对标准转换序列进行排名有任何误读吗?如何比较两个标准 ICS(包含转换的等级)?
关键点就在这里:
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*)赢得了比赛。
| 归档时间: |
|
| 查看次数: |
100 次 |
| 最近记录: |