Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to overload Inc (Dec) operators in Delphi?

Delphi documentation says that it is possible to overload the Inc and Dec operators; I see no valid way to do it. Here are attempts to overload the Inc operator; some attempts lead to compile errors, some to runtime access violation (Delphi XE):

program OverloadInc;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TMyInt = record
    FValue: Integer;
//    class operator Inc(var A: TMyInt);   DCC error E2023
    class operator Inc(var A: TMyInt): TMyInt;
    property Value: Integer read FValue write FValue;
  end;

class operator TMyInt.Inc(var A: TMyInt): TMyInt;
begin
  Inc(A.FValue);
  Result:= A;
end;

type
  TMyInt2 = record
    FValue: Integer;
    class operator Inc(A: TMyInt2): TMyInt2;
    property Value: Integer read FValue write FValue;
  end;

class operator TMyInt2.Inc(A: TMyInt2): TMyInt2;
begin
  Result.FValue:= A.FValue + 1;
end;

procedure Test;
var
  A: TMyInt;

begin
  A.FValue:= 0;
  Inc(A);
  Writeln(A.FValue);
end;

procedure Test2;
var
  A: TMyInt2;
  I: Integer;

begin
  A.FValue:= 0;
//  A:= Inc(A);  DCC error E2010
  Writeln(A.FValue);
end;

begin
  try
    Test;     // access violation
//    Test2;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.
like image 570
kludg Avatar asked Oct 06 '15 07:10

kludg


People also ask

How do you overload the operator?

To overload an operator, we use a special operator function. We define the function inside the class or structure whose objects/variables we want the overloaded operator to work with.

Can we overload address of operator?

It is not possible to change the precedence, grouping, or number of operands of operators. The overload of operator -> must either return a raw pointer, or return an object (by reference or by value) for which operator -> is in turn overloaded.

Can we overload all operators?

To work, at least one of the operands must be a user-defined class object. We can only overload the existing operators, Can't overload new operators. Some operators cannot be overloaded using a friend function. However, such operators can be overloaded using the member function.

Which keyword is used to overload an operator?

Operators Overloading in C++ Overloaded operators are functions with special names: the keyword "operator" followed by the symbol for the operator being defined.


1 Answers

The signature of the operator is wrong. It should be:

class operator Inc(const A: TMyInt): TMyInt;

or

class operator Inc(A: TMyInt): TMyInt;

You cannot use a var parameter.

This program

{$APPTYPE CONSOLE}

type
  TMyInt = record
    FValue: Integer;
    class operator Inc(const A: TMyInt): TMyInt;
    property Value: Integer read FValue write FValue;
  end;

class operator TMyInt.Inc(const A: TMyInt): TMyInt;
begin
  Result.FValue := A.FValue + 1;
end;

procedure Test;
var
  A: TMyInt;
begin
  A.FValue := 0;
  Inc(A);
  Writeln(A.FValue);
end;

begin
  Test;
  Readln;
end.

produces this output:

1

Discussion

This is a rather unusual operator when overloaded. In terms of usage the operator is an in-place mutation. However, when overloaded, it works like an addition operator with an implicit addend of one.

So, in the code above this line:

Inc(A);

is effectively transformed into

A := TMyInt.Inc(A);

and then compiled.

If you are wanting to maintain true in-place mutation semantics, and avoid the copying associated with this operator, then I believe that you need to use a method of the type.

procedure Inc; inline;
....
procedure TMyInt.Inc;
begin
  inc(FValue);
end;
like image 186
David Heffernan Avatar answered Nov 14 '22 23:11

David Heffernan