[fpc-pascal] How to use generics and meta class?

Sven Barth pascaldragon at googlemail.com
Fri Feb 28 07:44:21 CET 2014


On 27.02.2014 22:43, Joao Morais wrote:
> Em 27/02/14 09:39, Sven Barth escreveu:
>> Am 27.02.2014 13:37, schrieb Sven Barth:
>>> Am 27.02.2014 12:12, schrieb Joao Morais:
>>>> Em 25/02/14 05:14, Sven Barth escreveu:
>>>>> A generic is by definition not a fully existant type.
>>>>
>>>> Plans to include generics as a real type for class attributes?
>>>> Something like the Java world:
>>>>
>>>> generic TMyGeneric<T: TMyType>  <<-- this is the real type
>>>> specialize TMyGeneric<TSomeDescendantType>  <<-- only for type
>>>> safety, discarded after compiling
>>> No, because generics in FPC/Delphi work more like templates in C++
>>> than generics in Java/.Net (in these two it works, because of their
>>> "everything is an object" approach, we don't have that in Pascal).
>
> Correct. The feature I was talking about is something like:
>
> generic TMyGeneric<T: TMyType>
>
> And TMyType is a class. In this case the compiler knows I am talking
> about a generic for a class type and a "generic as Java" becomes possible.

Even if the compiler chooses to optimize here this will be - as I said - 
transparent to the user. So it will not change that TMyGeneric<> is not 
a full type, because only TMyGeneric<SomeType> is a full type.

Also it will not always be possible to simplify (the restrictions I 
mentioned below): if the generic calls a non-virtual function of T than 
the compiler may not be able to optimize the generic implementation, 
because the concrete specialization type might implement the method as 
well (hiding the method of TMyType) and thus the two approaches would 
result in different calls.

See here:

=== code begin ===

type
   TMyType = class
     procedure Test;
   end;

   TMySubType = class(TMyType)
     procedure Test;
   end;

   generic TMyGeneric<T: TMyType> = class
     procedure Test;
   end;

procedure TMyType.Test;
begin
   Writeln('Foo');
end;

procedure TMySubType.Test;
begin
   Writeln('Bar');
end;

procedure TMyGeneric.Test;
var
   o: T;
begin
   o.Test;
end;

type
   TMyGenericMySubType = specialize TMyGeneric<TMySubType>;
var
   t: TMyGenericMySubType;
begin
   t.Test;
end.

=== code end ===

Currently this will print:

=== output begin ===

Bar

=== output end ===

If the compiler would now naively generate an implementation of 
TMyGeneric with TMyType then the result would be:

=== output begin ===

Foo

=== output end ===

This must not be. So the compiler - while it might generate an implicit 
TMyType implementation - must not use that implicit implemenation if the 
type that is specialized with implements non virtual methods itself. 
This is one of the restrictions.

>> Addendum: this does not exclude the compiler from trying to optimize
>> this if the type parameter is indeed a class type. But this will be
>> transparent for the user and will have a few restrictions. It does
>> however not change that generics aren't full types.
>
> :/
>
> Maybe in the near (or not so near) future, these two approaches
> (templates and generics like in Java) may live together? I mean: is this
> technically possible?

FPC/Delphi generics are more templates than generics. Generics are not 
full types. This will not change.

Regards,
Sven



More information about the fpc-pascal mailing list