[fpc-devel] Implicit function specialization precedence
Sven Barth
pascaldragon at googlemail.com
Wed Apr 7 07:34:20 CEST 2021
Am 06.04.2021 um 22:47 schrieb Ryan Joseph via fpc-devel:
>
>> On Apr 6, 2021, at 12:57 PM, Sven Barth <pascaldragon at googlemail.com> wrote:
>>
>> In this specific case the two functions also are *not* ambigous, because for the non-generic Test the parameter requires an implicit conversion, but the implicit specialization does not. For example if there would be a "Test(aArg: LongInt)" instead of the generic the compiler would pick that instead of the string one. So if you move the check for generic vs. non-generic to the end of is_better_candidate all the other rules to determine this will take precedence.
> So the root of the problem is that we have no way to choose the generic function via explicit casting? That makes sense and presumably I can use the final result of is_better_candidate to determine this?
You simply need to put your check for generic vs. not-generic after the
check for ordinal_distance inside is_better_candidate instead of at the
start of the function.
> In your example:
>
> Writeln(Test('Hello World')); // is_better_candidate res = -1
> Writeln(Test(42)); // is_better_candidate res = 1
> Writeln(Test(String(42))); // is_better_candidate res = -1
>
> I'm struggling to see how the operator influenced the result. Res is -1 in both cases so how do we know which Test we want to call?
The compiler is free to use implicit operator overloads when determining
the overload to pick.
When the compiler sees the first call to Test it will have the
non-generic Test(String) in its candidate list as well as
Test<String>(String) due to the implicit specialization. Here it will
use the non-generic one.
In the second case the compiler will have the non-generic Test(String)
due to the implicit operator as well as Test<LongInt>(LongInt) due to
the implicit specialization. Here it will pick the generic one, because
a call without a type conversion is considered better.
In the third case the will will contain Test(String) as well as
Test<String>(String) due to the parameter being explicitely casted to
String with the compiler again picking the non-generic one.
Without the explicit cast by the user the compiler would have picked the
Test<LongInt>, but using a cast to the type of non-generic function one
is able to enforce the non-generic function (for example to avoid an
error during specialization if the Test<> function would not be able to
handle the LongInt type).
Regards,
Sven
More information about the fpc-devel
mailing list