[fpc-devel] Generics - a general question

Sven Barth pascaldragon at googlemail.com
Fri Nov 18 21:12:00 CET 2011


On 18.11.2011 18:31, AvP wrote:
> 1. Is this behavior intended (generic objects)?
>     I didn't find anything like that in the docs

It's at least not forbidden. I can imagine though that it was forgotten 
to document as objects aren't used by that many persons (and thus they 
are forgotten rather easily). They are rather similary handled by the 
compiler as "class" (at least in regards to parsing; the code generated 
is of course different).

>
> 2. Replacing "object" at (1) with "class" gives an error when compiling
>

Simply replacing "object" by "class" is not sufficient, because classes 
need to be used differently than objects. If you need help regarding 
this, I can provide you one if you want or you can read this: 
http://wiki.freepascal.org/Object_Oriented_Programming_with_FreePascal_and_Lazarus

> 3. In my case the specialization should only work if _ResType is TType or
> derived, as certain fields and functions/procedures are read / executed
>
> Is there currently a way to do this typesafe (my version is a hack, I believe)
> ?
> If not, maybe this would be an interesting feature for FPC.

Currently this is not possible, but I plan to add that, because of 
Delphi compatibility. The feature that you want is called "constraints" 
and the declaration of "TManager" will then look like this:

generic TManager<_ResType: TType> = object
   ...
end;

The compiler will then also be able to check whether you are using 
methods that are valid for the passed type.

Regarding your code:

>   constructor TManager.Create;
>   begin
>     SetLength(Resource, 2);
Resource[0] := New(PResType, Init); // You need to allocate the memory 
for the object
//>     Resource[0]^.Init;  // No problem here
>     WriteLn('Manager.Create done...');
>   end;
>
>   destructor TManager.Destroy;
>   begin
Dispose(Resource[0], Done); // Free the memory allocated earlier
//>     Resource[0]^.Done;  // No problem here
>     WriteLn('Manager.Destroy done...');
>   end;

Please note: While this is how it SHOULD work this does currently not 
work with any version of the compiler except maybe my generic branch (I 
haven't tested that yet).

As a workaround you can do this:

In TManager.Create:
Resource[0] := New(PResType);
Resource[0]^.Init;

In TManager.Destroy:
Resource[0]^.Dispose;
Dispose(Resource[0]);

This will issue two warnings though, but it works.

Regards,
Sven



More information about the fpc-devel mailing list