Recent

Author Topic: Operator overloading: Someone please explain this  (Read 8435 times)

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Operator overloading: Someone please explain this
« on: March 18, 2019, 09:07:57 pm »
Hi Folks,

playing around i overloaded some operators
Code: Pascal  [Select][+][-]
  1. //Somewhere in a Unit
  2. interface
  3. //String and LongInt
  4. Operator +(AString:String;ALongInt:LongInt):String;Overload;
  5. Operator +(ALongInt:LongInt;AString:String):String;Overload;                  
  6.  
  7. Implementation
  8. Operator +(AString:String;ALongInt:LongInt):String;
  9. Begin
  10.   Result:=AString+ALongInt.ToString;
  11. end;  
  12. Operator +(ALongInt:LongInt;AString:String):String;
  13. Begin
  14.   Result:=ALongInt.ToString+AString;
  15. end;      
  16.  

Using above i stumbled across this:
Code: Pascal  [Select][+][-]
  1. Uses MyOperatorUnit;
  2. Var
  3. MyText:String;
  4. MyNumber:Integer;      
  5.  
  6. Begin
  7. MyText:='Test ';
  8. MyNumber:=123456;      
  9. Writeln(MyText+MyNumber); //Works
  10. Writeln(MyNumber+MyText); //Works
  11. Writeln(MyNumber+' Test'); //Works
  12. Writeln(123456+MyText);  //Works
  13. Writeln(MyText+123456);   //Works
  14. Writeln('Test '+MyNumber); //Doesn't work?!?!??! --> project1.lpr(19,19) Error: Incompatible types: got "LongInt" expected "AnsiString"
  15.  
  16.  

Huh? I'm looking at it, and it doesn't make any sense to me.
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

ASerge

  • Hero Member
  • *****
  • Posts: 2222
Re: Operator overloading: Someone please explain this
« Reply #1 on: March 18, 2019, 09:25:18 pm »
Code: Pascal  [Select][+][-]
  1. Writeln('Test '+MyNumber); //Doesn't work?!?!??! --> project1.lpr(19,19) Error: Incompatible types: got "LongInt" expected "AnsiString"
Huh? I'm looking at it, and it doesn't make any sense to me.
A quoted string can be string, UnicodeString, ShortString, PChar, PWideChar and so on. Cast it: string('Test ') +...

Thaddy

  • Hero Member
  • *****
  • Posts: 14201
  • Probably until I exterminate Putin.
Re: Operator overloading: Someone please explain this
« Reply #2 on: March 18, 2019, 09:35:35 pm »
The real explanation is adding {$H+}
Specialize a type, not a var.

ASerge

  • Hero Member
  • *****
  • Posts: 2222
Re: Operator overloading: Someone please explain this
« Reply #3 on: March 18, 2019, 09:40:41 pm »
The real explanation is adding {$H+}
Check before you advise. The error occurs in {$H+}
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2. {$APPTYPE CONSOLE}
  3. {$LONGSTRINGS ON}
  4.  
  5. uses SysUtils;
  6.  
  7. operator + (const Left: string; Right: LongInt): string;
  8. begin
  9.   Result := Left + IntToStr(Right);
  10. end;
  11.  
  12. operator + (Left: LongInt; const Right: string): string;
  13. begin
  14.   Result := IntToStr(Left) + Right;
  15. end;
  16.  
  17. var
  18.   Text: string = 'text';
  19.   Number: LongInt = 123456;
  20. begin
  21.   Writeln(Text + Number);
  22.   Writeln(Number + Text);
  23.   Writeln(Number + 'other text');
  24.   Writeln(789012 + Text);
  25.   Writeln(Text + 789012);
  26.   Writeln('else text' + Number); // project1.lpr(26,25) Error: Incompatible types: got "LongInt" expected "AnsiString"
  27.   Readln;
  28. end.

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Operator overloading: Someone please explain this
« Reply #4 on: March 18, 2019, 10:37:56 pm »
So what's the Explanation/Solution?
You lost me along the way there....
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Operator overloading: Someone please explain this
« Reply #5 on: March 18, 2019, 10:51:28 pm »
ASerge already explained.
A string constant could be, for example, a PChar.
Because of the plethora of string types FPC supports, the compiler cannot know unambiguously what the type of
Code: Pascal  [Select][+][-]
  1.  'some string constant'
might be.
Casting the constant to a String, allows the compiler to see that it is indeed compatible with the String declaration of the parameter in your overloaded operator function.

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Operator overloading: Someone please explain this
« Reply #6 on: March 18, 2019, 10:59:00 pm »
ASerge already explained.
A string constant could be, for example, a PChar.
Because of the plethora of string types FPC supports, the compiler cannot know unambiguously what the type of
Code: Pascal  [Select][+][-]
  1.  'some string constant'
might be.
Casting the constant to a String, allows the compiler to see that it is indeed compatible with the String declaration of the parameter in your overloaded operator function.

????
Then the Error-Message doesn't make sense one jot at all. I was looking at the Integer the whole time, while my String-Literal was at fault.
The Error marked the Integer-Variable to boot!
And it doesn't explain why my Line 11/Serge's Line23 works.....

Or is it because that very first argument is that ambiguous Literal?
Because going by that logic, something like
Writeln('Text1 '+' Text2');
shouldn't work, which it does;
Oh, and FWIW: I stumbled across that not by using Writeln, but passing a String to a Function/Procedure which expects a String
« Last Edit: March 18, 2019, 11:02:30 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Operator overloading: Someone please explain this
« Reply #7 on: March 18, 2019, 11:13:41 pm »
After fiddling around a bit more, i'm still not satisfied with the proposed Answer!

For grins i did a

Code: Pascal  [Select][+][-]
  1. Var
  2. b:Boolean;
  3.  
  4. Begin
  5. Writeln('Test '+b);
  6.  

How is it, that the compiler throws the error
project1.lpr(7,18) Error: Operator is not overloaded: "Constant String" + "Boolean"

Constant String against Boolean.
So, the compiler recognizes it as a Constant String.
If i overload the "+"-Operator in a String/Boolean and Boolean/String-Combination, all combinations pass, even those with Literals

Writeln('This '+True);                  //Works!

EDIT:
Everything in
{$mode objfpc}{$H+}         

EDIT: OH NONONO
I Reject the Answer.
I just did the same Test as in my first Post, but with Double instead of Integer. It worked in all combinations!
So no, i don't believe it's the "Constant string" and the Error-Message is correct. It's the Integer!

EDIT3:
There is something wrong. I just commented out my operator unit (to force error-messages)
In the combination in question it's still the same error-message, so the error occurs before checking if an (overloaded) operator is available
« Last Edit: March 18, 2019, 11:24:41 pm by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: Operator overloading: Someone please explain this
« Reply #8 on: March 19, 2019, 01:26:21 am »
You are correct.
The compiler appears to treat a constant string in combination with other types differently if the other type is any kind of integer.
It seems to get stuck at its own internal concatenation attempt, and fails to consider the correctly declared overloaded operator alternative.

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Operator overloading: Someone please explain this
« Reply #9 on: March 19, 2019, 06:33:25 am »
You are correct.
The compiler appears to treat a constant string in combination with other types differently if the other type is any kind of integer.
It seems to get stuck at its own internal concatenation attempt, and fails to consider the correctly declared overloaded operator alternative.
Conclusion: Bug?
Considering a boolean (see above) is basically an integer
« Last Edit: March 19, 2019, 06:36:03 am by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 14201
  • Probably until I exterminate Putin.
Re: Operator overloading: Someone please explain this
« Reply #10 on: March 19, 2019, 09:25:20 am »
Yes, it is a bug, and for all supported string types the same bug. Same happens in shortstring, ansistring and unicodestring modes.
Just to be sure I also tested if sysutils could have some influence (because it contains some overloads?), but that is not the case.
Here's my reduced example:
Code: Pascal  [Select][+][-]
  1. {$MODE OBJFPC}
  2. {$IFDEF MSWINDOWS}{$APPTYPE CONSOLE}{$ENDIF}
  3.  
  4. operator + (Left: LongInt; const Right: string): string;
  5. begin
  6.   writestr(Result,Left,Right);
  7. end;
  8.  
  9. operator + (const Left: string; Right: LongInt): string;
  10. begin
  11.   writestr(Result,Left,Right);
  12. end;
  13.  
  14. var
  15.   Text: string = 'text';
  16.   Number: LongInt = 123456;
  17. begin
  18.   Writeln(Text + Number); // V+V
  19.   Writeln(Number + Text); // V+V
  20.   Writeln(789012 + Text);//L+V
  21.   Writeln(Text+789012);//V+L
  22.   // Next fails and is L+V
  23.   Writeln('else text'+Number); // fails only on LEFT string literals + non-literal number with all string types
  24.   // Next pass again
  25.   Writeln(Number + 'other text'); // passes, V+L
  26.   Writeln(string('else text')+Number); //passes, cast(L)+V
  27.   writeln(789012 + 'other text'); // passes, L+L
  28.   writeln('other text',789012); // passes, L+L
  29.   Readln;
  30.   Readln;
  31. end.
As you can see I have added some more - missing- tests from which one can conclude that this is the exact issue:
The overloaded operator fails only on LEFT string literals + non-literal number with all string types.
All other possible cases pass.
« Last Edit: March 19, 2019, 10:54:11 am by Thaddy »
Specialize a type, not a var.

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Operator overloading: Someone please explain this
« Reply #11 on: March 19, 2019, 11:35:34 am »
Someone going to report that bug?
I've never done that  :D :D :D :D

EDIT: Thaddy, your last Test is not of the same variety. You use Writeln String-Literal COMMA LiteralInteger.
You're passing 2 Arguments to Writeln instead of one

writeln('Test'+123456);   
This one fails too with the same errormessage
« Last Edit: March 19, 2019, 11:40:23 am by Zvoni »
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 14201
  • Probably until I exterminate Putin.
Re: Operator overloading: Someone please explain this
« Reply #12 on: March 19, 2019, 11:37:06 am »
I will do that now.
Specialize a type, not a var.

Zvoni

  • Hero Member
  • *****
  • Posts: 2319
Re: Operator overloading: Someone please explain this
« Reply #13 on: March 19, 2019, 11:40:34 am »
See my edit
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Thaddy

  • Hero Member
  • *****
  • Posts: 14201
  • Probably until I exterminate Putin.
Re: Operator overloading: Someone please explain this
« Reply #14 on: March 19, 2019, 12:17:36 pm »
Mm. call it a typo. Corrected.
Specialize a type, not a var.

 

TinyPortal © 2005-2018