[fpc-devel] [] property overloads

Ondrej Pokorny lazarus at kluug.net
Mon Jul 1 22:15:48 CEST 2019


On 01.07.2019 21:04, Michael Van Canneyt wrote:
> On Mon, 1 Jul 2019, Ondrej Pokorny wrote:
>> If the compiler encounters "Mytest.StringArray" it can be evaluated 
>> only as the non-indexed overload.
>
> Well... We can of course discuss forever, and still not agree.
> I suggest we let the compiler people have the last word on this. They 
> know best. And if you turn out to be right: so much the better.

Just an info: the non-indexed/indexed property overload resolving is 
currently supported in FPC: 
https://bugs.freepascal.org/file_download.php?file_id=23296&type=bug
(File arraypropenum.lpr in https://bugs.freepascal.org/view.php?id=28820 )

Yes, currently it's a bug because the overloads are taken from the 
methods and not from property definitions. But if the overloads were 
taken from property definitions, it would be a valid feature, IMO. (The 
bug in FPC is that indexed property information is not stored in the PPU 
- only the link "property name"->"getter name"+"setter name" is stored 
and therefore the information about the valid property definition is 
lost. The parameters and results are consequently taken from the 
getter/setter. I.e., the compiler can cope with the non-indexed/indexed 
property overloads since the very beginning.

This bug allows you to have some serious fun. For example this syntax is 
allowed (!!!):

   c := TMyClass.Create;
   Writeln(c[]); // c[] returns a Double
   c[] := 'oh my lord'; // c[] accepts a string

A compilable example:

program Project1;

{$mode objfpc}

type
   TValue = record A: Integer end;
   TMyClass = class
   private
     function GetValue: Double;                                   // 
result := x[]; syntax (without an index)
     function GetValue(index: integer): TValue;                   // 
result := x[999];
     function GetValue(index: string): string;                    // 
result := x['abc'];
     procedure SetValue(aindex: integer; const aValue: Double);   // 
x[999] := 9.9;
     procedure SetValue(aindex: integer; const aValue: TValue);   // 
x[999] := MyValue;
     procedure SetValue(aindex: string; const aValue: string);    // 
x['abc'] := 'xyz';
     procedure SetValue(const aValue: string);                    // x[] 
:= 'oh god'; syntax (without an index)
   public
     property Index[aindex: integer]: TValue read GetValue write 
SetValue; default;
   end;

{ TMyClass }

function TMyClass.GetValue(index: integer): TValue;
begin
   Result.A := index;
end;

function TMyClass.GetValue(index: string): string;
begin
   Result := index+index;
end;

function TMyClass.GetValue: Double;
begin
   Result := Pi;
end;

procedure TMyClass.SetValue(aindex: integer; const aValue: Double);
begin
   Writeln(aindex, ' ', aValue);
end;

procedure TMyClass.SetValue(aindex: integer; const aValue: TValue);
begin
   Writeln(aindex, ' ', aValue.A);
end;

procedure TMyClass.SetValue(const aValue: string);
begin
   Writeln(aValue);
end;

procedure TMyClass.SetValue(aindex: string; const aValue: string);
begin
   Writeln(aindex, ' ', aValue);
end;

var
   c: TMyClass;
begin
   c := TMyClass.Create;
   Writeln('Pi: ', c[]);
   Writeln(c[999].A);
   Writeln(c['key']);
   c['key'] := 'hello';
   c[] := 'oh my lord';
   c.Index := 'property fun';
   ReadLn;
end.

Ondrej



More information about the fpc-devel mailing list