Operator Overloading and Custom Managed Records
26.1 Operator Overloading (Records)
Supported operators: Add, Subtract, Multiply, Divide, IntDivide, Modulus, Negative, Positive, Inc, Dec, LogicalNot, LogicalAnd, LogicalOr, LogicalXor, BitwiseAnd/Or/Xor, LeftShift, RightShift, Equal, NotEqual, GreaterThan, LessThan, GreaterThanOrEqual, LessThanOrEqual, Implicit, Explicit, In, Round, Trunc.
Operator overloading is supported on records, not on classes (classes only on mobile under the old ARC model).
type
TMoney = record
private
FAmount: Currency;
FCurrency: string;
public
constructor Create(AAmount: Currency; const ACurrency: string);
class operator Add(const A, B: TMoney): TMoney;
class operator Subtract(const A, B: TMoney): TMoney;
class operator Multiply(const A: TMoney; Factor: Double): TMoney;
class operator Equal(const A, B: TMoney): Boolean;
class operator NotEqual(const A, B: TMoney): Boolean;
class operator GreaterThan(const A, B: TMoney): Boolean;
class operator Implicit(Value: Currency): TMoney; // implicit conversion
class operator Explicit(const Value: TMoney): Currency; // explicit cast
function ToString: string;
end;
class operator TMoney.Add(const A, B: TMoney): TMoney;
begin
if A.FCurrency <> B.FCurrency then raise EInvalidOpException.Create('Currency mismatch');
Result := TMoney.Create(A.FAmount + B.FAmount, A.FCurrency);
end;
class operator TMoney.Implicit(Value: Currency): TMoney;
begin
Result := TMoney.Create(Value, 'USD');
end;
var Price: TMoney := 19.99; // Implicit
var Total := Price * 3 + TMoney.Create(5, 'USD');
var Raw := Currency(Total); // Explicit26.2 Custom Managed Records (Delphi 10.4+)
This enables RAII-style smart pointers, scoped locks, and auto-freeing wrappers:
type
TSmartBuffer = record
private
FData: Pointer;
FSize: NativeInt;
public
class operator Initialize(out Dest: TSmartBuffer); // called on declaration
class operator Finalize(var Dest: TSmartBuffer); // called when going out of scope
class operator Assign(var Dest: TSmartBuffer; const [ref] Src: TSmartBuffer); // custom copy
procedure Allocate(Size: NativeInt);
end;
class operator TSmartBuffer.Initialize(out Dest: TSmartBuffer);
begin
Dest.FData := nil;
Dest.FSize := 0;
end;
class operator TSmartBuffer.Finalize(var Dest: TSmartBuffer);
begin
FreeMem(Dest.FData); // RAII: automatic cleanup
end;
class operator TSmartBuffer.Assign(var Dest: TSmartBuffer; const [ref] Src: TSmartBuffer);
begin
Dest.Allocate(Src.FSize);
Move(Src.FData^, Dest.FData^, Src.FSize); // deep copy
end;type
TAutoFree<T: class> = record
private
FObj: T;
public
class operator Initialize(out Dest: TAutoFree<T>);
class operator Finalize(var Dest: TAutoFree<T>);
property Obj: T read FObj write FObj;
end;