Recent

Author Topic: TFPGMap with custom type  (Read 1590 times)

kur

  • Newbie
  • Posts: 5
TFPGMap with custom type
« on: August 04, 2020, 06:04:42 pm »
I want to use TFPGMap from fgl module with my own types. I have something like this:

Code: Pascal  [Select][+][-]
  1. type
  2.     TMyMap = specialize TFPGMap<TMyType1, TMyType2>;
  3.  

TMyType1 and TMyType2 - my custom types (classes).

But when I compile my code, I get the error:

fgl.pp(1582,18) Error: Operator is not overloaded: "TMyType1" < "TMyType1"

Is there a way to overload the operator to allow my code compile? I tried to overload it in my module, but this does not help.

P. S. I didn't use free pascal for about 10 years, and don't know much about its new features. So, if there is another way to use any kind of map for two custom object types, it is also OK for me.

simone

  • Hero Member
  • *****
  • Posts: 573
Re: TFPGMap with custom type
« Reply #1 on: August 04, 2020, 06:35:04 pm »
I suggest you to use generics.collections instead of FGL and TDictionary or TObjectDictionary instead of TFPGMap.
Microsoft Windows 10 64 bit - Lazarus 3.0 FPC 3.2.2 x86_64-win64-win32/win64

TRon

  • Hero Member
  • *****
  • Posts: 2435
Re: TFPGMap with custom type
« Reply #2 on: August 04, 2020, 09:09:11 pm »
But when I compile my code, I get the error:

fgl.pp(1582,18) Error: Operator is not overloaded: "TMyType1" < "TMyType1"
That is because the generic only 'implements' this comparison for 'simple' types.

From that it should be a fair guess to state that one (or both) of your types is not a simple type  :)

Quote
Is there a way to overload the operator to allow my code compile? I tried to overload it in my module, but this does not help.
Yes it is possible, but depends on your type. You probably failed (? using a global operator ?) because of the notes written here https://www.freepascal.org/docs-html/ref/refse59.html#x117-1390008.9

An example:
Code: Pascal  [Select][+][-]
  1. program test;
  2. {$MODE OBJFPC}{$H+}{$MODESWITCH ADVANCEDRECORDS}
  3. uses fgl;
  4.  
  5. type
  6.   // simple types  
  7.   TMyType1= string;
  8.   TMyType2= integer;
  9.   TMyMap1= specialize TFPGMap<TMyType1, TMyType2>;
  10.  
  11.   // not so simple type
  12.   TMyType3= record
  13.     x: string;
  14.     class operator <(first, second: TMyType3): boolean;
  15.     class operator >(first, second: TMyType3): boolean;
  16.   end;
  17.   TMyType4= integer;
  18.   TMyMap2= specialize TFPGMap<TMyType3, TMyType4>;
  19.  
  20. class operator TMyType3.<(first, second: TMyType3): boolean;
  21. begin
  22.   result:= true;
  23. end;
  24.  
  25. class operator TMyType3.>(first, second: TMyType3): boolean;
  26. begin
  27.   result:= true;
  28. end;
  29.  
  30. begin
  31. end.
  32.  

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: TFPGMap with custom type
« Reply #3 on: August 04, 2020, 09:54:27 pm »
P. S. I didn't use free pascal for about 10 years, and don't know much about its new features. So, if there is another way to use any kind of map for two custom object types, it is also OK for me.
Example with Generics.Collections (new in FPC 3.2.0):
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2. {$APPTYPE CONSOLE}
  3.  
  4. uses Generics.Collections;
  5.  
  6. type
  7.   TMyType1 = record
  8.     Id: Integer;
  9.   end;
  10.  
  11.   TMyType2 = type AnsiString;
  12.  
  13.   TMyMap = specialize TDictionary<TMyType1, TMyType2>;
  14.  
  15. var
  16.   R1, R2: TMyType1;
  17.   M: TMyMap;
  18.   RIndex: specialize TPair<TMyType1, TMyType2>;
  19. begin
  20.   R1.Id := 100;
  21.   R2.Id := 2;
  22.   M := TMyMap.Create;
  23.   try
  24.     M.Add(R1, '_100_');
  25.     M.Add(R2, '_2_');
  26.     for RIndex in M do
  27.       Writeln(RIndex.Key.Id, '=', RIndex.Value);
  28.   finally
  29.     M.Free;
  30.   end;
  31.   Readln;
  32. end.

Example with old fgl:
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2. {$MODESWITCH ADVANCEDRECORDS}
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses fgl;
  6.  
  7. type
  8.   TMyType1 = record
  9.   public
  10.     Id: Integer;
  11.     class operator < (Left, Right: TMyType1): Boolean;
  12.     class operator > (Left, Right: TMyType1): Boolean;
  13.   end;
  14.  
  15.   TMyType2 = type AnsiString;
  16.  
  17.   TMyMap = specialize TFPGMap<TMyType1, TMyType2>;
  18.  
  19. class operator TMyType1.< (Left, Right: TMyType1): Boolean;
  20. begin
  21.   Result := Left.Id < Right.Id;
  22. end;
  23.  
  24. class operator TMyType1.>(Left, Right: TMyType1): Boolean;
  25. begin
  26.   Result := Left.Id > Right.Id;
  27. end;
  28.  
  29. var
  30.   R1, R2: TMyType1;
  31.   M: TMyMap;
  32.   Index: SizeInt;
  33. begin
  34.   R1.Id := 100;
  35.   R2.Id := 2;
  36.   M := TMyMap.Create;
  37.   try
  38.     M.Add(R1, '_100_');
  39.     M.Add(R2, '_2_');
  40.     for Index := 0 to M.Count - 1 do
  41.       Writeln(M.Keys[Index].Id, '=', M.Data[Index]);
  42.   finally
  43.     M.Free;
  44.   end;
  45.   Readln;
  46. end.

kur

  • Newbie
  • Posts: 5
Re: TFPGMap with custom type
« Reply #4 on: August 05, 2020, 09:21:39 am »
Example with Generics.Collections (new in FPC 3.2.0):
Thank you for this example, it is exactly what I need!

Yes it is possible, but depends on your type. You probably failed (? using a global operator ?) because of the notes written here https://www.freepascal.org/docs-html/ref/refse59.html#x117-1390008.9

An example
...
Thank you for this too, I'll keep in mind as a possible workaround.
« Last Edit: August 05, 2020, 09:25:54 am by kur »

PascalDragon

  • Hero Member
  • *****
  • Posts: 5446
  • Compiler Developer
Re: TFPGMap with custom type
« Reply #5 on: August 05, 2020, 09:31:17 am »
P. S. I didn't use free pascal for about 10 years, and don't know much about its new features. So, if there is another way to use any kind of map for two custom object types, it is also OK for me.

TFPGMap is 14 years old, but okay, advanced records (that you need here) are 9 years and 7 months old... :P

kur

  • Newbie
  • Posts: 5
Re: TFPGMap with custom type
« Reply #6 on: August 05, 2020, 02:55:31 pm »
TFPGMap is 14 years old, but okay, advanced records (that you need here) are 9 years and 7 months old... :P
In that days, I was quite newbie in programming... I recalled now, I saw TDictionary class before, but don't remember anything how to use it.
But just have a look, what Google shows on "freepascal map tutorial" and compare it with "java map tutorial" or some other languages... Not so much for 14 years, right?

Nevertheless, I still like fpc more than others.

 

TinyPortal © 2005-2018