8.3 Generic type specialization

Once a generic type is defined, it can be used to generate other types: this is like replaying the definition of the types, with the template placeholders filled in with actual type definitions.

This can be done in any Type definition block. The specialized type looks as follows:

_________________________________________________________________________________________________________
Specialized type

--specialized- type- specialize -identifier- < type- identifier- list- >-----------

--type-identifier- list-|type- identifier------------------------------------
                 ------,-------
___________________________________________________________________

In Delphi mode, the specialize keyword must not be used.

The generic specialization is a very simple definition and can be used wherever a type definition would be used.

Given the declaration of TList in the previous section, the following would be a valid type definition:

Type  
  TPointerList = specialize TList<Pointer>;  
  TIntegerList = specialize TList<Integer>;

As of version 3.0 of Free Pascal, the specialize keyword can also be used in a variable declaration:

Var  
  P : specialize TList<Pointer>;

The specialize keyword is part of the specialized type, so when using fully qualified names, the specialize keyword must be after the unit name and parent type names.

The type in the specialize statement must be known, except in another generic type definition. Given the two generic class definitions:

type  
  Generic TMyFirstType<T1> = Class(TMyObject);  
  Generic TMySecondType<T2> = Class(TMyOtherObject);

Then the following specialization is not valid:

type  
  TMySpecialType = specialize TMySecondType<TMyFirstType>;

because the type TMyFirstType is a generic type, and thus not fully defined. The compiler will complain:

Error: Generics cannot be used as parameters when specializing generics

However, the following is allowed:

type  
  TA = specialize TMyFirstType<Atype>;  
  TB = specialize TMySecondType<TA>;

because TA is already fully defined when TB is specialized.

However, the specialize keyword can be used in another generic type definition as shown in the example above:

  generic TList<_T>=class(TObject, specialize IList<_T>)

and

  generic TPointSet<t> = array of specialize PlanarCoordinate<t>;

In these definitions, the specialization is only performed when the generic type itself is specialized, and at that time, the types are known.

Remark It is not possible to make a forward definition of a class which is a specialization of a generic, i.e. the following will not compile:

  TMyClass = Class;  
 
  // Other declarations  
 
  TMyClass = specialize TList<T>;