[Lazarus] "global" operator overloading

Sven Barth pascaldragon at googlemail.com
Tue Feb 26 15:00:59 CET 2013


On 26.02.2013 09:36, Xiangrong Fang wrote:
> Hi Sven,
>
> Could you please give a simple example that shows what you said: require
> that the type with which you specialize is a record. Then a class
> operator in that record can be defined.

Let's suppose you have the following generic declaration:

=== example begin ===

type
   generic TTreap<T1, T2> = class
     // let's assume T1 requires "<"
   end;

=== example end ===

If you use a record to specialize TTreap's T1 parameter then you can do 
it the following way:

=== example begin ===

type
   TMyRecord = record
     // note: in mode objfpc the modeswitch advancedrecords is needed
     class operator < (aLeft, aRight: TMyRecord): Boolean;
   end;

// implementation:

class operator TMyRecord.<(aLeft, aRight: TMyRecord): Boolean;
begin
   // compare aLeft and aRight
end;

// somewhere else

TTreapTMyRecordLongInt = specialize TTreap<TMyRecord, LongInt>;

=== example end ===

Now the generic will specialize without problem. If you want to 
specialize other types that don't support class operators then you need 
to wrap them inside a record, e.g.:

=== example begin ===

type
   TRecTStringList = record
     MyStringList: TStringList;
     class operator < (aLeft, aRight: TRecTStringList): Boolean;
   end;

=== example end ===

You can also use visibility modifiers like private or strict private to 
hide the MyStringList field and make it accessible only through 
properties. To simplyfy usage you can also define assignment operators. 
E.g.:

=== example begin ===

type
   // maybe it will also work with a TStringList if you use TStrings 
instead...
   TRecTStringList = record
   private
     fStringList: TStringList;
   public
     class operator := (aRight: TStringList): TRecTStringList;
     class operator := (aRight: TRecStringList): TStringList;
   end;

class operator TRecTStringList.:=(aRight: TStringList): TRecTStringList;
begin
   Result.fStringList := aRight;
end;

class operator TRecTStringList.:=(aRight: TRecStringList): TStringList;
begin
   Result := aRight.fStringList;
end;

// somewhere else:
var
   sl: TStringList;
   rec: TRecStringList;
begin
   // setup sl
   rec := sl;
   // use rec in the tree
   sl := rec;
end;

=== example end ===

It's not the nicest solution, but currently the only thing you can do.

Regards,
Sven




More information about the Lazarus mailing list