Recent

Author Topic: Problem when casting with a generic type  (Read 2754 times)

Basile B.

  • Guest
Problem when casting with a generic type
« on: August 17, 2014, 09:21:25 pm »
Hello, I'm thinking about refactoring a program using the standard observer pattern, based on generics and simple non-COM interfaces. The problem is that FPC (either 2.6.4 or latest trunk) doesn't seem to accept the parameterized type to cast:

I've attached the full source as it's a simple console program test, however the subject class declaration looks like this, (ITF is the observer interface):
Code: [Select]
  generic TGenericEmitter<ITF> = class(IInfoEmitter)
  protected
    fReceivers: TObjectList;
    function acceptReceiver(aObject: TObject): boolean; virtual; // test for ITF
    function getReceiver(index: Integer): ITF;
  public
    constructor create;
    destructor destroy; override;
    //
    procedure updateReceivers; virtual;
    procedure addReceiver(aReceiver: TObject);
    procedure removeReceiver(aReceiver: TObject);
    //
    property receiver[index: integer]: ITF read getReceiver;
  end;

and the implementation:
Code: [Select]
constructor TGenericEmitter.create;
begin
  fReceivers := TObjectList.create(false);
end;

destructor TGenericEmitter.destroy;
begin
  fReceivers.Free;
  inherited;
end;

function TGenericEmitter.getReceiver(index: Integer): ITF;
begin
  // ouch 1:Error: Class or interface type expected, but got "<undefined type>"
  result := (fReceivers.Items[index] as ITF);
end;

function TGenericEmitter.acceptReceiver(aObject: TObject): boolean;
begin
  // ouch 2:Error: Class or interface type expected, but got "<undefined type>"
  result := (aObject as ITF) <> nil;
end;

procedure TGenericEmitter.addReceiver(aReceiver: TObject);
begin
  if fReceivers.IndexOf(aReceiver) <> -1 then
    exit;
  if not acceptReceiver(aReceiver) then
    exit;
  fReceivers.Add(aReceiver);
end;

procedure TGenericEmitter.updateReceivers;
begin
end;

procedure TGenericEmitter.removeReceiver(aReceiver: TObject);
begin
  fReceivers.Remove(aReceiver);
end;

What's the right syntax to get rid of those errors ?

taazz

  • Hero Member
  • *****
  • Posts: 5363
Re: Problem when casting with a generic type
« Reply #1 on: August 17, 2014, 10:09:34 pm »
I have never used generics so this is a bit trial and error but can you try to declare like this
Code: [Select]
generic TGenericEmitter<T:ITF> = class(IInfoEmitter)
...
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

Basile B.

  • Guest
Re: Problem when casting with a generic type
« Reply #2 on: August 17, 2014, 11:56:40 pm »
alas this does not do the trick.

Basile-B

  • Sr. Member
  • ****
  • Posts: 457
    • GH...
Re: Problem when casting with a generic type
« Reply #3 on: December 26, 2015, 12:04:17 pm »
I have never used generics so this is a bit trial and error but can you try to declare like this
Code: [Select]
generic TGenericEmitter<T:ITF> = class(IInfoEmitter)
...

It works finally:

Code: Pascal  [Select]
  1. program Project1;
  2. {$Mode objfpc}
  3. {$Interfaces CORBA}
  4.  
  5. type
  6.   IDummy = interface
  7.   end;
  8.  
  9.   ISomething = interface(IDummy)
  10.     function test(value: TObject): boolean;
  11.   end;
  12.  
  13.   generic TTest<T:IDummy> = class
  14.     function test(value: TObject): boolean;
  15.   end;
  16.  
  17.   TSomething = specialize TTest<ISomething>;
  18.  
  19. function TTest.test(value: TObject): boolean;
  20. begin
  21.   result := value is T;
  22. end;
  23.  
  24. begin
  25. end.  
  26.  

Thx...