Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can a generic interface refer to a pointer to its type parameter?

In a nutshell, I want to be able to do something like this (where T is usually a record)

interface
ITable<T> = interface
  ...
  other methods
  ...
  function Append: ^T;
end;

But as we see in a question about declaring pointers based on generic types, Delphi doesn't allow the ^T construction. If this were allowed, I could do stuff like:

var 
  myrec: PMyRec;
  myTable: ITable<TMyRec>;
begin
  myTable := TableFactory.Build(TMyRec);
  myRec := myTable.Append;
  myRec.FieldA := 'Test';
  .. Do stuff with myTable containing myRec
end;

The reason that I want to do this, is that I have a hell of a lot of existing code that is written that way around rather than building up a record then calling a procedure that accepts the built record like MyTable.Add(MyRec), which is the more Delphi-like way.

The solution to the linked question is to use an internal type statement in the generic class, but generic interfaces don't allow type statements.

To get around this, I thought I may be able to use something like the Spring4D interfaced collections using a generic record to return the pointer as so:

ListRec<T> = record
type
  P = ^T;
private
  InternalList = IList<T>;
public
... exposed list functions
  function Append: PT;
end;

function ListRec<T>.Append: PT;
var
  index: integer;
  TempT: TMyRec;
begin
  index := InternalList.add(TempT);
  result := @InternalList.Items[index];
end;

After all that, my question is: Is there an easier way of achieving my objective or have I massively over-complicated it? Are there any obvious downsides (other than the standard risks of working with pointers)? I'd ideally prefer a pure interface solution for testability if nothing else.

like image 819
Matt Allwood Avatar asked Sep 15 '25 07:09

Matt Allwood


1 Answers

In an ideal world, you would be able to declare a generic pointer type directly:

type
  P<T> = ^T;

But the language does not permit this. You can declare generic pointer types but only if they are contained inside another type. For instance:

type
  PointerTo<T> = record
    type
      P = ^T;
  end;

Now your interface can be:

type
  ITable<T> = interface
    function Append: PointerTo<T>.P;
  end;

Frankly, in my opinion, this is rather lame.

like image 79
David Heffernan Avatar answered Sep 18 '25 09:09

David Heffernan