[fpc-pascal] class operator enumerator

Ben Grasset operator97 at gmail.com
Wed Apr 24 06:30:47 CEST 2019


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.

On Tue, Apr 23, 2019 at 2:08 PM Ryan Joseph <ryan at thealchemistguild.com>
wrote:

> 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  -  fpc-pascal at lists.freepascal.org
> http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20190424/62efaa4d/attachment.html>


More information about the fpc-pascal mailing list