Search code examples
delphipascallazarus

Converting TStack code from Delphi to Lazarus


In Delphi I have the following code, and all works well:

var
  StackOptions:TStack<String>;
  s:string;
  bfisio:boolean;
begin
  StackOptions:=TStack<String>.Create;
  //some pushs here 
  for s in StackOptions do begin
    dosomething;
  end;
end;

In Lazarus I can do this:

uses
  ..., gstack;

type
  TStringStack = specialize TStack<String>;

var
  StackOptions: TStringStack;
  s:string;
begin
  //But this code doesn;t compile
  StackOptions := TStringStack.Create;
  //some pushs here 
  for s in StackOptions do begin // <-- Error 
    dosomething;
  end;
end;

I get the next error in Lazarus:

Compile Project, Target: TicketLaz.exe: Exit code 1, Errors: 1
umain.pas(263,12) Error: Cannot find an enumerator for the type "TStack$1$crcAC3AF268"

How could I loop the Stack and search for a value with Lazarus without removing items from Stack?


Solution

  • FPC's stack is backed by a TVector.
    The TVector has an enumerator.

    You can easily add a class helper like so:
    Quick and dirty code.

    type
      TStringStack = specialize TStack<String>;
    
     type
    
       { TStackHelper }
    
       TVectorEnumerator = specialize TVector<string>.TVectorEnumerator;
    
       TStackHelper = class helper for TStringStack
         function GetEnumerator: TVectorEnumerator;
       end;
    
    { TStackHelper }
    
    function TStackHelper.GetEnumerator: TVectorEnumerator;
    begin
      Result:= FData.GetEnumerator;
    end;
    

    I really don't see why a stack is not supposed to have an iterator.
    Even in assembly you can simply do mov reg,[esp-04].
    This puritanical approach to data-structures helps no-one

    All this is complicated by the fact that TStack is generic.
    I know FPC allows generic class helpers, but I'm not sure how to make the solution work for all TStack<T>

    Another approach would be to simply edit gstack.pas to expose the iterator.