Operator overloading

From Free Pascal wiki

English (en)


Operator overloading refers to re-defining already defined operators with new definitions. The term is – although imprecisely – used for operator definitions, that have not yet been defined, too.

availability

FPC allows operator overloading, however it is not allowed in {$mode TP} or {$mode MacPas}. In {$mode Delphi}, operator overloading can only be done in the context of classes or advanced records (confer Delphi documentation), so the Delphi mode does not support global operator overloads as {$mode FPC} and {$mode objFPC} do.

overloadable operators

Almost all operators can be (re-)defined:

  • assignment operators
    • :=
    • the special operator explicit (referring to explicit typecasts)
  • arithmetic operators
    • + (only binary operation)
    • - (both unary and binary)
    • *
    • **
    • div
    • mod
    • /
    • inc
    • dec
    • (As of 2019 in the future: pow)
  • comparison operators
  • logical operators
  • and the special operator enumerator.

The only operators that can not be overloaded are @ (address operator), ^ (de-referencing operator), as and is.

definition

An operator is declared as if it was a function, with a few differences:

  • Instead of the word function it starts with operator.
  • The function's identifier is always one of the available operators e.g. ><, although this would not constitute a valid identifier anywhere else. However, in {$mode Delphi} a spelled out operator name has to be used. These are allowed in other modes, too:
Delphi compatibility operator names
operator symbol symbolic name
:= assign
+ add
- subtract
* multiply
div intDivide
mod modulus
/ divide
= equal
<> notEqual
< lessThan
<= lessThanOrEqual
> greaterThan
>= greaterThanOrEqual
>< symmetricalDifference
not logicalNot
and logicalAnd
or logicalOr
not bitwiseNot
and bitwiseAnd
or bitwiseOr
xor bitwiseXor
shl leftShift
shr rightShift
  • The parameter list has to name exactly one or two parameters, depending on the operator.
  • A result identifier has to be specified in front of the colon separating the result type, but can be omitted where the special identifier result is available.
  • Note, the concept of “default parameters,” that means a default value for a parameter, only applies to “real” functions. When an operator is used, e.g. in an expression, you can not just skip naming an operand, hoping the compiler will insert “something”. Therefore, the concept of default parameter values does not apply to operator overloads.

The following shows a valid operator declaration (in {$mode Delphi} the := has to be replaced by assign and the declaration may only appear in the context of class or advanced record definitions).

operator := (x: myNewType) y: someOtherType;

Operators are defined the same way as any other function, by following the signature with a block.

Some operator overloads are not allowed:

routing

How an operator overload definition is chosen differs in many aspects how a function is chosen.

  • The assignment operator := is used for implicit typecasts. Everywhere, where a value has to be stored in memory, an implicit typecast may occur. Note, that calling a routine requires storing its parameters in memory, too, thus the parameter list might become subject of implicit typecasts as well, even though on the surface they are not part of an assignment statement.
  • Unlike regular function overloads, assignment operator overloads are chosen by their result type.
  • Operator overloads can not be chosen explicitly by their scope they are defined in. Something like unitDefiningOverloads.+ is not possible. The last operator definition always wins and this can not be changed.
  • Operator precedence remains as usual for all operator symbols. When defining operators for a new custom type from scratch, the * will still bind stronger than the +. The operator precedence system can not be altered.

Operator overloads should be used with caution. They potentially make it harder to identify problems, since it is not necessarily obvious, that an operator overload applies.

see also