Sign in Join

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

Mailing lists / fpc-pascal / 2019-04

class operator enumerator

4 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

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

Ryan Joseph

Is "class operator enumerator” supposed to work or is this a bug that it compiles but doesn’t do anything? Seems like it should work.

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

{$mode objfpc}
{$modeswitch advancedrecords}
program test;
type
  TArrayEnumerator = class
    public type
      TArrayValue = integer;
    public
      function GetCurrent: TArrayValue;
      constructor Create(a: pointer);
      property Current: TArrayValue read GetCurrent;
      function MoveNext: Boolean;
  end;
  TRec = record
    class operator enumerator(a: TRec): TArrayEnumerator;
  end;
class operator TRec.Enumerator(a: TRec): TArrayEnumerator;
begin
  result := TArrayEnumerator.Create(@a);
end;
function TArrayEnumerator.GetCurrent: TArrayValue;
begin
end;
constructor TArrayEnumerator.Create(a: pointer);
begin
end;
function TArrayEnumerator.MoveNext: Boolean;
begin
end;
var
  arr: TRec;
  value: integer;
begin
  for value in arr do	// <<<< ERROR: Cannot find an enumerator for the type "TRec"
    begin
    end;
end.

Regards,
Ryan Joseph

Reply by email

Ben Grasset
to Ryan Joseph

Seems like it's mixed up in some way with the FPC-style enumerator operator, so the "class" version is recognized but not actually implemented currently or something.

The normal way for classes/records/objects is to implement a GetEnumerator function, anyways. Here's an expanded-on version of your example, using your generic constants feature:

program Test;
{$mode ObjFPC}
{$PointerMath On}
{$modeswitch AdvancedRecords}
type
  generic TConstArray<T; const N: PtrUInt> = array[0..N] of T;
  generic TArrayEnumerator<T; const N: PtrUInt> = record
  public type
    PT = ^T;
  public const
    HIGH_INDEX = N;
  private
    CurrentIndex: PtrUInt;
    DataPointer: PT;
  public
    function GetCurrent: T; inline;
    class function Create(const A: PT): TArrayEnumerator; static; inline;
    function MoveNext: Boolean; inline;
    property Current: T read GetCurrent;
  end;
  generic TRec<T; const N: PtrUInt> = record
  public type
    TRecEnumerator = specialize TArrayEnumerator<T, N>;
  private
    FData: specialize TConstArray<T, N>;
  public
    class operator Initialize(var Rec: TRec);
    function GetEnumerator: TRecEnumerator; inline;
  end;
  function TArrayEnumerator.GetCurrent: T;
  begin
    Result := DataPointer[CurrentIndex];
  end;
  class function TArrayEnumerator.Create(const A: PT): TArrayEnumerator;
  begin
    with Result do begin
      DataPointer := A;
      CurrentIndex := -1;
    end;
  end;
  function TArrayEnumerator.MoveNext: Boolean;
  begin
    Inc(CurrentIndex);
    Result := CurrentIndex <= HIGH_INDEX;
  end;
  class operator TRec.Initialize(var Rec: TRec);
  var I: PtrUInt;
  begin
    for I := 0 to N do Rec.FData[I] := I;
  end;
  function TRec.GetEnumerator: TRecEnumerator;
  begin
    Result := TRecEnumerator.Create(@FData);
  end;
var
  Arr: specialize TRec<SizeInt, 5>;
  Value: SizeInt;
begin
  for Value in Arr do WriteLn(Value);
end.
PM Ryan Joseph wrote 58 lines
Is "class operator enumerator” supposed to work or is this a bug that it compiles but doesn’t do anything? Seems like it should work. =========================== {$mode objfpc} {$modeswitch advancedrecords} program test; type TArrayEnumerator = class public type TArrayValue = integer; public function GetCurrent: TArrayValue; constructor Create(a: pointer); property Current: TArrayValue read GetCurrent; function MoveNext: Boolean; end; TRec = record class operator enumerator(a: TRec): TArrayEnumerator; end; class operator TRec.Enumerator(a: TRec): TArrayEnumerator; begin result := TArrayEnumerator.Create(@a); end; function TArrayEnumerator.GetCurrent: TArrayValue; begin end; constructor TArrayEnumerator.Create(a: pointer); begin end; function TArrayEnumerator.MoveNext: Boolean; begin end; var arr: TRec; value: integer; begin for value in arr do // <<<< ERROR: Cannot find an enumerator for the type "TRec" begin end; end. Regards, Ryan Joseph _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Ryan Joseph
to Ben Grasset
Show quoted text 5 lines
On Apr 24, 2019, at 12:30 AM, Ben Grasset wrote: Seems like it's mixed up in some way with the FPC-style enumerator operator, so the "class" version is recognized but not actually implemented currently or something. The normal way for classes/records/objects is to implement a GetEnumerator function, anyways. Here's an expanded-on version of your example, using your generic constants feature:

I think they just forget to disable the operator for records but I believe the operator function works as intended however.

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph
Ryan Joseph wrote 7 lines
> On Apr 24, 2019, at 12:30 AM, Ben Grasset wrote: > > Seems like it's mixed up in some way with the FPC-style enumerator operator, so the "class" version is recognized but not actually implemented currently or something. > > The normal way for classes/records/objects is to implement a GetEnumerator function, anyways. Here's an expanded-on version of your example, using your generic constants feature: I think they just forget to disable the operator for records but I believe the operator function works as intended however.

It should probably best be forbidden for class operators considering there is the GetEnumerator way to add one (and it even works with helpers).

Regadrs,
Sven

Reply by email