Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2020-04

New feature announcement: constant parameters for generics

1 message · 1 person ·

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Sven Barth

The Free Pascal team is happy to announce the addition of a new language feature: constant parameters for generics.

This allows to declare generic types or routines that aside from type parameters can also take constant parameters that can be used inside the generic as if one would use untyped constants. Together with inlining and optimizations this allows to generate optimal code that is yet flexible.

This feature was developed by Ryan Joseph. Thank you very much Ryan for your contribution and your patience until this feature was included.

A generic constant parameter is declared like this:

CONSTPARAM::=const <IDLIST>: <TYPE>
IDLIST::=<ID>[, <ID>]
TYPE::=<ID>

The following types are supported for constant parameters:
- integer types (including range types)
- floating point types
- string types
- set types
- enum types
- Boolean types
- Pointer types

While the type declaration might look like a typed constant it is in fact an untyped constant. The type is used to allow the author of a generic to restrict the range of the type. This has some implications:

- the constant parameter can be used inside the generic whereever an untyped constant can be used (e.g. variable initializers, constant initializers, default parameters, array indices, compile time intrinsics and operations)
- types that can't be used for untyped constants can't be used for generic constant parameters either

Example:

=== code begin ===

{$mode objfpc}
type
   generic TStaticArray<T; const N: Integer> = array[0..N-1] of T;
generic function TimesX<const N: Integer>(aArg: Integer): Integer;
begin
   Result := aArg * N;
end;
var
   myArray: specialize TStaticArray<LongInt, 2>;
   i: LongInt;
begin
   i := specialize TimesX<2>(21);
end.

=== code end ===

Important: Unlike C++ FPC does not support default specializations, thus doing recursive specializations together with operations on constants will result in out of stack exceptions or infinite loops:

=== code begin ===

{$mode objfpc}
type
   generic TTest<const N: Integer> = class
   const
     N1 = N - 1;
   type
     TSubTest = specialize TTest<N1>;
     // the following does not work currently for a different reason:
     // TSubTest = specialize TTest<N - 1>;
   end;
begin
end.

=== code end ===

Delphi compatibility: this feature is NOT Delphi compatible. However to not inconvience users that prefer mode Delphi this feature is also available in that mode as our stance usually is that Delphi code should compile with FPC while the inverse is not necessarily true.

Also this feature will NOT be part of 3.2.

Please give the generic constant parameters a try and report bugs in the bugtracker.

Regards,
Sven