Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2024-04

Operator overloading question: Impossible to overload assignment for equal types. Why?

7 messages · 3 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bart

Hi,

Overloading the := (assignment) operator for equal types is forbidden.
Out of curiosity I would like to know why that is?

When you have e.g. a record definition containing a dynamic array, not being able to overload the assignment operator is just a PITA.

OK, once you know why the assignment operator in such a case does not do what you intuitively thought it would do, you just work around this.

Just a simple example:

type
  TArr = array of integer;
  TRec = record
    A: TArr;
  end;
procedure DoItConst(const R: TRec);
var
  temp: TRec;
begin
  temp := R;
  temp.A[0] := 111;
end;
var
  R1, R2: TRec;
begin
  R1.A := [1,2,3];
  R2 := R1;
  R2.A[0] := 666;
  DoItConst(R2);
end.

After all this:
R1:
Length(R.A) = 3
R.A[0] = 111
R.A[1] = 2
R.A[2] = 666

R2:
Length(R.A) = 3
R.A[0] = 111
R.A[1] = 2
R.A[2] = 666

Yes: programmer error (PEBKAC).
(I once spent several hours to find out why my configuration got changed after passing a property around to a procedure similar to DoItConst ...)
So you write something like:

function AssignRec(Src: TRec): TRec;
begin
  Result.A := Copy(Src.A);
end;

And then call that in every place where you intuitively would have used the assignment operator, and avoid code like in DoIt().

In such instances it would really be helpfull if you could just
overload the assignment operator like:
operator := (Src: TRec): TRec;
begin
  Result := AssignRec(Src);
end;
Bart

Reply by email

Hairy Pixels
to Bart
Show quoted text 8 lines
On Apr 24, 2024, at 4:59 PM, Bart via fpc-devel wrote: In such instances it would really be helpfull if you could just overload the assignment operator like: operator := (Src: TRec): TRec; begin Result := AssignRec(Src); end;

I agree this seems reasonable but maybe the Copy operator makes more sense? It should have the same effect I think.

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Bart: Overloading the := (assignment) operator for equal types is forbidden. Out of curiosity I…

Bart via fpc-devel schrieb am Mi., 24.
Apr. 2024, 11:59:

Overloading the := (assignment) operator for equal types is forbidden. Out of curiosity I would like to know why that is?

If there exists a built-in operator then overloading that operator is forbidden to avoid confusion when what operator might be used (operators can after all be declared *anywhere* and thus they might sometimes be used and sometimes not depending on which unit is used).

When you have e.g. a record definition containing a dynamic array, not being able to overload the assignment operator is just a PITA.

Then declare a Copy management operator in the record. Unlike an assignment operator these *must* be part of the record, thus the same rules are applied for the same type everywhere unlike for operator overloads. See also https://wiki.freepascal.org/management_operators

Regards,
Sven

Reply by email

Bart
to Sven Barth
If there exists a built-in operator then overloading that operator is forbidden to avoid confusion when what operator might be used (operators can after all be declared *anywhere* and thus they might sometimes be used and sometimes not depending on which unit is used).

OK, that makes sense.

Then declare a Copy management operator in the record. Unlike an assignment operator these *must* be part of the record, thus the same rules are applied for the same type everywhere unlike for operator overloads. See also https://wiki.freepascal.org/management_operators

So, I would have to declare something like this?

class operator TArr.Copy(constref aSrc: TArr; var aDst: TArr);
begin
  aDst.A := Copy(aSrc.A);
end;

And then in my example:

R1.A := [1,2,3];
R2 := R1;
  --> R2.A will be (1,2,3), and changing that will not affect R1.A anymore

Sounds like a nice feature to have (in 3.4).

I'll write some tests to get familiar with this and if I don't forget I'll write a simple example in the wiki (there's a ToDo for that currently).

Bart

Reply by email

Sven Barth
to Bart

Bart via fpc-devel schrieb am Do., 25.
Apr. 2024, 11:48:

Show quoted text 19 lines
> Then declare a Copy management operator in the record. Unlike an assignment operator these *must* be part of the record, thus the same rules are applied for the same type everywhere unlike for operator overloads. See also https://wiki.freepascal.org/management_operators So, I would have to declare something like this? class operator TArr.Copy(constref aSrc: TArr; var aDst: TArr); begin aDst.A := Copy(aSrc.A); end; And then in my example: R1.A := [1,2,3]; R2 := R1; --> R2.A will be (1,2,3), and changing that will not affect R1.A anymore

Correct.

Sounds like a nice feature to have (in 3.4).

Management operators are already part of 3.2.x (
https://wiki.freepascal.org/FPC_New_Features_3.2.0#Management_operators_for_record_types ). Or did I misunderstand your remark? 🤔

I'll write some tests to get familiar with this and if I don't forget I'll write a simple example in the wiki (there's a ToDo for that currently).

Please do. 😊

Regards,
Sven

Reply by email