RAD Studio |  |

Implementing Binary Operations
See Also
Collapse All

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 VarCmplx unit:

Copy Code

    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
                opAdd:
                  TComplexVarData(Left).VComplex.DoAdd(TComplexVarData(Right).VComplex);
                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:

Copy Code

    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:

Copy Code

    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.

See Also

Implementing Comparison Operations

Implementing Unary Operations

Enabling Casting

Copying and Clearing Custom Variants

Using the TCustomVariantType Descendant

Loading and Saving Custom Variant Values

Copyright(C) 2009 Embarcadero Technologies, Inc. All Rights Reserved.
What do you think about this topic? Send feedback!