Recent

Author Topic: Array indexed by generic enum ?  (Read 7006 times)

guest58172

  • Guest
Array indexed by generic enum ?
« on: March 11, 2018, 09:39:41 pm »
I feel a bit blocked because this is not accepted

Code: Pascal  [Select][+][-]
  1. type
  2.   generic TFoo<SomeEnum> = class
  3.     a: array[SomeEnum] of integer;
  4.   end;
  5.  
  6.   TEnum = (e0, e1);
  7.  
  8. var
  9.   a: specialize TFoo<TEnum>;
  10.  

Is this supported in a way or another ?

bytebites

  • Hero Member
  • *****
  • Posts: 624
Re: Array indexed by generic enum ?
« Reply #1 on: March 11, 2018, 10:11:19 pm »
a: array[Low(SomeEnum)..High(SomeEnum)] of integer;

guest58172

  • Guest
Re: Array indexed by generic enum ?
« Reply #2 on: March 11, 2018, 10:15:49 pm »
This is what i'm trying to do in a helper record:

Code: Pascal  [Select][+][-]
  1.   generic TEnumIndexedArray<TheEnum, ElementType> = record
  2.   private
  3.     fArray: array[Low(TheEnum) .. High(TheEnum)] of ElementType;
  4.     procedure setElement(index: TheEnum; value: ElementType);
  5.     function getElement(index: TheEnum): ElementType;
  6.   public
  7.     property element[index: TheEnum]: ElementType read getElement write setElement; default;
  8.   end;
  9.  
  10. procedure TEnumIndexedArray.setElement(index: TheEnum; value: ElementType);
  11. begin
  12.   fArray[integer(index)] := value;
  13. end;
  14.  
  15. function TEnumIndexedArray.getElement(index: TheEnum): ElementType;
  16. begin
  17.   result := fArray[integer(index)];
  18. end;
  19.  

but the compiler says: Error: Type mismatch

guest58172

  • Guest
Re: Array indexed by generic enum ?
« Reply #3 on: March 11, 2018, 10:33:29 pm »
I can use Byte boundaries but this not super nice, not strongly typed.
At least the ugly things are hidden.

bytebites

  • Hero Member
  • *****
  • Posts: 624
Re: Array indexed by generic enum ?
« Reply #4 on: March 12, 2018, 04:12:49 am »
It works in trunk-version.

ASerge

  • Hero Member
  • *****
  • Posts: 2212
Re: Array indexed by generic enum ?
« Reply #5 on: March 12, 2018, 07:02:19 pm »
Is this supported in a way or another ?
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. {$MODE OBJFPC}
  3. {$APPTYPE CONSOLE}
  4. {$MODESWITCH ADVANCEDRECORDS}
  5.  
  6. uses TypInfo;
  7.  
  8. type
  9.   generic TEnumArray<TEnum, TData> = record
  10.   private
  11.     FArray: array of TData;
  12.     FMinValue: LongInt;
  13.     function GetItem(const Index: TEnum): TData; inline;
  14.     procedure SetItem(const Index: TEnum; const Value: TData); inline;
  15.   public
  16.     property Items[Index: TEnum]: TData read GetItem write SetItem; default;
  17.     procedure Init;
  18.   end;
  19.  
  20. function TEnumArray.GetItem(const Index: TEnum): TData;
  21. begin
  22.   Result := FArray[LongInt(Index) - FMinValue];
  23. end;
  24.  
  25. procedure TEnumArray.Init;
  26. var
  27.   EnumTypeInfo: PTypeInfo;
  28.   EnumTypeData: PTypeData;
  29.   i: LongInt;
  30. begin
  31.   EnumTypeInfo := TypeInfo(TEnum);
  32.   assert(EnumTypeInfo^.Kind = tkEnumeration, 'Support only enum types');
  33.   EnumTypeData := GetTypeData(EnumTypeInfo);
  34.   FMinValue := EnumTypeData^.MinValue;
  35.   SetLength(FArray, EnumTypeData^.MaxValue - FMinValue + 1);
  36.   for i := Low(FArray) to High(FArray) do
  37.     FArray[i] := Default(TData);
  38. end;
  39.  
  40. procedure TEnumArray.SetItem(const Index: TEnum; const Value: TData);
  41. begin
  42.   FArray[LongInt(Index) - FMinValue] := Value;
  43. end;
  44.  
  45. type
  46.   TOneTwoThree = (One, Two, Three);
  47.   TTwoThree = Two..Three;
  48.  
  49. var
  50.   X: specialize TEnumArray<TTwoThree, TOneTwoThree>;
  51. begin
  52.   X.Init;
  53.   X[Two] := One;
  54.   X[Three] := X[Two];
  55.   Writeln(X[Three]);
  56.   Readln;
  57. end.

Thaddy

  • Hero Member
  • *****
  • Posts: 14159
  • Probably until I exterminate Putin.
Re: Array indexed by generic enum ?
« Reply #6 on: March 20, 2018, 08:44:42 am »
In trunk it is even easier since last week, mantis 33414:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$H+}
  2. uses Classes, SysUtils;
  3.  
  4. type
  5.   generic TFoo<SomeEnum> = class
  6.     m: array[SomeEnum] of integer;
  7.   end;
  8.  
  9.   TEnum = (e0, e1);
  10.  
  11. var
  12.   a: specialize TFoo<TEnum>;
  13.  
  14. begin
  15. end.

But it needs trunk revision 38532 or higher. No need for typinfo.
It doesn't need a class. It also works for TArray<T>

Cleaned up code in proper syntax:
Code: Pascal  [Select][+][-]
  1. {$mode delphi}
  2. type
  3.   TFoo<SomeEnum> = class
  4.     m: array[SomeEnum] of integer;
  5.   end;
  6.   TEnum = (e0, e1);
  7. var
  8.   a: TFoo<TEnum>;
  9. begin
  10. end.
« Last Edit: March 20, 2018, 12:36:39 pm by Thaddy »
Specialize a type, not a var.

Thaddy

  • Hero Member
  • *****
  • Posts: 14159
  • Probably until I exterminate Putin.
Re: Array indexed by generic enum ?
« Reply #7 on: March 20, 2018, 12:29:32 pm »

Cumbersome and slow. At least trunk works now... 8-) 8-) O:-)
Specialize a type, not a var.

ASerge

  • Hero Member
  • *****
  • Posts: 2212
Re: Array indexed by generic enum ?
« Reply #8 on: March 21, 2018, 01:39:22 am »
Cumbersome and slow. At least trunk works now... 8-) 8-) O:-)
Yes, but it works! 8-)

 

TinyPortal © 2005-2018