On Sun, Jan 27, 2019 at 8:00 AM Marco van de Voort < f...@pascalprogramming.org> wrote:
> I wonder though that maybe makes passing properties etc difficult? > As far I know "const" has no tangible effect on how properties can be passed. Here's a little example to demonstrate: program Test; {$mode ObjFPC}{$H+}{$J-} {$modeswitch AdvancedRecords} type TRecA = record public A, B: SizeInt; constructor Create(const IA, IB: SizeInt); constructor Create(const ARec: TRecA); end; TRecB = record private FRecA: TRecA; public constructor Create(const ARec: TRecA); property RecA: TRecA read FRecA; end; TObjectB = object private FRecA: TRecA; public constructor Create(const ARec: TRecA); property RecA: TRecA read FRecA; end; TClassB = class private FRecA: TRecA; public constructor Create(const ARec: TRecA); property RecA: TRecA read FRecA; end; constructor TRecA.Create(const IA, IB: SizeInt); begin A := IA; B := IB; end; constructor TRecA.Create(const ARec: TRecA); begin A := ARec.A; B := ARec.B; end; constructor TRecB.Create(const ARec: TRecA); begin FRecA := ARec; end; constructor TObjectB.Create(const ARec: TRecA); begin FRecA := ARec; end; constructor TClassB.Create(const ARec: TRecA); begin FRecA := ARec; end; var R: TRecB; O: TObjectB; C: TClassB; begin R := TRecB.Create(TRecA.Create(5, 10)); WriteLn(R.RecA.A, ' ', R.RecA.B); O.Create(R.RecA); WriteLn(O.RecA.A, ' ', O.RecA.B); C := TClassB.Create(O.RecA); WriteLn(C.RecA.A, ' ', C.RecA.B); R := TRecB.Create(C.RecA); //back to where we started... WriteLn(R.RecA.A, ' ', R.RecA.B); C.Free(); end. Compiles without issues and works as intended. Personally though something I often do is use static "class functions" instead of constructors for advanced records, as they have the benefit of being able to be marked inline as well as not having the "at least one parameter" restriction. From an end-user perspective they're syntactically identical to how you'd call an actual constructor, also, so there's no worries in that area either. The program above changed in that fashion, where for example the TRecA record is written like this: type TRecA = record public A, B: SizeInt; class function Create(const IA, IB: SizeInt): TRecA; static; inline; class function Create(const ARec: TRecA): TRecA; static; inline; end; class function TRecA.Create(const IA, IB: SizeInt): TRec; begin with Result do begin A := IA; B := IB; end; end; class function TRecA.Create(const ARec: TRecA): TRec; begin with Result do begin A := ARec.A; B := ARec.B; end; end; generates assembly at -O3 for the main method that is actually two lines *shorter* than the assembly for the constructor version, while also of course avoiding three entire function calls completely via inlining (both TRecA constructors plus the one for TRecB.) So I could change things in that regard too for TSize/TPoint/TRect while I'm at it, unless anyone has any objections.
_______________________________________________ fpc-devel maillist - fpc-devel@lists.freepascal.org http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel