[fpc-devel] generic constraints...

Mattias Gaertner nc-gaertnma at netcologne.de
Tue Jul 29 09:53:32 CEST 2025



On 7/25/25 16:31, Martin Frb via fpc-devel wrote:
> On 25/07/2025 15:20, Mattias Gaertner via fpc-devel wrote:
>>
>>
>> On 7/25/25 13:44, Martin Frb via fpc-devel wrote:
>>> Currently you can't do
>>>
>>> type
>>>    generic TFoo<A> = class
>>>       procedure Bar; virtual;
>>>    end;
>>>
>>>    generic FooChild<F: TFoo> = class(F)
>>>       procedure Bar; override;
>>>    end;
>[...] 

> No.
> 
> One example is that I have several
>    TItem1, TItem2, TItem3,...
> and for each a
>      TItem1List = specialize TFpgList<TItem1>;
> 
> But I don't actually use TItem1, ....
> 
> I use
>    TMyFinalItem1 =
>         specialize TFeatureX<
>             specialize TFeatureY<
>                 specialize TFeatureZ< TItem1 >
>            >
>        >;
> 
> And each list needs to be
>    TMyFinalItem1 =
>         specialize TFeatureXForList<
>             specialize TFeatureYForList<
>                 specialize TFeatureZForList< specialize TFpgList<TItem1> 
>    >
>            >
>        >;

IMO that does not look human friendly for reading and debugging.


> Currently I can swap the order, and git it working by creating a non 
> generic base.... But that introduces dependencies that were not wanted...
> 
> 
> Also, the error by the compiler is
>       Error: Generics without specialization cannot be used as a type 
> for a variable
> 
> But
>     generic FooChild<F: TFoo> = class(F)
> 
> - F is not a variable
> - TFoo in not a type (for somethnig), TFoo is a constraint

The problem is the ambiguity of TFoo, because Delphi (aka modeswitch) 
distinguishes TFoo, TFoo<> and TFoo<,>:

type
   generic TFoo<A> = class
      procedure Bar; virtual;
   end;
   generic TFoo<A,B> = class
      procedure NoBar; virtual;
   end;

   generic FooChild<F: TFoo> = class(F)
      procedure Bar; override;
   end;

So you have to be more specific:

   generic FooChild<A,F: specialized TFoo<A>> = class(F)
      procedure Bar; override;
   end;


> If that syntax was allowed, it should mean that
> -  F must be of any type that is (a descendand of) a specialization of 
> TFoo.
> 
> So this is NOT to allow FooChild to be specialized with another generic, 
> but with a (any) specialization of that generic.

AFAIK there is currently no "Any" placeholder in constraints. It would 
be something like
   generic FooChild<F: specialized TFoo<>> = ...

Although that looks like something was forgotten. Maybe better:

   generic FooChild<F: specialized TFoo<*>> = ...


Mattias



More information about the fpc-devel mailing list