Sign in Join

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

Mailing lists / fpc-pascal / 2013-03

Use generic class as parameter (was: how to write enumerator for trees)

14 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

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

Xiangrong Fang

Hi,

I try to do exactly the same as show here:

QUOTE:
http://svn.freepascal.org/svn/fpc/trunk/packages/fcl-stl/src/gvector.pp

generic TVector<T> = class
  ... ...
  type
    TVectorEnumerator = class
    private
      FVector: TVector;
      FPosition: SizeUInt;
      FFirstDone: Boolean;
      function GetCurrent: T; inline;
    public
      *constructor Create(AVector: TVector);*
      function MoveNext: Boolean; inline;
      property Current: T read GetCurrent;
    end;
  ... ...
  public

My code:

generic TTreap<TKey, TValue> = class
  ... ...
  type
    TTreapEnumerator = class
      FStack: TStack;
      FCurrent: PNode;
    public
      *constructor Create(ATreap: TTreap);*
      destructor Destroy; override;
      function MoveNext: Boolean;
      property Current: PNode read FCurrent;
    end;
  ... ...
  private

Error message I got is: Error: Generics without specialization cannot be used as a type for a variable

Then I found this: http://bugs.freepascal.org/view.php?id=19499&history=1

I wonder if this bug's fix is release or not? How does the TVector class compile with this problem?

Thanks!
Xiangrong

Reply by email

Xiangrong Fang
to Xiangrong Fang

Hi,

I missed the key point. This bug should be fixed in 2.7.1, but I am now using 2.6.0. Now there is another problem:

If I change my code to this:

      TTreapEnumerator = class
        FStack: TStack;
        FCurrent: PNode;
      public
*        constructor Create(root: PNode);*
        destructor Destroy; override;
        function MoveNext: Boolean;
        property Current: PNode read FCurrent;
      end;

The problem is gone, because PNode is not a generic class, but only a record. However, the following errors are generated:

Error: Forward declaration not solved "constructor THistogram.TTreap$Char$LongInt.TTreapEnumerator.Create(PNode);" Error: Forward declaration not solved "destructor
THistogram.TTreap$Char$LongInt.TTreapEnumerator.Destroy;" Error: Forward declaration not solved
"THistogram.TTreap$Char$LongInt.TTreapEnumerator.MoveNext:Boolean;"

THistogram is defined as:

  THistogram = class(specialize TTreap<Char, Integer>)
  protected
    function DefaultTraverser(Key: Char; Value: Integer): Boolean; override;
    procedure DefaultDisposer(Value: Integer); override;
    function DefaultUpdater(Key: TKey; Value: TValue; IsNew: Boolean):
Boolean; override;
  public
    MKey: Char;
    Max: Integer;
    constructor Create; override;
  end;

I think there is no need to define TTreapEnumerator in THistogram again, right?

Xiangrong

2013/3/22 Xiangrong Fang

Show quoted text 55 lines
Hi, I try to do exactly the same as show here: QUOTE: http://svn.freepascal.org/svn/fpc/trunk/packages/fcl-stl/src/gvector.pp generic TVector<T> = class ... ... type TVectorEnumerator = class private FVector: TVector; FPosition: SizeUInt; FFirstDone: Boolean; function GetCurrent: T; inline; public *constructor Create(AVector: TVector);* function MoveNext: Boolean; inline; property Current: T read GetCurrent; end; ... ... public My code: generic TTreap<TKey, TValue> = class ... ... type TTreapEnumerator = class FStack: TStack; FCurrent: PNode; public *constructor Create(ATreap: TTreap);* destructor Destroy; override; function MoveNext: Boolean; property Current: PNode read FCurrent; end; ... ... private Error message I got is: Error: Generics without specialization cannot be used as a type for a variable Then I found this: http://bugs.freepascal.org/view.php?id=19499&history=1 I wonder if this bug's fix is release or not? How does the TVector class compile with this problem? Thanks! Xiangrong

Reply by email

Sven Barth
to Xiangrong Fang
"Xiangrong Fang" wrote
Hi, I missed the key point. This bug should be fixed in 2.7.1, but I am now

using 2.6.0. Now there is another problem:

Show quoted text 16 lines
If I change my code to this: TTreapEnumerator = class FStack: TStack; FCurrent: PNode; public constructor Create(root: PNode); destructor Destroy; override; function MoveNext: Boolean; property Current: PNode read FCurrent; end; The problem is gone, because PNode is not a generic class, but only a

record. However, the following errors are generated:

2.6.x does not support nested types in generics. Generic fixes and improvements are only found in 2.7.1 as most of them were to invasive to be merged back.

Regards,
Sven

Reply by email

Xiangrong Fang
to Sven Barth

2013/3/22 Sven Barth

Show quoted text 7 lines
> The problem is gone, because PNode is not a generic class, but only a record. However, the following errors are generated: 2.6.x does not support nested types in generics. Generic fixes and improvements are only found in 2.7.1 as most of them were to invasive to be merged back.

OK, then why this error happened:

demo2.lpr(76,13) Error: Incompatible types: got
"TRoller.TTreap$PPerson$Byte" expected "TRoller"

The problematic lines are:

=== demo2.lpr ===

var
  n: TRoller.PNode;
  r1, r2: TRoller;
begin
  r1 := TRoller.Create;
  with r1 do begin
    ... ...
 *   r2 := r1.Copy(@OrderByAge);*
    ... ...
  end;
end.

=== treap.pas ===

function TTreap.Copy(Comp: TComparator): TTreap;
var
  n: PNode;
begin
  if Comp = nil then Comp := FComparator;
  Result := TTreap.Create;
  Result.Comparator := Comp;
  for n in Self do Result.Insert(n^.Key, n^.Value);
end;

I don't see there are "nested types" and why there is a type named: TRoller.TTreap$PPerson$Byte?
Shouldn't be either
TRoller or TTreap$PPerson$Byte but not both?

Thanks,
Xiangrong

Reply by email

Sven Barth
to Xiangrong Fang
Xiangrong Fang wrote 14 lines
2013/3/22 Sven Barth < > > The problem is gone, because PNode is not a generic class, but only a record. However, the following errors are generated: 2.6.x does not support nested types in generics. Generic fixes and improvements are only found in 2.7.1 as most of them were to invasive to be merged back. OK, then why this error happened: demo2.lpr(76,13) Error: Incompatible types: got "TRoller.TTreap$PPerson$Byte" expected "TRoller"

AFAIR there was also a problem with result types in generics. Could you please test your code with 2.7.1 to be sure?

Regards,
Sven

Reply by email

Xiangrong Fang
to Sven Barth

I didn't see a DEB package for 2.7.1. I am currently using 2.6.0. Can I compile 2.7.1 from source with 2.6.0?

2013/3/22 Sven Barth

Show quoted text 28 lines
Am 22.03.2013 08:13, schrieb Xiangrong Fang: 2013/3/22 Sven Barth > > The problem is gone, because PNode is not a generic class, but only a > record. However, the following errors are generated: > > 2.6.x does not support nested types in generics. Generic fixes and > improvements are only found in 2.7.1 as most of them were to invasive to be > merged back. > OK, then why this error happened: demo2.lpr(76,13) Error: Incompatible types: got "TRoller.TTreap$PPerson$Byte" expected "TRoller" AFAIR there was also a problem with result types in generics. Could you please test your code with 2.7.1 to be sure? Regards, Sven _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal

Reply by email

Sven Barth
to Xiangrong Fang
Xiangrong Fang wrote
I didn't see a DEB package for 2.7.1. I am currently using 2.6.0. Can I compile 2.7.1 from source with 2.6.0?

Yes. In fact you MUST compile with 2.6.0 (or 2.6.2).

Go to the directory of your 2.7.1 source and execute "make all". If your test code does only depend on the RTL units then you can compile your example without an installation from within the top level directory using this command:

=== command begin ===

./compiler/ppc386 -n -Furtl/units/i386-linux -viwn -FEsomeoutputdir yourunit.pas

=== comand end ===

If you compiled a 64-bit version you need to use this instead:

=== command begin ===

./compiler/ppcx64 -n -Furtl/units/x86_64-linux -viwn -FEsomeoutputdir yourunit.pas

=== command end ===

Regards,
Sven

Reply by email

Xiangrong Fang
to Xiangrong Fang: I didn't see a DEB package for 2.7.1. I am currently using 2.6.0. Can I compile 2.7.1…

Hi Sven,

My unite uses contnrs unit, how can I instruct the compiler to use the contnrs unit (also the Classes and sysutils units) of v2.7.1? I have already built 2.7.1 and now try to compile my program in the fpc source dir as you told.

Thanks

2013/3/22 Xiangrong Fang

Show quoted text 35 lines
I didn't see a DEB package for 2.7.1. I am currently using 2.6.0. Can I compile 2.7.1 from source with 2.6.0? 2013/3/22 Sven Barth > Am 22.03.2013 08:13, schrieb Xiangrong Fang: > > 2013/3/22 Sven Barth > > >> > The problem is gone, because PNode is not a generic class, but only a >> record. However, the following errors are generated: >> >> 2.6.x does not support nested types in generics. Generic fixes and >> improvements are only found in 2.7.1 as most of them were to invasive to be >> merged back. >> > OK, then why this error happened: > > demo2.lpr(76,13) Error: Incompatible types: got > "TRoller.TTreap$PPerson$Byte" expected "TRoller" > > > AFAIR there was also a problem with result types in generics. Could you > please test your code with 2.7.1 to be sure? > > Regards, > Sven > > _______________________________________________ > fpc-pascal maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-pascal >

Reply by email

Sven Barth
to Xiangrong Fang
Xiangrong Fang wrote 6 lines
Hi Sven, My unite uses contnrs unit, how can I instruct the compiler to use the contnrs unit (also the Classes and sysutils units) of v2.7.1? I have already built 2.7.1 and now try to compile my program in the fpc source dir as you told.

The Classes and SysUtils unit should be no problem if you used the command I gave you (if you look into the "rtl/units/i386-linux" (or "rtl/units/x86_64-linux") directory you'll see the files "classes.ppu" and "sysutils.ppu"). For the compiler to find unit "Contnrs" you need to add "-Fupackages/fcl-base/units/i386-linux" (or
"-Fupackages/fcl-base/units/x86_64-linux") to the command.

Regards,
Sven

Reply by email

Xiangrong Fang
to Sven Barth

I got this error now:

treap.pas(311,48) Error: Illegal expression
treap.pas(311,50) Error: Illegal expression
treap.pas(311,50) Fatal: Syntax error, ";" expected but "ordinal const"
found
Fatal: Compilation aborted

The line that generated this error is:

  if Result = NullNode then begin
    if (Rank = 0) or (Anchor < Key) then Rank += 1;   <-- error here
    Result := nil;
  end;

It seems that the += operator is not supported anymore?? Is there any switches in the new 2.7.1?

2013/3/23 Sven Barth

Show quoted text 25 lines
On 23.03.2013 03:35, Xiangrong Fang wrote: > Hi Sven, > > My unite uses contnrs unit, how can I instruct the compiler to use the > contnrs unit (also the Classes and sysutils units) of v2.7.1? I have > already built 2.7.1 and now try to compile my program in the fpc source > dir as you told. > The Classes and SysUtils unit should be no problem if you used the command I gave you (if you look into the "rtl/units/i386-linux" (or "rtl/units/x86_64-linux") directory you'll see the files "classes.ppu" and "sysutils.ppu"). For the compiler to find unit "Contnrs" you need to add "-Fupackages/fcl-base/units/**i386-linux" (or "-Fupackages/fcl-base/units/ **x86_64-linux") to the command. Regards, Sven ______________________________**_________________ fpc-pascal maillist - http://lists.freepascal.org/**mailman/listinfo/fpc-pascal<http://lists.freepascal.org/mailman/listinfo/fpc-pascal>

Reply by email

Sven Barth
to Xiangrong Fang
Xiangrong Fang wrote 17 lines
I got this error now: treap.pas(311,48) Error: Illegal expression treap.pas(311,50) Error: Illegal expression treap.pas(311,50) Fatal: Syntax error, ";" expected but "ordinal const" found Fatal: Compilation aborted The line that generated this error is: if Result = NullNode then begin if (Rank = 0) or (Anchor < Key) then Rank += 1; <-- error here Result := nil; end; It seems that the += operator is not supported anymore?? Is there any switches in the new 2.7.1?

The C style operators need to be enabled using a switch which is AFAIK either normally done in the fpc.cfg or by Lazarus. Nevertheless the command line switch you need is "-Sc".

Regards,
Sven

Reply by email

Xiangrong Fang
to Sven Barth

I think the problem is not fixed in 2.7.1:

~/fpc $ ./compiler/ppcx64 -n -Furtl/units/x86_64-linux -Fupackages/fcl-base/units/x86_64-linux -viwn -FE/home/xrfang -Sc demo2.lpr Target OS: Linux for x86-64
Compiling demo2.lpr
Compiling treap.pas
demo2.lpr(88,11) Error: Incompatible types: got "TTreap$2$crc94C56373" expected "TRoller"
demo2.lpr(98) Fatal: There were 1 errors compiling module, stopping Fatal: Compilation aborted

2013/3/24 Sven Barth

Show quoted text 33 lines
On 23.03.2013 14:51, Xiangrong Fang wrote: > I got this error now: > > treap.pas(311,48) Error: Illegal expression > treap.pas(311,50) Error: Illegal expression > treap.pas(311,50) Fatal: Syntax error, ";" expected but "ordinal const" > found > Fatal: Compilation aborted > > The line that generated this error is: > > if Result = NullNode then begin > if (Rank = 0) or (Anchor < Key) then Rank += 1; <-- error here > Result := nil; > end; > > It seems that the += operator is not supported anymore?? Is there any > switches in the new 2.7.1? > The C style operators need to be enabled using a switch which is AFAIK either normally done in the fpc.cfg or by Lazarus. Nevertheless the command line switch you need is "-Sc". Regards, Sven ______________________________**_________________ fpc-pascal maillist - http://lists.freepascal.org/**mailman/listinfo/fpc-pascal<http://lists.freepascal.org/mailman/listinfo/fpc-pascal>

Reply by email

Sven Barth
to Xiangrong Fang
Xiangrong Fang wrote 11 lines
I think the problem is not fixed in 2.7.1: ~/fpc $ ./compiler/ppcx64 -n -Furtl/units/x86_64-linux -Fupackages/fcl-base/units/x86_64-linux -viwn -FE/home/xrfang -Sc demo2.lpr Target OS: Linux for x86-64 Compiling demo2.lpr Compiling treap.pas demo2.lpr(88,11) Error: Incompatible types: got "TTreap$2$crc94C56373" expected "TRoller" demo2.lpr(98) Fatal: There were 1 errors compiling module, stopping Fatal: Compilation aborted

Aha! Now that I've seen your code I know where the problem is.

Your TRoller class is declared like this:

=== code begin ===

type
   TRoller = class(specialize TTreap<PPerson, Byte>)
     //...
   end;

=== code end ===

So TRoller is a child class of TTreap<PPerson, Byte> and thus the result type of Copy is TTreap<PPerson, Byte>. This is basically not related to generics, but to normal class inheritance. To solve this you need to adjust your TTreap.Copy in such a way that it doesn't use "TTreap.Create", but "ClassType.Create" and you must use TRoller's Copy then this way:

=== code begin ===

r2 := r1.Copy as TRoller;

=== code end ===

Regards,
Sven

Reply by email

Xiangrong Fang
to Sven Barth

Thanks Sven :)

2013/3/24 Sven Barth

Show quoted text 48 lines
On 24.03.2013 03:49, Xiangrong Fang wrote: > I think the problem is not fixed in 2.7.1: > > ~/fpc $ ./compiler/ppcx64 -n -Furtl/units/x86_64-linux > -Fupackages/fcl-base/units/**x86_64-linux -viwn -FE/home/xrfang -Sc > demo2.lpr > Target OS: Linux for x86-64 > Compiling demo2.lpr > Compiling treap.pas > demo2.lpr(88,11) Error: Incompatible types: got "TTreap$2$crc94C56373" > expected "TRoller" > demo2.lpr(98) Fatal: There were 1 errors compiling module, stopping > Fatal: Compilation aborted > Aha! Now that I've seen your code I know where the problem is. Your TRoller class is declared like this: === code begin === type TRoller = class(specialize TTreap<PPerson, Byte>) //... end; === code end === So TRoller is a child class of TTreap<PPerson, Byte> and thus the result type of Copy is TTreap<PPerson, Byte>. This is basically not related to generics, but to normal class inheritance. To solve this you need to adjust your TTreap.Copy in such a way that it doesn't use "TTreap.Create", but "ClassType.Create" and you must use TRoller's Copy then this way: === code begin === r2 := r1.Copy as TRoller; === code end === Regards, Sven ______________________________**_________________ fpc-pascal maillist - http://lists.freepascal.org/**mailman/listinfo/fpc-pascal<http://lists.freepascal.org/mailman/listinfo/fpc-pascal>

Reply by email