Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2023-03

Is this supposed to work (generic)?

4 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Martin Frb

3.2.3 and 3.3.1 on Win 64bit

Trying a generic linked list.
So the specialized class must have an entry for the "next" element. And that entry is of the same type as the class itself.

Now at first, this seems to be not possible using generics, because specialize does not allow to pass in the "partially done" class. (the 2 commented lines produce "Error: Illegal expression") Only it does work, if the class is forward declared.

So is it supposed to work?
And if it is in the last case, then what about the other two cases?

program Project1;
type
   generic GenLinkedList<D, T> = class
     Data: D;
     Next: T;
   end;
   //TBar = specialize GenLinkedList<integer, TBar>;
   //TFoo = class(specialize GenLinkedList<integer, TFoo>);
   TSome = class;
   TSome = class(specialize GenLinkedList<integer, TSome>);
begin
end.

Btw, it is the same, if the linked list uses actual pointer.

   generic GenLinkedList<D, T> = class
     type  PT = ^T;
   public
     Data: D;
     NextPtr: PT;
   end;

Reply by email

Sven Barth
to Martin Frb
Martin Frb wrote 39 lines
3.2.3 and 3.3.1 on Win 64bit Trying a generic linked list. So the specialized class must have an entry for the "next" element. And that entry is of the same type as the class itself. Now at first, this seems to be not possible using generics, because specialize does not allow to pass in the "partially done" class. (the 2 commented lines produce "Error: Illegal expression") Only it does work, if the class is forward declared. So is it supposed to work? And if it is in the last case, then what about the other two cases? program Project1; type   generic GenLinkedList<D, T> = class     Data: D;     Next: T;   end;   //TBar = specialize GenLinkedList<integer, TBar>;   //TFoo = class(specialize GenLinkedList<integer, TFoo>);   TSome = class;   TSome = class(specialize GenLinkedList<integer, TSome>); begin end. Btw, it is the same, if the linked list uses actual pointer.   generic GenLinkedList<D, T> = class     type  PT = ^T;   public     Data: D;     NextPtr: PT;   end;

The correct way to declare a generic linked list using classes is the following:

=== code begin ===

type
   generic TGenLinkedList<D> = class
     Data: D;
     Next: specialize TGenLinkedList<D>;
   end;
   TSome = specialize TGenLinkedList<Integer>;

=== code end ===

Regards,
Sven

Reply by email

Martin Frb
to Sven Barth
Sven Barth wrote 19 lines
Am 26.03.2023 um 13:30 schrieb Martin Frb via fpc-devel: >   TSome = class; >   TSome = class(specialize GenLinkedList<integer, TSome>); > The correct way to declare a generic linked list using classes is the following: === code begin === type   generic TGenLinkedList<D> = class     Data: D;     Next: specialize TGenLinkedList<D>;   end;   TSome = specialize TGenLinkedList<Integer>; === code end ===

Ok, but the forward declaration (which is the only working one of my examples) is also important.
Not sure, why it needs the forward. After all, the forward also comes after the generic.

   generic TGenLinkedList<D, C> = class
     Data: D;
     Next: C;
   end;
   TSome = class;
   TSome = class(specialize TGenLinkedList<Integer, TSome>)
     other: boolean;
     procedure Foo;
   end;
procedure TSome.Foo;
begin
   Next.other := true; // Next must be type TSome, not just the
specialized generic.
end;

Reply by email

Kostas Michalopoulos
to Martin Frb: 3.2.3 and 3.3.1 on Win 64bit Trying a generic linked list. So the specialized class must…
Martin Frb wrote 6 lines
generic GenLinkedList<D, T> = class Data: D; Next: T; end; TSome = class; TSome = class(specialize GenLinkedList<integer, TSome>);

AFAIK "specialize" essentially "pastes" the parameters (after some checking) so it'd be as if you had declared...

     TSome = class;
     GenLinkedList = class
       Data: Integer;
       Next: TSome;
     end;
     TSome = class(GenLinkedList);

...which is perfectly valid Free Pascal code.

Also AFAIK the reason the others do not work is because when specialize is called, TFoo and TBar are not known to the compiler yet, but the forward declaration with TSome tells to the compiler that it is a class.

I guess it *is* a bit inconsistent that you can use the name of the type you are declaring during the declaration itself for classes - like "TFoo = class Foo: TFoo; end" - or target a type with a pointer before the targeted type is even known and yet specialization needs to know ahead of time everything, but that's how things are :-P

Kostas

Reply by email