[fpc-devel] New feature announcement: constant parameters for generics
Sven Barth
pascaldragon at googlemail.com
Sun Apr 26 11:48:59 CEST 2020
Am 26.04.2020 um 09:38 schrieb Michael Van Canneyt:
>
>
> On Sun, 26 Apr 2020, Ryan Joseph via fpc-devel wrote:
>
>>
>>
>>> On Apr 26, 2020, at 5:13 AM, Sven Barth via fpc-devel
>>> <fpc-devel at lists.freepascal.org> wrote:
>>>
>>> The Free Pascal team is happy to announce the addition of a new
>>> language feature: constant parameters for generics.
>>
>> Excellent! Thanks for getting this merged. It was a long battle but
>> it's finally over. ;)
>
> As the original author, can you say something about the intended use
> of this feature ?
>
> Sven gave some examples, and they show how it works, but from his
> examples I don't see the point
> of this feature.
Jeppe had provided a potential usecase on the core mailing list in
October '18. His example is not useable as-is, but to give you an idea:
=== code begin ===
program tgpio;
{$mode objfpc}
{$modeswitch advancedrecords}
type
generic TSomeMicroGPIO<const Base: PtrUInt> = record
private
procedure SetPin(aIndex: SizeInt; aEnable: Boolean); inline;
function GetPin(aIndex: SizeInt): Boolean; inline;
public
property Pin[Index: SizeInt]: Boolean read GetPin write SetPin;
end;
procedure TSomeMicroGPIO.SetPin(aIndex: SizeInt; aEnable: Boolean);
begin
if aEnable then
PLongWord(Base)[2] := PLongWord(Base)[2] or (1 shl aIndex)
else
PLongWord(Base)[2] := PLongWord(Base)[2] and not (1 shl aIndex);
end;
function TSomeMicroGPIO.GetPin(aIndex: SizeInt): Boolean;
begin
Result := (PLongWord(Base)[2] and (1 shl aIndex)) <> 0
end;
var
GPIOA: specialize TSomeMicroGPIO<$8000F000>;
GPIOB: specialize TSomeMicroGPIO<$8000F100>;
GPIOC: specialize TSomeMicroGPIO<$8000F200>;
begin
GPIOA.Pin[2] := True;
end.
=== code end ===
As the compiler can inline all this, the writing of maintainable,
hardware agnostic frameworks for embedded controllers becomes easier.
In general I agree with you that the use of constants as generic
parameters is less wide. But there cases where one might want them.
A further example could be to determine the size of a hash table:
Determining that at compile time instead of runtime might allow for
better code. At the same time the user of that code would still be able
to influence it.
In the bug report there was a further example by Akira1364. At its core
it's about static arrays again, but it shows what can be done with this:
=== code begin ===
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.
=== code end ===
I'm sure the future will show more potential examples. Or one could look
at C++ examples that allow constants as well.
Regards,
Sven
More information about the fpc-devel
mailing list