0

I have read how to make a pointer to a normal class and use it inside the class difinition:

type
  PExample = ^TExample;
  TExample = class
    data: Integer;
    next: PExample;
  end;

but how do you do it with templatized parameters? This does not compile with the error Undeclared identifier: 'TExample' on the second line:

type
 PExample = ^TExample;
 TExample<T> = class
   data: T;
   next: PExample;
 end;

Changing it to

PExample = ^TExample<T>;

does not fix it.

Hal
  • 165
  • 1
  • 7

3 Answers3

4

As you are using a class, you don't need to use a PExample. Classes are already reference types.

 TExample<T> = class
   data: T;
   next: TExample<T>;
 end;

This should work without the need to declare any pointer types. Pointer types are only required if you work with records (which are value types).

EDIT:

To my surprise I just noticed that this compiles and works in Delphi XE:

program Project;

{$APPTYPE CONSOLE}

type
  TNode<T> = record
    Next: ^TNode<T>;
    Data: T;
  end;

var
  Node1, Node2: TNode<Integer>;

begin
  Node1.Next := @Node2;
  Node1.Data := 1;
  Node2.Next := nil;
  Node2.Data := 2;

  WriteLn(Node1.Data);
  WriteLn(Node1.Next.Data);
end.

It does still not solve the problem of defining a general generic pointer type, because this:

PNode<T> = ^TNode<T>;

does not work.

Thorsten Engler
  • 2,333
  • 12
  • 13
  • I disagree with your last statement, so I keep the +1 for now, as pointers are "required" for other types, for instance, simple types like Integer, Double, etc. – jachguate Mar 19 '11 at 21:43
  • It was not my intention of saying that generic pointers are generally not required. Not supporting them is a huge hole in Delphi's generic support. But *in the context of the original question* pointers are only required if you want to use records. They are not required if you use classes (which are already pointers). – Thorsten Engler Mar 20 '11 at 03:55
  • What about simple types, like Integers? – jachguate Mar 21 '11 at 15:12
  • @jachguate, What do you mean? I already said that generic pointer types in general should definitely be added. But again, this has nothing at all to do with the original question. The example given in the original question, the Questioner was trying to define a pointer to a class. *In this context*, pointers are not required because classes are already pointers (as my answer stated). You could define the same type of data structure (a single linked list) using records. In that case pointers would be required (as my answer stated)... – Thorsten Engler Mar 22 '11 at 01:00
  • ... You can *not* define a single linked lists using "simple types, like integers" which is why they have absolutely nothing, whatsoever, at all, to do with my answer. – Thorsten Engler Mar 22 '11 at 01:02
2

The other answers tell you how to build a generic linked list of classes. If you ever need to build a generic linked list of records, you cannot do so at present:

type
  PNode<T> = ^TNode<T>;
  TNode<T> = record
  public
    Next: PNode;
  end;

does not compile.

Nor does:

type
  TNode<T> = record
  type
    PNode = ^TNode;
  public
    Next: PNode;
  end;

I believe that the reason for this is that the single-pass compiler does not support forward declarations of methods. This is actually more of a practical problem for operator overloading than for generics because classes can be used for generic linked lists.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • That is not correct. In this case Next is a pointer to T, not to TNode as it would need to be.. and there should be a Data: T; field. Unfortunately, the delphi compiler fails when trying to define "P = ^TNode;". Clearly generics in Delphi are not yet ready for much more than playing around with and marvel at all the holes still left in their implementation. – Thorsten Engler Mar 18 '11 at 08:35
  • @Thorsten Thanks. I'm doing a lot of learning in public today!! ;-) I think Delphi generics are fine for what they are, they are still very useful. They just don't have the flexibility of templates. – David Heffernan Mar 18 '11 at 09:01
  • The limitations of generics in Delphi are not fundamental limitations of generics, they are simply the result of an half-baked implementation that was never properly finished. I've a rather large number of QC's logged against generics (and the new RTTI) in the hope that they are one day actually finished so far that it's actually possible to seriously use them. – Thorsten Engler Mar 18 '11 at 09:22
  • @Thorsten Is that so. I'm making the distinction between generics and templates. For example I'd like to be able to write a generic method, `DoSomething(const a, b: T): T; begin Result := a+b; end;` and that can't be done with generics as implemented in Delphi, but can with templates. Can .net generics do what I want? – David Heffernan Mar 18 '11 at 09:26
  • @David, yes, .NET supports what you describe: http://msdn.microsoft.com/en-us/library/ms172192.aspx#Y200 – Hal Mar 18 '11 at 16:26
  • @Hal No I think you'd need operator constraints, which aren't there, unless they got added very recently. – David Heffernan Mar 18 '11 at 16:35
  • @Hal There are a couple of questions here on SO about this: http://stackoverflow.com/questions/2404731/ http://stackoverflow.com/questions/2555780/ http://stackoverflow.com/questions/147646/ – David Heffernan Mar 18 '11 at 16:37
  • @David oh wow, that's stupid. Does every language suck with generics but C++? – Hal Mar 18 '11 at 17:11
  • @Hal Yes, that's right. C++ has templates, most of the others have generics. That's really the difference. Templates are different. – David Heffernan Mar 18 '11 at 17:18
1

Is it necessary to use a pointer to a class? Using a class reference for your "next" field should work, like this:

type
 TExample<T> = class
   data: T;
   next: TExample<T>;
 end;

The "next" field can still be NIL or can be assigned another TExample instance. This seems to negate the need of using a traditional ^ pointer (although you could argue that a reference to a class is also a pointer, just with different syntax).

Jason Swager
  • 6,421
  • 6
  • 41
  • 56