Here's a little heads-up to those working with generics + advanced records:
When invoking a parameterless method on an instance of a parametrized type (without type restrictions), you must omit the parentheses or else the code won't compile.Take the following example:
type
generic TCurve<T> = record
Parameters: T;
function Sample(Progress: Double): TPoint;
end;
Expecting
T to provide a method
function Evaluate(Progress: Double): TPoint of object works just fine:
function TCurve.Sample(Progress: Double): TPoint;
begin
Result := Parameters.Evaluate(Progress);
end;
Changing it to
function Evaluate(): TPoint of object (and passing the argument via a field/property), however, causes the compiler to reject the method call if you add empty parentheses:
function TCurve.Sample(Progress: Double): TPoint;
begin
Parameters.Position := Progress;
Result := Parameters.Evaluate(); // `Error: Illegal expression` at parentheses
end;
Removing the parentheses fixes this error:
function TCurve.Sample(Progress: Double): TPoint;
begin
Parameters.Position := Progress;
Result := Parameters.Evaluate; // Compiles just fine
end;
I'm posting this so others do not fall into the same trap as I did - when I first tried using advanced record methods inside generics, I had the misfortune of choosing a parameterless method as my test subject. Seeing this error I misconcluded that what I sought to do wasn't possible (with the misunderstanding being made worse by comparing it with
T: class restrictions, which reinforced my belief that the compiler would need to know about available methods in advance since such class-based type restrictions
do check for that).
I originally stumbled upon this while writing an ARC smart pointer template and struggling to forward the inner type's finalizer/destructor to the template itself. In the end I wound up with a cursed workaround involving operator overloads that I do not want anyone to repeat - hence why I'm posting this.
LLMs say that this quirk might stem from limitations in FPC's parser, which I haven't been able to verify. But regardless of whether this should be considered a bug (and if so whether fixing it is even worth the effort), it might be a good idea to document this somewhere.