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
_______________________________________________
fpc-announce maillist  -  fpc-announce@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-announce

Reply via email to