Beside the template type, all other types used in the generic declaration must be known when the
declaration is parsed.
This means that a type identifier with the same name must exist. The following unit will produce
an error:
                                                                            
                                                                            
{$mode objfpc}
 
unit myunit;
 
 
interface
 
 
type
 
  Generic TMyClass<T> = Class(TObject)
 
    Procedure DoSomething(A : T; B : TSomeType);
 
  end;
 
 
Type
 
  TSomeType = Integer;
 
  TSomeTypeClass = specialize TMyClass<TSomeType>;
 
 
Implementation
 
 
Procedure TMyClass.DoSomething(A : T; B : TSomeType);
 
 
begin
 
  // Some code.
 
end;
 
 
end.
The above code will result in an error, because the type TSomeType is not known when the
declaration is parsed:
                                                                            
                                                                            
home: >fpc myunit.pp
 
myunit.pp(8,47) Error: Identifier not found "TSomeType"
 
myunit.pp(11,1) Fatal: There were 1 errors compiling module, stopping
A second way in which this is visible, is the following. Assume a unit
                                                                            
                                                                            
{$mode objfpc}
 
unit mya;
 
 
interface
 
 
type
 
  Generic TMyClass<T> = Class(TObject)
 
    Procedure DoSomething(A : T);
 
  end;
 
 
 
Implementation
 
 
Procedure DoLocalThings;
 
 
begin
 
  Writeln(mya.DoLocalThings);
 
end;
 
 
 
Procedure TMyClass.DoSomething(A : T);
 
 
begin
 
  DoLocalThings;
 
end;
 
 
end.
The compiler will not allow to compile this unit, since the DoLocalThings function will not be
visible when the generic type is specialized:
                                                                            
                                                                            
Error: Global Generic template references static symtable
Now, if the unit is modified, and the DoLocalThings function is moved to the interface section,
the unit will compile. When using this generic in a program:
                                                                            
                                                                            
{$mode objfpc}
 
program myb;
 
 
uses mya;
 
 
procedure DoLocalThings;
 
 
begin
 
  Writeln(myb.DoLocalThings);
 
end;
 
 
Type
 
  TB = specialize TMyClass<Integer>;
 
 
Var
 
  B : TB;
 
 
begin
 
  B:=TB.Create;
 
  B.DoSomething(1);
 
end.
Despite the fact that generics act as a macro which is replayed at specialization time, the reference
to DoLocalThings is resolved when TMyClass is defined, not when TB is defined. This means
that the output of the program is:
                                                                            
                                                                            
home: >fpc -S2 myb.pp
 
home: >myb
 
mya.DoLocalThings
This behavior is dictated by safety and necessity:
     
     - A programmer specializing a class has no way of knowing which local procedures are
     used, so he cannot accidentally “override” it.
     
- A programmer specializing a class has no way of knowing which local procedures are
     used, so he cannot implement it either, since he does not know the parameters.
     
- If  implementation  procedures  are  used  as  in  the  example  above,  they  cannot  be
     referenced from outside the unit. They could be in another unit altogether, and the
     programmer has no way of knowing he should include them before specializing his class.