On Mon, Jul 8, 2019 at 3:47 PM Ben Grasset <operato...@gmail.com> wrote:
> On Mon, Jul 8, 2019 at 2:22 PM Ryan Joseph <generic...@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.
_______________________________________________ fpc-devel maillist - fpc-devel@lists.freepascal.org https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel