Anybody here knows since when we don't have to write <T> when calling generic ProcSomething<T>(param: T)?
It was brought to my attention today that the following code compiles and works as expected and I was quite surprised.
program Project17;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TGeneric = class
class procedure GuessTheType<T>(const value: T);
end;
var
x: Exception;
s: TSimpleRWSync;
{ TGeneric<T> }
class procedure TGeneric.GuessTheType<T>(const value: T);
begin
end;
begin
TGeneric.GuessTheType<Exception>(x);
TGeneric.GuessTheType(x);
TGeneric.GuessTheType(s);
end.
A quick look into the generated assembler code proves that the type is indeed resolved correctly:
Project17.dpr.26: TGeneric.GuessTheType<Exception>(x);
0041C530 8B151C484200 mov edx,[$0042481c]
0041C536 A1F4974100 mov eax,[$004197f4]
0041C53B E84CD3FFFF call TGeneric.GuessTheType<System.SysUtils.Exception>
Project17.dpr.27: TGeneric.GuessTheType(x);
0041C540 8B151C484200 mov edx,[$0042481c]
0041C546 A1F4974100 mov eax,[$004197f4]
0041C54B E83CD3FFFF call TGeneric.GuessTheType<System.SysUtils.Exception>
Project17.dpr.28: TGeneric.GuessTheType(s);
0041C550 8B1520484200 mov edx,[$00424820]
0041C556 A1F4974100 mov eax,[$004197f4]
0041C55B E83CD3FFFF call TGeneric.GuessTheType<System.SysUtils.TSimpleRWSync>
Tested in Berlin and Tokyo.
It was brought to my attention today that the following code compiles and works as expected and I was quite surprised.
program Project17;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils;
type
TGeneric = class
class procedure GuessTheType<T>(const value: T);
end;
var
x: Exception;
s: TSimpleRWSync;
{ TGeneric<T> }
class procedure TGeneric.GuessTheType<T>(const value: T);
begin
end;
begin
TGeneric.GuessTheType<Exception>(x);
TGeneric.GuessTheType(x);
TGeneric.GuessTheType(s);
end.
A quick look into the generated assembler code proves that the type is indeed resolved correctly:
Project17.dpr.26: TGeneric.GuessTheType<Exception>(x);
0041C530 8B151C484200 mov edx,[$0042481c]
0041C536 A1F4974100 mov eax,[$004197f4]
0041C53B E84CD3FFFF call TGeneric.GuessTheType<System.SysUtils.Exception>
Project17.dpr.27: TGeneric.GuessTheType(x);
0041C540 8B151C484200 mov edx,[$0042481c]
0041C546 A1F4974100 mov eax,[$004197f4]
0041C54B E83CD3FFFF call TGeneric.GuessTheType<System.SysUtils.Exception>
Project17.dpr.28: TGeneric.GuessTheType(s);
0041C550 8B1520484200 mov edx,[$00424820]
0041C556 A1F4974100 mov eax,[$004197f4]
0041C55B E83CD3FFFF call TGeneric.GuessTheType<System.SysUtils.TSimpleRWSync>
Tested in Berlin and Tokyo.
- P.S. This is neither bug nor issue but I couldn't find a better category for the post.5h
- AFAIK this has been in the compiler since generic methods in non-generic classes have been introduced. The compiler infers the type from the parameter. Of course, there are times you don't want this to happen -- if the param is 200 you might want to force "Integer" rather then Byte of what the compiler would map the small number to5h
- Type inference for generic methods, described here: "There are two ways to instantiate a method:
- Explicitly specifying type argument
- Automatically inferring from the type argument"
docwiki.embarcadero.com - Declaring Generics - RAD Studio4h - Thank you, guys! I was not aware that this existed at all!4h
- This is a rare piece of code where type inference actually works. Mostly it does not which is very frustrating.
It's a little ironic that you ask why you don't need to include <T>. Normally people ask about the much more frequent instances where you do need to include <T> because the compiler's type inference is so weak.4h - +Marco Cantù Much more commonly there are times when you want the compiler to infer the type, but it won't. It would really make a difference to us if the compiler was better at this.4h
- +David Heffernan I tend to agree the compiler should be much better at type inference. Working on it!3h
- Infering the generic argument from a constructed generic type would be great.
GuessTheType<T>(const x: TArray<T>);
var
a: TArray<Integer>;
begin
GuessTheType(a);
does not work although the compiler could infer the parameter for GuessTheType from its x parameter but currently it does not know that a originally was a TArray<T> (yes, I know array of T as signature works but that is a different thing).
P.S. +Marco Cantù btw how hard can it be to finally implement generic standalone routines without that ugly static type? Probably one of the highest voted feature requests: https://quality.embarcadero.com/browse/RSP-13724)3h