[fpc-devel] [] property overloads

Ben Grasset operator97 at gmail.com
Tue Jul 9 00:11:46 CEST 2019


On Mon, Jul 8, 2019 at 3:47 PM Ben Grasset <operator97 at gmail.com> wrote:

> On Mon, Jul 8, 2019 at 2:22 PM Ryan Joseph <genericptr at gmail.com> wrote:
>
>> and it will actually write to the actual record in the array and not a
>> returned copy. However due to how the properties are currently structured
>> this means we can’t use the setter without passing pointers
>>
>
> Ah, I see what you mean. Note you can at least work around this for now
> with operator overloading:
>

Also, here's a longer (but much better because it doesn't require the data
type provided by the user to itself be directly assignable to a pointer)
version of that:

program Example;

{$mode Delphi}{$H+}

uses SysUtils;

type
  PVec3F = ^TVec3F;

  TVec3F = record
    X, Y, Z: Single;
  end;

type
  TList<T> = record
  public type
    PT = ^T;
    TConverter = record
      V: PT;
      class operator Implicit(constref From: T): TConverter; inline;
      class operator Implicit(const From: PT): TConverter; inline;
      class operator Implicit(constref From: TConverter): PT; inline;
    end;
  strict private
    FData: array of TConverter;
  private
    function GetItem(const I: PtrUInt): TConverter; inline;
    procedure SetItem(const I: PtrUInt; const Val: TConverter); inline;
    function GetLength: PtrInt; inline;
    procedure SetLength(const I: PtrInt); inline;
  public
    property Items[const I: PtrUInt]: TConverter read GetItem write
SetItem; default;
    property Length: PtrInt read GetLength write SetLength;
  end;

  class operator TList<T>.TConverter.Implicit(constref From: T): TConverter;
  begin
    Result.V := @From;
  end;

  class operator TList<T>.TConverter.Implicit(const From: PT): TConverter;
  begin
    Result.V := From;
  end;

  class operator TList<T>.TConverter.Implicit(constref From: TConverter):
PT;
  begin
    Result := From.V;
  end;

  function TList<T>.GetItem(const I: PtrUInt): TConverter;
  begin
    if I < System.Length(FData) then
      Result := FData[I]
    else
      Result := nil;
  end;

  procedure TList<T>.SetItem(const I: PtrUInt; const Val: TConverter);
  begin
    if I < System.Length(FData) then
      FData[I] := Val;
  end;

  function TList<T>.GetLength: PtrInt;
  begin
    Result := System.Length(FData);
  end;

  procedure TList<T>.SetLength(const I: PtrInt);
  begin
    System.SetLength(FData, I);
  end;

const
  DEFAULT_VEC3F: TVec3F = (
    X: 0.0;
    Y: 0.0;
    Z: 0.0;
  );

var
  PVec: PVec3F;
  VecList: TList<TVec3F>;

begin
  VecList.Length := 2;

  // So, you can directly assign to the list by value...
  VecList[0] := DEFAULT_VEC3F;

  // Or via a pointer...
  VecList[1] := @DEFAULT_VEC3F;

  // And directly assign *from* the list to a pointer...
  PVec := VecList[0];
  with PVec^ do begin
    X := 2.0;
    Y := 4.0;
    Z := 6.0;
  end;
  with PVec^ do
    WriteLn(Format('[%f %f %f]', [X, Y, Z]));

  // Or just do this
  with VecList[0].V^ do begin
    X := 2.0;
    Y := 4.0;
    Z := 6.0;
  end;

  //And this
  with VecList[0].V^ do
    WriteLn(Format('[%f %f %f]', [X, Y, Z]));
end.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20190708/e35cc5a0/attachment.html>


More information about the fpc-devel mailing list