Forum > Beginners

Generic methods, fpc 3.2.2

<< < (2/2)

big_M:

--- Quote from: PascalDragon on November 25, 2021, 11:16:39 pm ---Type constraints only support classes and interfaces as well as the keyword record for primitive types and records.

For what you want to achieve you need to generalize the element type of the array:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type  generic TMap<T> = array of array of T; generic procedure Dummy<T>(x,y:integer; map: specialize TMap<T>);begin  map[x,y]:=1;end;
Otherwise the compiler can't know that map might possibly be an array.

--- End quote ---

Ah, okay I see. Yes, that makes sense, although I must admit this concept has to sink in a bit.

Thanks!

big_M:
Just another question. Inside a generic class, can I specialize another class only once? The second unit compiles, but the first doesn't with:

utest2.pas(29,31) Error: Duplicate identifier "TMap$1$crc237D1D69"
utest2.pas(29,31) Hint: Identifier already defined in utest2.pas at line 18

Is that normal behavior?



--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit utest2; {$mode ObjFPC}{$H+} interface uses  Classes, SysUtils; type   generic TMap<T> = class(TObject) end;   //----------------------------------   generic TAvancedMap<T> = class(TObject)  private    FMap: specialize TMap<T>;                  {***}  public    constructor Create;  end;   //----------------------------------  implementation constructor TAvancedMap.Create;var   tmpMap: specialize TMap<T>;              {***}begin //do some stuffend; end.  


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit utest2; {$mode ObjFPC}{$H+} interface uses  Classes, SysUtils; type   generic TMap<T> = class(TObject) end;   //----------------------------------   generic TAvancedMap<T> = class(TObject)  type     STMap = specialize TMap<T>;                      {***}   private    FMap: STMap;                                  {***}  public    constructor Create;  end;   //----------------------------------  implementation constructor TAvancedMap.Create;var  tmpMap: STMap;                               {***}begin //do some stuffend; end. 

jamie:
Here's my take on it...

As simple as I can make it...

Please read the comments I placed in code here, there is no need to test compile this of course.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---unit Unit1; {$mode objfpc}{$H+} interface uses  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls; type  //Following is a blue print to be used later to create an actual type.  generic test<T>=Class  //create a base template for the compiler to read when needed.    aField:T;  End;// Following are actual types being created using the Generic Template as the reference.// Specifying a <TYPE> now makes a complete type define using the BASE to start with;  TNewTypeInt = specialize Test<Integer>; //Now actually Create the type with Integers;  TNewTypeFloat = specialize Test<Double>;//Now actually create the type with floats;  //After this the compiler now has two types as if you were to type them out manually yourself.  //Note: you can only instruct FPC to Specialze once per type, otherwise it's a dup of course.  //  you would think only a hint of location where it was specilized aready would be enough?  { TForm1 }   TForm1 = class(TForm)    Button1: TButton;    procedure Button1Click(Sender: TObject);  private   public   end; var  Form1: TForm1;  aNewTypeInt :TNewTypeInt; //declare an instance body pointer;  aNewTypefloat:TNewTypeFloat;//Declare an instance body pointer; implementation {$R *.lfm} { TForm1 } procedure TForm1.Button1Click(Sender: TObject);begin   aNewTypeInt := TNewTypeInt.Create; //Create the instance so the the "aField" member has memory.   aNewTypeFloat:= TNewTypeFloat.Create;// "" "" ect.   AnewTypeInt.AField := 1;   AnewtypeFloat.aField := 1.56;   aNewTypeInt.Free;   aNewTypeFloat.free;end; end.  

PascalDragon:

--- Quote from: big_M on November 26, 2021, 04:04:05 pm ---Just another question. Inside a generic class, can I specialize another class only once? The second unit compiles, but the first doesn't with:

utest2.pas(29,31) Error: Duplicate identifier "TMap$1$crc237D1D69"
utest2.pas(29,31) Hint: Identifier already defined in utest2.pas at line 18

Is that normal behavior?
--- End quote ---

It's an already known bug (though surprisingly annoying to fix...). Your second example is the currently suggested workaround.

big_M:

--- Quote from: PascalDragon on November 27, 2021, 12:36:38 pm ---It's an already known bug (though surprisingly annoying to fix...). Your second example is the currently suggested workaround.

--- End quote ---
Ok, good to know :)

And thanks jamie for your examples!

Navigation

[0] Message Index

[*] Previous page

Go to full version