# Implementing Binary Operations

Go Up to Using the RTL Index

To allow the custom variant type to work with standard binary operators (+, -, *, /, div, mod, shl, shr, and, or, xor listed in the System unit), you must override the BinaryOp method. `BinaryOp` has three parameters: the value of the left-hand operand, the value of the right-hand operand, and the operator. Implement this method to perform the operation, and return the result using the same variable that contained the left-hand operand.

For example, the following `BinaryOp` method comes from the `TComplexVariantType` defined in the System.VarCmplx unit:

Object Pascal:

``` procedure TComplexVariantType.BinaryOp(var Left: TVarData; const Right: TVarData;
const Operator: TVarOp);
begin
if Right.VType = VarType then
case Left.VType of
varString:
case Operator of
opAdd: Variant(Left) := Variant(Left) + TComplexVarData(Right).VComplex.AsString;
else
RaiseInvalidOp;
end;
else
if Left.VType = VarType then
case Operator of
opSubtract:
TComplexVarData(Left).VComplex.DoSubtract(TComplexVarData(Right).VComplex);
opMultiply:
TComplexVarData(Left).VComplex.DoMultiply(TComplexVarData(Right).VComplex);
opDivide:
TComplexVarData(Left).VComplex.DoDivide(TComplexVarData(Right).VComplex);
else
RaiseInvalidOp;
end
else
RaiseInvalidOp;
end
else
RaiseInvalidOp;
end;
```

There are several things to note in this implementation:

This method only handles the case where the variant on the right side of the operator is a custom variant that represents a complex number. If the left-hand operand is a complex variant and the right-hand operand is not, the complex variant forces the right-hand operand first to be cast to a complex variant. It does this by overriding the RightPromotion method so that it always requires the type in the `VarType` property:

Object Pascal:

``` function TComplexVariantType.RightPromotion(const V: TVarData;
const Operator: TVarOp; out RequiredVarType: TVarType): Boolean;
begin
{ Complex Op TypeX }
RequiredVarType := VarType;
Result := True;
end;
```

The addition operator is implemented for a string and a complex number (by casting the complex value to a string and concatenating), and the addition, subtraction, multiplication, and division operators are implemented for two complex numbers using the methods of the `TComplexData` object that is stored in the complex variant's data. This is accessed by casting the `TVarData` record to a `TComplexVarData` record and using its `VComplex` member.

Attempting any other operator or combination of types causes the method to call the `RaiseInvalidOp` method, which causes a runtime error. The `TCustomVariantType` class includes a number of utility methods such as `RaiseInvalidOp` that can be used in the implementation of custom variant types.

`BinaryOp` only deals with a limited number of types: strings and other complex variants. It is possible, however, to perform operations between complex numbers and other numeric types. For the `BinaryOp` method to work, the operands must be cast to complex variants before the values are passed to this method. We have already seen (above) how to use the `RightPromotion` method to force the right-hand operand to be a complex variant if the left-hand operand is complex. A similar method, LeftPromotion, forces a cast of the left-hand operand when the right-hand operand is complex:

Object Pascal:

```function TComplexVariantType.LeftPromotion(const V: TVarData; const Operator: TVarOp; out RequiredVarType: TVarType): Boolean;
begin
{ TypeX Op Complex }
if (Operator = opAdd) and VarDataIsStr(V) then
RequiredVarType := varString
else
RequiredVarType := VarType;
Result := True;
end;
```

This `LeftPromotion` method forces the left-hand operand to be cast to another complex variant, unless it is a string and the operation is addition, in which case `LeftPromotion` allows the operand to remain a string.