<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">On Sun, Jan 27, 2019 at 8:00 AM Marco van de Voort <<a href="mailto:fpc@pascalprogramming.org">fpc@pascalprogramming.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I wonder though that maybe makes passing properties etc difficult?<br></blockquote><div><br></div><div>As far I know "const" has no tangible effect on how properties can be passed. Here's a little example to demonstrate:</div><div><br></div><div><div>program Test;</div><div><br></div><div>{$mode ObjFPC}{$H+}{$J-}</div><div>{$modeswitch AdvancedRecords}</div><div><br></div><div>type</div><div>  TRecA = record</div><div>  public</div><div>    A, B: SizeInt;</div><div>    constructor Create(const IA, IB: SizeInt);</div><div>    constructor Create(const ARec: TRecA);</div><div>  end;</div><div><br></div><div>  TRecB = record</div><div>  private</div><div>    FRecA: TRecA;</div><div>  public</div><div>    constructor Create(const ARec: TRecA);</div><div>    property RecA: TRecA read FRecA;</div><div>  end;</div><div><br></div><div>  TObjectB = object</div><div>  private</div><div>    FRecA: TRecA;</div><div>  public</div><div>    constructor Create(const ARec: TRecA);</div><div>    property RecA: TRecA read FRecA;</div><div>  end;</div><div><br></div><div>  TClassB = class</div><div>  private</div><div>    FRecA: TRecA;</div><div>  public</div><div>    constructor Create(const ARec: TRecA);</div><div>    property RecA: TRecA read FRecA;</div><div>  end;</div><div><br></div><div>  constructor TRecA.Create(const IA, IB: SizeInt);</div><div>  begin</div><div>    A := IA;</div><div>    B := IB;</div><div>  end;</div><div><br></div><div>  constructor TRecA.Create(const ARec: TRecA);</div><div>  begin</div><div>    A := ARec.A;</div><div>    B := ARec.B;</div><div>  end;</div><div><br></div><div>  constructor TRecB.Create(const ARec: TRecA);</div><div>  begin</div><div>    FRecA := ARec;</div><div>  end;</div><div><br></div><div>  constructor TObjectB.Create(const ARec: TRecA);</div><div>  begin</div><div>    FRecA := ARec;</div><div>  end;</div><div><br></div><div>  constructor TClassB.Create(const ARec: TRecA);</div><div>  begin</div><div>    FRecA := ARec;</div><div>  end;</div><div><br></div><div>var</div><div>  R: TRecB;</div><div>  O: TObjectB;</div><div>  C: TClassB;</div><div><br></div><div>begin</div><div>  R := TRecB.Create(TRecA.Create(5, 10));</div><div>  WriteLn(R.RecA.A, ' ', R.RecA.B);</div><div>  O.Create(R.RecA);</div><div>  WriteLn(O.RecA.A, ' ', O.RecA.B);</div><div>  C := TClassB.Create(O.RecA);</div><div>  WriteLn(C.RecA.A, ' ', C.RecA.B);</div><div>  R := TRecB.Create(C.RecA); //back to where we started...</div><div>  WriteLn(R.RecA.A, ' ', R.RecA.B);</div><div>  C.Free();</div><div>end.</div></div><div><br></div><div>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.</div><div><br></div><div>The program above changed in that fashion, where for example the TRecA record is written like this:</div><div><br></div><div><div>type</div><div>  TRecA = record</div><div>  public</div><div>    A, B: SizeInt;</div><div>    class function Create(const IA, IB: SizeInt): TRecA; static; inline;</div><div>    class function Create(const ARec: TRecA): TRecA; static; inline;</div><div>  end;</div><div><br></div><div>  class function TRecA.Create(const IA, IB: SizeInt): TRec;</div><div>  begin</div><div>    with Result do begin</div><div>      A := IA;</div><div>      B := IB;</div><div>    end;</div><div>  end;</div><div><br></div><div>  class function TRecA.Create(const ARec: TRecA): TRec;</div><div>  begin</div><div>    with Result do begin</div><div>      A := ARec.A;</div><div>      B := ARec.B;</div><div>    end;</div><div>  end;</div></div><div><br></div><div>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.)</div><div><br></div><div>So I could change things in that regard too for TSize/TPoint/TRect while I'm at it, unless anyone has any objections.</div></div></div></div></div>