#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
}
Consider the above code, #3 is seleteced for f(ptr), however, g(arr) gives a ambiguous diagnostic.
The rule for choosing the best function is defined as:
Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if
- S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form defined by [over.ics.scs], excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence) or, if not that
So take a look at over.ics.scs#3
These are used to rank standard conversion sequences. The rank of a conversion sequence is determined by considering the rank of each conversion in the sequence and the rank of any reference binding.
According to my understanding of the above rule, I can understand why #3 is the best overload for f(ptr), that is:
Given S1 as (arr => int*):
Array-to-pointer conversion -> (identity conversion)
^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
int[2] => int* int* => int*
while given S2 as (ptr => int const*)
Array-to-pointer conversion -> Qualification conversions -> identity conversion
^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
int[2] => int* int* => int const* int const* => int const*
Since identity conversion is a proper subsequence of Qualification conversions, hence S1 is better than S2. So, #3 is selected by overload resolution for f(ptr).
When I use a similar process to determine which is best for g(arr), I encounter an issue.
Again, given S1 as (arr => int*)
Array-to-pointer conversion -> identity conversion
^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^
int[2] => int* int* => int*
while given S2 as(arr => int (&arr)[2])
When a parameter of reference type binds directly to an argument expression, the implicit conversion sequence is the identity conversion, unless the argument expression has a type that is a derived class of the parameter type, in which case the implicit conversion sequence is a derived-to-base Conversion
identity conversion
^^^^^^^^^^^^^^^^^^^
bind to reference
Here, identity conversion of S2 is a proper subsequence of Array-to-pointer conversion of S1, hence it should be better than S1, why the compiler complained g(arr) is an ambiguous invocation?
Do I have any misreading about how to rank the standard conversion sequences? How to compare two standard ICS (rank of the contained conversion)?