Forum > Beginners

Generic methods, fpc 3.2.2

(1/2) > >>

big_M:
First time trying generics, but I fail. I try to write a generic method that could process different types of maps (int16, int32, double etc). So I tried something like this:


--- 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";}};} ---interface type     TInt16Map = Array of Array of int16;  TInt32Map = Array of Array of int32;   
--- 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";}};} ---implementation generic procedure Dummy<T>(x,y:integer; map:T);begin  map[x,y]:=1;end; 
but the compiler doesn't like map[x,y]. (Illegal qualifier)
So, I guess I would have to restrict the possible types to the actual 2d arrays?


--- 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";}};} ---generic procedure Dummy<T: TInt16Map, TInt32Map>(x,y:integer; map:T);begin  map[x,y]:=1;end;
But that fails with Error: Class or interface type expected, but got "TInt16Map".

Am I right though in assuming that a global method (not a class method) can be generic? I mostly read of generics in the context of classes


marcov:
(I quickly tested in trunk and with [x][y], behaviour is the same, please file a bug)

big_M:

--- Quote from: marcov on November 24, 2021, 04:29:15 pm ---(I quickly tested in trunk and with [x][y], behaviour is the same, please file a bug)

--- End quote ---


Will do. And when trying to restrict the types, should that work like in my second example?

Edit: So, when looking at the following example, only the first method works. So the type really has to be either a class or interface? But in that case, should map[x,y] not be illegal anyways?


--- 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 UTest; {$mode ObjFPC}{$H+} interface uses  Classes, SysUtils; type  TMyArray = Array of Array of int32;   TMyClass = class(TObject)    data: Array of Array of int32;  end;  implementation generic procedure Dummy<T: TMyClass>(x,y:integer; map:T); {works}begin  map.data[x,y]:=1;end; generic procedure Dummy<T: TMyArray>(x,y:integer; map:T); {doesn't work | Class or interface type expected, but got "TMyArray"}begin  map[x,y]:=1;end; generic procedure Dummy<T: integer>(var value:T); {doesn't work | Class or interface type expected, but got "LongInt"}begin  value:=1;end; end.  

big_M:
Okey, so I tried the same in Delphi CE just to see if it works there. From what I understand in Delphi global methods cannot be generic, but in fpc they can. So I tried this using classes this time:

Delphi:

--- 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; interface type  TDummyClass<T> = class(TObject)    procedure bla(x,y:integer; map:T);  end; implementation {$R *.dfm} procedure TDummyClass<T>.bla(x,y:integer; map:T);begin  map[x,y]:=1;end; end.
FPC:

--- 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; type  generic TDummyClass<T> = class(TObject)    procedure bla(x,y:integer; map:T);  end; implementation {$R *.lfm} procedure TDummyClass.bla(x,y:integer; map:T);begin  map[x,y]:=1;end; end.
Both don't work. FPC gives me the mentioned error "Illegal qualifier" for map[x,y], and Delphi says for the same line "Array type required". I'm confused now. Is this at all supposed to work or not? Ah, btw, when changing the line to map[y] it compiles with FPC, but not with Delphi.

PascalDragon:
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.

Navigation

[0] Message Index

[#] Next page

Go to full version