[fpc-pascal] Generic type conflicts

Michael Van Canneyt michael at freepascal.org
Fri Nov 8 07:32:48 CET 2019

On Thu, 7 Nov 2019, Ben Grasset via fpc-pascal wrote:

> On Thu, Nov 7, 2019 at 10:23 AM Michael Van Canneyt <michael at freepascal.org>
> wrote:
>> If I understood Sven's example correct, then the compiler does exactly this
>> already.
> It does in the sense of *code generation* for things that are specifically
> compiler intrinsics (which I was aware of), but not in a sense that makes
> the issue Ryan was posting about here avoidable. Maybe this will explain
> what I'm trying to get at a bit better:
> program Example;
> {$mode ObjFPC}
> // Without actually specializing and using GDiv,
> // this program compiles fine.
> generic function GDiv<T>(const A, B: T): T; inline;
> begin
>  if GetTypeKind(T) in [tkInteger, tkInt64, tkQWord] then
>    Result := A div B
>  else if GetTypeKind(T) = tkFloat then
>    Result := A / B
>  else
>    Result := Default(T);
> end;
> // However, once we do specialize it...
> procedure UseGDiv;
> begin
>  // Example.pas(13,17) Error: Incompatible types: got "Double" expected
> "Int64"
>  WriteLn(specialize GDiv<Int64>(1, 2));
>  // Example.pas(11,17) Error: Operator is not overloaded: "Double" div
> "Double"
>  WriteLn(specialize GDiv<Double>(1, 2));
> end;

Thanks for the explanation. All is clear.

As an aside:
In my opinion (keep in mind I am not a big fan of generics) the above code
would be a prime example where one should not be using generics, but simple overloads.
If you need to use GetTypeKind in a generic, I think you're on the wrong path. 
Use of IsManagedType() in a generic is stretching it, but GetTypeKind() is over the line.


More information about the fpc-pascal mailing list