How can I declare a pointer based on a generic type?
type
Pointer<T> = record
public type
Ty = ^T;
end;
Now you can use this generic pointer anywhere
type A = class
procedure<T> DoStuff(tPtr: Pointer<T>.Ty);
end;
You can move the generic parameter from the class to the method, and use var instead of a pointer type:
type
TMyGeneric = record
class procedure DoStuff<T>(var aParam: T); static;
end;
var
int : Integer;
s : string;
...
TMyGeneric.DoStuff<Integer>(int);
TMyGeneric.DoStuff<string>(s);
EDIT: Unfortunately the Delphi compiler doesn't seem to be able to perform type inference when var parameters are used which makes it necessary to explicitly specify the generic paramter type using <..> on the method calls.
Without the "var" the <..> can be omitted (but then the method can no longer modify the passed in variable).
To do this you need to declare a pointer type as a nested type in the generic class:
type
TMyGeneric<T> = class
type
P = ^T;
public
procedure DoStuff(tPtr: P);
end;
And if you want a class method (i.e. not an instance method) you can do it this way:
type
TMyGeneric<T> = record
type
P = ^T;
public
class procedure DoStuff(tPtr: P); static;
end;
var
int: Integer;
...
TMyGeneric<Integer>.DoStuff(@int);
Or using a var parameter:
type
TMyGeneric<T> = record
public
class procedure DoStuff(var a: T); static;
end;
It seems to be common to use records rather than classes for generic types that don't ever get instantiated.
Finally, you cannot have, in Delphi, a generic method without making the class generic. In other words there is no analogue of the following C++ template code:
Thorsten's answer shows how to implement a generic method without making the class generic, that is the Delphi analogue of of the following C++ template code:
class C {
public:
template <typename T>
int SomeTemplateFunction(T* data) {
printf("Address of parameter is %p\n", data);
return 0;
}
};
int a;
char c;
C cinst;
cinst.SomeTemplateFunction<int>(&a);
cinst.SomeTemplateFunction<char>(&c);
Thorsten's answer gives you a class function but in the comments you state you are looking for a normal member function.
type
TMyClass = class
public
procedure DoStuff<T>(var a: T);
end;
procedure TMyClass.DoStuff<T>(var a: T);
begin
end;
...
var
instance: TMyClass;
i: Integer;
s: string;
...
instance.DoStuff<Integer>(i);
instance.DoStuff<string>(s);
However, what I'm struggling with is how exactly you could do anything very useful with this, in Delphi, that could not be done just as effectively without a generic solution.
I'd appreciate any suggestions and would be happy to edit the answer to accommodate them.