Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are pointers to generic types supported in Delphi XE?

I'm on D2010, on which I have to stay until the 64 bit comes out.

With the generics, pointers to generic types are not supported, and I would find them to be very useful indeed. I read elsewhere on SO (2009 posting) Sir Barry Kelly thought this may well change in future. Does anyone know if this is supported in XE?

If not, I really hope they get put into XE2.

Thanks.

like image 761
csharpdefector Avatar asked Jan 08 '11 20:01

csharpdefector


2 Answers

On XE (2011):

This works:

type
  TTest1<T> = record
    FX : T;
  end;

  TTest2<T> = array of T;

This won't work:

type
  TTest3<T> = ^TTest1<T>;
  TTest4<T> = ^TTest2<T>;
  TTest<T> = ^T;

So pointers to generics are not yet possible.

But you can do the following:

type
  TMyClass = class
  public
    class function GetAddr<T>(const AItem: T): Pointer;
    class function GetP<T>(const APtr: Pointer): T;
  end;

class function TMyClass.GetAddr<T>(const AItem: T): Pointer;
begin
  Result := @AItem;
end;

class function TMyClass.GetP<T>(const APtr: Pointer): T;
begin
  Result := T(APtr^);
end;

You can't have generic functions, but you can have generic methods.

So with this you are able to have pointers to generics, but remember that you have no type safety using this dirty technique.

like image 69
Toon Krijthe Avatar answered Nov 01 '22 15:11

Toon Krijthe


NOTE: The following answer is wrong, starting as it does from an flawed premise! Rather than redact the entire thing to save my blushes, I have left it intact so that the comments highlighting the error make sense,

How can this possibly be supported safely ?

Given (if this is what you have in mind, which I think it is):

  type
    TFoo<T> = class end;
    PFoo<T> = ^TFoo<T>;

Then if we have:

  var
    a, b: TFoo<T>;
    p: PFoo<T>;

  a := TFoo<String>.Create;
  b := TFoo<Integer>.Create;

Then both of the following would be permissible:

  p := @a;

  p := @b;

At any given time p might dereference to any TFoo of T, but at any given time it can only ever reference a specific T. I cannot see any type-safe compile time mechanism for ensuring that code dereferences p correctly.

One way to get around this issue (not a limitation of the compiler, but a limitation of trying to express something in a type safe way for which type safety simply cannot be expressed) would be to create type-specific derivatives of these types and use those. At the point at which you wish to dereference you are almost certainly going to know the type T anyway:

  type
    TFoo<T> = class end;

    TFooString = TFoo<String>;
    PFooString = ^TFooString;


  var
     p: PFooString;


  a := TFoo<Integer>;
  b := TFoo<String>;


  p := @a;  // Should not compile
  p := @b;  // This is OK

This is possible even in Delphi 2010.

However, worryingly, in investigating this I find that:

  p := @a;  // Should not compile

DOES in fact compile. Which strikes me as wrong. VERY wrong. And could point to (yet) another flaw in the generics implementation in Delphi.

Here be dragons...

like image 25
Deltics Avatar answered Nov 01 '22 16:11

Deltics