Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2018-10

Indexing into records using [] property

2 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

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

Ben Grasset
to Ryan Joseph

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.

PM Ryan Joseph wrote 63 lines
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 - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal