Franz
Franz

Reputation: 2043

generic compare function for 2 class types

here come my definition of Vertex class and graph class using generic programming features of Delphi :

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  System.Math, System.Generics.Collections,
  System.Generics.Defaults, Vcl.StdCtrls;

type

  tvertex = class(TObject)
    name: string;
    function markme: tvertex;
    function Compare(const v: TVertex): Integer;
    constructor create;
    destructor free;
  end;

  tvertex<T> = class(tvertex)
    Userdata: T;
  end;

  TGraph <T : class > = class (Tobject)
      vertexlist :  TObjectList<T>;

      procedure CompareLists(
      var _V1: TObjectList<T>;
      var _V2: TObjectList<T>);
  end;




  TForm1 = class(TForm)
    Edit1: TEdit;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

  // helper function
function createVertexComparer(): IComparer <TVertex  >;

implementation

// helper functions
function createVertexComparer(): IComparer<TVertex>;
begin
  Result := TDelegatedComparer<TVertex>.Create(
    function(const Left, Right: TVertex): Integer
    begin
      Result := Left.Compare(Right);
    end);

end;




{$R *.dfm}
{ tvertex }

function tvertex.Compare(const v: TVertex): Integer;
begin
    // ...
end;

constructor tvertex.create;
begin
  // ...
end;

destructor tvertex.free;
begin
  // ...
end;

function tvertex.markme: tvertex;
begin
  // ...
end;



procedure TGraph<T>.CompareLists(
var _V1: TObjectList<T>;
var _V2: TObjectList<T>);
begin
     _V1 := TObjectList<T>.Create(createVertexComparer(), False);  /// line which does not compile ....
end;

end.

How to modify the code that he is willing to accept TVertex and TVertex<T> class types as arguments ....

Upvotes: 0

Views: 1020

Answers (1)

David Heffernan
David Heffernan

Reputation: 612993

I would say that the main problem that you have is that you declared the graph class like this:

type
  TGraph<T: class>
    ...
  end;

And this means that the compiler will accept any class as T. Consequently the graph class knows nothing about T, beyond that it is a class.

It's hard to be sure, but I think that you intend T to be a vertex. So you need to constraint the graph class appropriately.

type
  TGraph<T: TVertex>
    ...
  end;

And then you have another problem with this function:

function createVertexComparer(): IComparer<TVertex>;

You pass the result of that to

TObjectList<T>.Create

But that expects a parameter of type IComparer<T> and you are supplying IComparer<TVertex>. That's the type mismatch that the compiler reports.

You'll need to make createVertexComparer be a method of TGraph<T> so that it can be generic. Its implementation would be:

function TGraph<T>.createVertexComparer(): IComparer<T>;
begin
  Result := TDelegatedComparer<T>.Create(
    function(const Left, Right: T): Integer
    begin
      Result := Left.Compare(Right);
    end);
end;

Also, do note that

destructor free;

is a disaster waiting to happen. You must use

destructor Destroy; override;

In fact, the rest of your code troubles me. For instance:

procedure TGraph<T>.CompareLists(var _V1, _V2: TObjectList<T>);
begin
  _V1 := TObjectList<T>.Create(createVertexComparer(), False);
end;

The method's name does not match what it does. It only returns one value, so why have two var parameters? It's very hard to discern intent when viewing code like this.

Upvotes: 2

Related Questions