[fpc-devel] New feature announcement: constant parameters for generics

Ryan Joseph genericptr at gmail.com
Sun Apr 26 10:09:43 CEST 2020



> On Apr 26, 2020, at 2:38 PM, Michael Van Canneyt <michael at freepascal.org> wrote:
> 
> As the original author, can you say something about the intended use of this feature ?

It was meant for a pretty narrow use of array types. If I knew how much work it would be to implement I probably would have not done it. :P I personally wanted it for static array lists that had methods like Add/Delete.
 
Here's an example of something I came across in a C++ project for decoding some data files old DOS games.

==================

{$mode objfpc}

program Block;

type
  generic TBlock<T, const Alpha, Depth: Integer> = record
    bits: array[0..(Alpha + Depth) - 1] of T;
  end;

type
  TBlock32 = specialize TBlock<UInt32, 4, 1>;
  { ... other block types ... }

begin

end.

Here's an example from the bug tracker by another user (Akira) that helped with testing. More arrays you'll note.

==================

program ConstMatrixExampleObjFPC;

{$mode ObjFPC}
{$modeswitch AdvancedRecords}

type
  String3 = String[3];

  generic TRawMatrix<T; const N: SizeUInt> = array[0..N-1] of array[0..N-1] of T;

  generic TMatrix<T; const N: SizeUInt> = record
  private type
    ArrayType = specialize TRawMatrix<T, N>;
  private
    Data: ArrayType;
  public
    class operator :=(constref Arr: ArrayType): TMatrix; inline;
    procedure Display;
  end;

  class operator TMatrix.:=(constref Arr: ArrayType): TMatrix;
  begin
    Result.Data := Arr;
  end;

  procedure TMatrix.Display;
  var I, J: SizeInt;
  begin
    WriteLn('[');
    for I := 0 to N - 1 do begin
      Write(' [');
      for J := 0 to N - 2 do
        Write(Data[I, J], ', ');
      Write(Data[I, N - 1]);
      Writeln('] ');
    end;
    Write(']');
  end;

const RawMat: specialize TRawMatrix<String3, 4> = (
  ('AAA', 'BBB', 'CCC', 'DDD'),
  ('EEE', 'FFF', 'GGG', 'HHH'),
  ('III', 'JJJ', 'KKK', 'LLL'),
  ('MMM', 'NNN', 'OOO', 'PPP')
);

var Mat: specialize TMatrix<String3, 4>;

begin
  Mat := RawMat;
  Mat.Display();
end.

And another example from him that gets pretty clever. ;)

==================

program Example;

// using Delphi-mode here as a matter of preference...

{$mode Delphi}

type
  Meters<const Value: Double> = record
  public const
    ToKilometers = Value / 1000;
    Unconverted = Value;
    ToCentimeters = Value * 100;
    ToMillimeters = Value * 1000;
    ToFeet = Value * 3.28084;
  end;

  procedure Test;
  type
    TenMeters = Meters<10>;
  const
    KILOMETER_VALUE = TenMeters.ToKilometers;
    UNCONVERTED_VALUE = TenMeters.Unconverted;
    CENTIMETER_VALUE = TenMeters.ToCentimeters;
    MILLIMETER_VALUE = TenMeters.ToMillimeters;
    FOOT_VALUE = TenMeters.ToFeet;
  begin
    WriteLn(KILOMETER_VALUE : 0 : 4);
    WriteLn(UNCONVERTED_VALUE);
    WriteLn(CENTIMETER_VALUE);
    WriteLn(MILLIMETER_VALUE);
    WriteLn(FOOT_VALUE : 0 : 4);
  end;

begin
  Test();
end.

Regards,
	Ryan Joseph



More information about the fpc-devel mailing list