Indexing into records using [] property

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Indexing into records using [] property

Ryan Joseph
I’d like to know if there is a solution to the problem of indexing into records using [] properties.

In the example below I have an array of records (a dynamic array for the example) and I’d like to use the [] property to index into the values. The problem is because the array holds records I need to return a pointer to the record so I can access the fields. In the end the only problem is I need to dereference the pointer using ^.

Are there any solutions we could propose to this? Some ideas:

1) I looks like we could have a “var” modifier for function results but that concept has only ever existed in function params (like & in C++).

        function GetValue(i: integer): TVec2; var;

2) Maybe a modifier added to GetValue which tells the compiler to call the function (and result) like a pointer when the indexer is used?

====================================

type
        TVec2 = record
                x, y: integer;
        end;
        TVec2Ptr = ^TVec2;
        TVec2Array = array of TVec2;

type
        TVecArray = class
                values: TVec2Array;
                function GetValue(i: integer): TVec2Ptr;
                procedure Resize(newLength: integer);
                property Indexer[i: integer]: TVec2Ptr read GetValue; default;
        end;


function TVecArray.GetValue(i: integer): TVec2Ptr;
begin
        result := @values[i];
end;

procedure TVecArray.Resize(newLength: integer);
begin
        SetLength(values, newLength);
end;

var
        arr: TVecArray;
begin
        arr := TVecArray.Create;
        arr.Resize(1);
        arr[0]^.x := 100;
        arr[0]^.y := 100;
end.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Indexing into records using [] property

Ben Grasset
If the absence of dereferencing is the most important thing to you, you could do something like this:

program Example;

{$mode ObjFPC}{$H+}
{$modeswitch AdvancedRecords}

type
  TVec2 = record
    X, Y: Integer;
  end;

  TVec2Array = array of TVec2;

  TVecArray = record
  strict private
    Values: TVec2Array;
  public
    class function Create(const ACapacity: Integer = 16): TVecArray; inline; static;
    procedure Resize(const NewLength: Integer); inline;
    property I: TVec2Array read Values write Values;
  end;

  class function TVecArray.Create(const ACapacity: Integer = 16): TVecArray;
  begin
    Result := Default(TVecArray);
    SetLength(Result.Values, ACapacity);
  end;

  procedure TVecArray.Resize(const NewLength: Integer);
  begin
    SetLength(Values, NewLength);
  end;

begin
  with TVecArray.Create(0) do
  begin
    Resize(1);
    I[0].X := 100;
    I[0].Y := 100;
  end;
end.

The only downside there is that you obviously don't quite get the real "default" property syntax.

On Wed, Oct 10, 2018 at 11:06 PM Ryan Joseph <[hidden email]> wrote:
I’d like to know if there is a solution to the problem of indexing into records using [] properties.

In the example below I have an array of records (a dynamic array for the example) and I’d like to use the [] property to index into the values. The problem is because the array holds records I need to return a pointer to the record so I can access the fields. In the end the only problem is I need to dereference the pointer using ^.

Are there any solutions we could propose to this? Some ideas:

1) I looks like we could have a “var” modifier for function results but that concept has only ever existed in function params (like & in C++).

        function GetValue(i: integer): TVec2; var;

2) Maybe a modifier added to GetValue which tells the compiler to call the function (and result) like a pointer when the indexer is used?

====================================

type
        TVec2 = record
                x, y: integer;
        end;
        TVec2Ptr = ^TVec2;
        TVec2Array = array of TVec2;

type
        TVecArray = class
                values: TVec2Array;
                function GetValue(i: integer): TVec2Ptr;
                procedure Resize(newLength: integer);
                property Indexer[i: integer]: TVec2Ptr read GetValue; default;
        end;


function TVecArray.GetValue(i: integer): TVec2Ptr;
begin
        result := @values[i];
end;

procedure TVecArray.Resize(newLength: integer);
begin
        SetLength(values, newLength);
end;

var
        arr: TVecArray;
begin
        arr := TVecArray.Create;
        arr.Resize(1);
        arr[0]^.x := 100;
        arr[0]^.y := 100;
end.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal