Recent

Author Topic: Operator overloading  (Read 1128 times)

LemonParty

  • Sr. Member
  • ****
  • Posts: 355
Operator overloading
« on: September 12, 2025, 07:37:24 pm »
Hello.

There is an article about operator overloading in wiki https://wiki.freepascal.org/Operator_overloading. There are no examples of code. Could anybody provide an example of operator overloading?
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

Tomu

  • New Member
  • *
  • Posts: 14
Re: Operator overloading
« Reply #1 on: September 12, 2025, 08:29:31 pm »
Code

Code: Pascal  [Select][+][-]
  1. type
  2.   TMyClass = record
  3.     payload: integer;
  4.  
  5.     // Overloading the addition operator
  6.     class operator Add(a, b: TMyClass): TMyClass;
  7.  
  8.     // Overloading the subtraction operator
  9.     class operator Subtract(a, b: TMyClass): TMyClass;
  10.  
  11.     // Implicit conversion from Integer to TMyClass
  12.     class operator Implicit(a: Integer): TMyClass;
  13.  
  14.     // Implicit conversion from TMyClass to Integer
  15.     class operator Implicit(a: TMyClass): Integer;
  16.   end;
  17.  
  18. // Implementation of the overloaded operators
  19. class operator TMyClass.Add(a, b: TMyClass): TMyClass;
  20. var
  21.   returnrec: TMyClass;
  22. begin
  23.   returnrec.payload := a.payload + b.payload;
  24.   Result := returnrec;
  25. end;
  26.  
  27. class operator TMyClass.Subtract(a, b: TMyClass): TMyClass;
  28. var
  29.   returnrec: TMyClass;
  30. begin
  31.   returnrec.payload := a.payload - b.payload;
  32.   Result := returnrec;
  33. end;
  34.  
  35. class operator TMyClass.Implicit(a: Integer): TMyClass;
  36. var
  37.   returnrec: TMyClass;
  38. begin
  39.   returnrec.payload := a;
  40.   Result := returnrec;
  41. end;
  42.  
  43. class operator TMyClass.Implicit(a: TMyClass): Integer;
  44. begin
  45.   Result := a.payload;
  46. end;
  47.  
  48. // Example usage
  49. procedure TForm1.Button1Click(Sender: TObject);
  50. var
  51.   myVar1, myVar2, myVar3: TMyClass;
  52.   myInt: Integer;
  53. begin
  54.   // Using overloaded operators
  55.   myVar1.payload := 10;
  56.   myVar2.payload := 5;
  57.  
  58.   myVar3 := myVar1 + myVar2; // Uses overloaded Add operator
  59.   Memo1.Lines.Add('myVar1 + myVar2 = ' + IntToStr(myVar3.payload)); // Expected: 15
  60.  
  61.   myVar3 := myVar1 - myVar2; // Uses overloaded Subtract operator
  62.   Memo1.Lines.Add('myVar1 - myVar2 = ' + IntToStr(myVar3.payload)); // Expected: 5
  63.  
  64.   // Using implicit conversions
  65.   myVar3 := 20; // Uses overloaded Implicit(Integer) operator
  66.   Memo1.Lines.Add('myVar3 (from Integer) = ' + IntToStr(myVar3.payload)); // Expected: 20
  67.  
  68.   myInt := myVar1; // Uses overloaded Implicit(TMyClass) operator
  69.   Memo1.Lines.Add('myInt (from TMyClass) = ' + IntToStr(myInt)); // Expected: 10
  70. end;
« Last Edit: September 12, 2025, 09:31:17 pm by Martin_fr »

LV

  • Sr. Member
  • ****
  • Posts: 358
Re: Operator overloading
« Reply #2 on: September 12, 2025, 09:05:41 pm »
Hello!

Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2. {$modeswitch advancedrecords}
  3.  
  4. type
  5.   TComplex = record
  6.     Re, Im: Double;
  7.  
  8.     class operator +(a, b: TComplex): TComplex;
  9.     class operator -(a, b: TComplex): TComplex;
  10.     class operator *(a, b: TComplex): TComplex;
  11.     class operator /(a, b: TComplex): TComplex;
  12.     class operator -(a: TComplex): TComplex;
  13.   end;
  14.  
  15. class operator TComplex.+(a, b: TComplex): TComplex;
  16. begin
  17.   Result.Re := a.Re + b.Re;
  18.   Result.Im := a.Im + b.Im;
  19. end;
  20.  
  21. class operator TComplex.-(a, b: TComplex): TComplex;
  22. begin
  23.   Result.Re := a.Re - b.Re;
  24.   Result.Im := a.Im - b.Im;
  25. end;
  26.  
  27. class operator TComplex.*(a, b: TComplex): TComplex;
  28. begin
  29.   Result.Re := a.Re*b.Re - a.Im*b.Im;
  30.   Result.Im := a.Re*b.Im + a.Im*b.Re;
  31. end;
  32.  
  33. class operator TComplex./(a, b: TComplex): TComplex;
  34. var
  35.   d: Double;
  36. begin
  37.   d := b.Re*b.Re + b.Im*b.Im;
  38.   Result.Re := (a.Re*b.Re + a.Im*b.Im)/d;
  39.   Result.Im := (a.Im*b.Re - a.Re*b.Im)/d;
  40. end;
  41.  
  42. class operator TComplex.-(a: TComplex): TComplex;
  43. begin
  44.   Result.Re := -a.Re;
  45.   Result.Im := -a.Im;
  46. end;
  47.  
  48. // test
  49. var
  50.   x, y, z: TComplex;
  51. begin
  52.   x.Re := 1; x.Im := 2;
  53.   y.Re := 3; y.Im := 4;
  54.  
  55.   z := x + y; writeln('x+y = ', z.Re:0:1, ' + ', z.Im:0:1, 'i');
  56.   z := x - y; writeln('x-y = ', z.Re:0:1, ' + ', z.Im:0:1, 'i');
  57.   z := x * y; writeln('x*y = ', z.Re:0:1, ' + ', z.Im:0:1, 'i');
  58.   z := x / y; writeln('x/y = ', z.Re:0:1, ' + ', z.Im:0:1, 'i');
  59.   z := -x;    writeln('-x  = ', z.Re:0:1, ' + ', z.Im:0:1, 'i');
  60.  
  61.   readln;
  62. end.
  63.  

Output:

Code: Text  [Select][+][-]
  1. x+y = 4.0 + 6.0i
  2. x-y = -2.0 + -2.0i
  3. x*y = -5.0 + 10.0i
  4. x/y = 0.4 + 0.1i
  5. -x  = -1.0 + -2.0i
  6.  

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11793
  • Debugger - SynEdit - and more
    • wiki
Re: Operator overloading
« Reply #3 on: September 12, 2025, 09:34:53 pm »
@Tomu: Please use code tags. I added them for you (this time). Thanks

[ code=pascal]  Pascal code here  [ /code]

(remove spaces, and the above generates code)

LemonParty

  • Sr. Member
  • ****
  • Posts: 355
Re: Operator overloading
« Reply #4 on: September 12, 2025, 10:33:58 pm »
Great! Thank you.

Maybe code from LV should be added into wiki page.
Lazarus v. 4.99. FPC v. 3.3.1. Windows 11

jamie

  • Hero Member
  • *****
  • Posts: 7302
Re: Operator overloading
« Reply #5 on: September 13, 2025, 01:57:32 am »
I like things like this construction.
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4. {$modeSwitch AdvancedRecords}
  5. uses
  6.   {$IFDEF UNIX}
  7.   cthreads,
  8.   {$ENDIF}
  9.   Classes
  10.   { you can add units after this };
  11. Type
  12.   TMyRecord = Record
  13.      X,Y:Integer;
  14.      Function aXY(aaX,aaY:Integer):TMyRecord; inline;
  15.     Public
  16.      Property XY[aX,aY:Integer]:TMyRecord Read aXY; Default;
  17.   end;
  18.  Function TMyREcord.aXY(aaX,aaY:Integer):TMyRecord;
  19.   begin
  20.     X:=aax;Y:=aaY;
  21.     Result := Self;
  22.   end;
  23. Var
  24.   Plot1,Plot2:TmyRecord;
  25. begin
  26.   Plot2 := Plot1[10,4];
  27.   With Plot2 do
  28.    WriteLn(X,',',Y);
  29.   With Plot1 do
  30.    WriteLn(X,',',Y);
  31.   Readln;
  32. end.                    
  33.  

That is a shorthand for initializing record elements and cross assignment all in one!

That may even work better inline, too!

 :D
Jamie



« Last Edit: September 13, 2025, 11:53:37 pm by jamie »
The only true wisdom is knowing you know nothing

Thaddy

  • Hero Member
  • *****
  • Posts: 18306
  • Here stood a man who saw the Elbe and jumped it.
Re: Operator overloading
« Reply #6 on: September 13, 2025, 06:16:04 am »
That wiki entry is of really poor quality and is more or less not even a half-copy of the reference guide.
The official reference guide is much better and quite comprehensive.
https://www.freepascal.org/docs-html/ref/refch15.html

It is not a new feature, btw, it exists for more than 10 (closer to 20?, fpc 2.x.x before 2.4.0 ) years.

The standard code base (rtl and packages) makes clever use of it in many places.
For example in the math unit, my overload for floating point mod such that you write modulo operations on floating point values more easily or the uComplex, matrix or real48unit or other mathematical stuff.
From the math unit:
Code: Pascal  [Select][+][-]
  1. operator mod(const a,b:float) c:float;inline;
  2. operator ** (base,exponent : float) e: float; inline;
  3. operator ** (base,exponent : int64) res: int64;

I use operators and write operators almost daily.
They are, as an example - the basis of my x-way logic systems. See for example:
https://forum.lazarus.freepascal.org/index.php/topic,41144.msg295325.html#msg295325 for examples

But I also use them in audio systems where I can add filters and effects by means of operator overloads to an audio stream.
It makes code often much easier to understand and - when inlined - do not have a speed penalty.
(E.g, my mod operator overload generates the same code as the fmod function that uses the same code and makes it simpler to translate the C style % fp mod operator)

I also use the much more recent management operators for records quite often, although these are conceptually may be quite a different beast.

People do not realize it, but you are probably using operator overloads daily.
Example from the objpas unit:
Code: Pascal  [Select][+][-]
  1.        TMethod = record
  2.          Code : CodePointer;
  3.          Data : Pointer;
  4.        public
  5.          class operator =(const aLeft, aRight: TMethod): Boolean; inline;
  6.          class operator <>(const aLeft, aRight: TMethod): Boolean; inline;
  7.          class operator >(const aLeft, aRight: TMethod): Boolean; inline;
  8.          class operator >=(const aLeft, aRight: TMethod): Boolean; inline;
  9.          class operator <(const aLeft, aRight: TMethod): Boolean; inline;
  10.          class operator <=(const aLeft, aRight: TMethod): Boolean; inline;
  11.        end;

Btw, the wiki entry for management operators is well written, for that special case:
https://wiki.freepascal.org/management_operators
« Last Edit: September 13, 2025, 08:11:57 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Thaddy

  • Hero Member
  • *****
  • Posts: 18306
  • Here stood a man who saw the Elbe and jumped it.
Re: Operator overloading
« Reply #7 on: September 13, 2025, 08:23:12 am »
That may even work better inline, too!

 :D
Jamie
Why would code that makes an unnecessary copy be faster or efficient? (Result := self is a copy operation)
For what you do you can also simply use TRecord.Create(x,y) syntax.
Also, with records created through pointer (new) this leads to much more cumbersome code.
See the examples in the link for management operators I provided above.

The use of the default modifier is neat, though.
« Last Edit: September 13, 2025, 08:35:10 am by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

jamie

  • Hero Member
  • *****
  • Posts: 7302
Re: Operator overloading
« Reply #8 on: September 13, 2025, 12:28:42 pm »
Plot[ 20,4 ] instead of all that create code.
I just included the copy as a composite example.

Have u actually looked at the inlined asm code?

I use that in large code base inlined, it saves tons code editing and coder gen is good.

The only true wisdom is knowing you know nothing

Thaddy

  • Hero Member
  • *****
  • Posts: 18306
  • Here stood a man who saw the Elbe and jumped it.
Re: Operator overloading
« Reply #9 on: September 13, 2025, 01:09:50 pm »
Have u actually looked at the inlined asm code?
Yes I did.... It copies. So, no, not for me.
(Why do you even ask?, the one that didn't check is you, and you know it)

But the default is a neat trick.

Copying is not necessarily bad, but here it slows down.
In such cases better use the management operator initialize or a constructor.

You seem to have a problem with the speed of the management operators?
Well, there isn't much overhead, if any.
The generated code is fast. It only slows down (minute) compilation a bit.


Anyway, it is only just about on topic and only touches management operators for records and that is a different beast.
So, compile with -al and examine *.s
« Last Edit: September 13, 2025, 01:22:32 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

jamie

  • Hero Member
  • *****
  • Posts: 7302
Re: Operator overloading
« Reply #10 on: September 13, 2025, 03:02:42 pm »
I don't have any issues with code I use, I actually study the ASM results and decide what is best for me between code writing and what is generate by the compiler.

 Say what you want, as you normally would do and find whatever fault you can, as you normally do.

 I believe in balance between non-bloat and shortness of code writing...

 I prefer this:
 
 
Code: Pascal  [Select][+][-]
  1.  Plot[10,20]
  2.  
  or this
Code: Pascal  [Select][+][-]
  1.  Plot := TPlot.Create(10,20);
  2.  

As you can see, more typing on the second and still there is a copy there, whereas the first, there is no copy and the results is the same and putting that method member with INLINE status, that is only a couple of lines of ASM code.
 
Have a good day.

Jamie
The only true wisdom is knowing you know nothing

Thaddy

  • Hero Member
  • *****
  • Posts: 18306
  • Here stood a man who saw the Elbe and jumped it.
Re: Operator overloading
« Reply #11 on: September 13, 2025, 05:55:02 pm »
Not relevant and polluting the subject.
Other readers, please read from the beginning. There are several (almost all) serious answers and on topic.
« Last Edit: September 13, 2025, 06:02:38 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

jamie

  • Hero Member
  • *****
  • Posts: 7302
Re: Operator overloading
« Reply #12 on: September 13, 2025, 06:29:18 pm »
Not relevant and polluting the subject.
Other readers, please read from the beginning. There are several (almost all) serious answers and on topic.

 your answer does not surprise me at all; 8)

Have a good day.

Jamie
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018