User-Defined Operators
Overload Ada's operators (+, -, *, /, abs, <, =, and, &, ...) for your own types by declaring functions with quoted names, understand which operators can be redefined, how 'use type' makes them visible, and design guidelines for natural operator semantics.
Any Ada operator symbol can be defined for your own types by writing a function whose name is the operator in quotes: function "+" (L, R : Vector) return Vector. Calls then look natural (A + B) while remaining ordinary, type-checked function calls. This is how vector math, money, units, big numbers and matrix libraries provide clean interfaces.
Declaring Operators
Binary operators take two parameters (Left, Right), unary ones one parameter. The overloadable operators are: and or xor = /= < <= > >= + - & * / mod rem ** abs not. You cannot invent new symbols or change precedence, arity or the short-circuit forms (and then, or else), membership (in) or assignment (:=). Operators can mix types: "*" (K : Float; V : Vector) enables 2.0 * V. Operators can also be overloaded on result type, e.g. "*" returning a Float dot product versus a Vector scaling.
Defining "=" with a Boolean result automatically gives you "/=" as its negation. Predefined "=" for records compares all components; redefine it when logical equality differs (e.g. case-insensitive names or floating tolerance).
• function "op" (L, R : T) return R_Type — quoted operator name. • Overloadable: and or xor = /= < <= > >= + - & * / mod rem ** abs not. • Cannot overload: :=, and then, or else, in, not in; cannot change precedence. • Defining "=" gives "/=" automatically.
Visibility: use type
When operators are declared in a package (e.g. Geometry), clients must make them visible to use infix notation. 'use Geometry;' makes everything visible; the lighter 'use type Geometry.Vector;' makes only the operators of that type directly visible, which is the recommended style. Without either, you would have to write Geometry."+" (A, B). Ada 2012's 'use all type' also makes the type's primitive subprograms visible.
• use type Pkg.T; — makes T's operators usable infix. • use all type Pkg.T; — also its primitive subprograms. • Fallback: Pkg."+" (A, B).
Code Examples
Vector gets +, -, scalar *, a dot-product * overloaded on result type, abs as squared length and < comparing lengths. Record aggregates like (L.X + R.X, L.Y + R.Y) build the results. Predefined = compares components. Output: A + B = ( 4.00000E+00, 1.00000E+00) A - B = (-2.00000E+00, 3.00000E+00) 2.0 * A = ( 2.00000E+00, 4.00000E+00) A * B = 1.00000E+00 abs B = 1.00000E+01 A < B = TRUE A = (1,2) = TRUE function "+" (L, R: Money) return Money is (L - R);
function "+" (L, R : Money) return Money is (Money (Float (L) + Float (R)));
Operators must keep their conventional meaning; surprising semantics make code unreadable.
Sum:= A + B; -- "+" declared in package Geometry, not visible use type Geometry.Vector;... Sum:= A + B;
Make the operators visible with use type.
function "=" (L, R : T) return Integer;
function "=" (L, R : T) return Boolean;
An "=" returning Boolean gets "/=" for free and behaves as expected in conditions.
How do you declare a '+' operator for type Vector? A. operator + (L, R : Vector) B. function "+" (L, R : Vector) return Vector C. procedure "+" (L, R : Vector) D. overload + for Vector
B. A function with the quoted operator name.
Which cannot be overloaded? A. abs B. & C. and then D. mod C. and then — short-circuit forms cannot be redefined.
What does 'use type Pkg.T;' do? A. Makes all of Pkg visible B. Makes T's operators directly visible C. Renames T D. Converts types
B. Makes the operators of T usable with infix notation.
If you define "=" returning Boolean, what about "/="? A. Must define it too B. Defined implicitly as not "=" C. Illegal D. Unchanged predefined version
B. It is implicitly the negation of your "=".
Trace the operator example.
Real output: A + B = ( 4.00000E+00, 1.00000E+00 ) A - B = (-2.00000E+00, 3.00000E+00 ) 2.0 * A = ( 2.00000E+00, 4.00000E+00 ) A * B = 1.00000E+00 abs B = 1.00000E+01 A < B = TRUE A = (1,2) = TRUE A * B = 1×3 + 2×(-1) = 1; abs B = 9 + 1 = 10; abs A = 5 < 10 so A < B.
with Ada.Text_IO; use Ada.Text_IO;
procedure L18_Operators is
type Vector is record
X, Y : Float;
end record;
function "+" (L, R : Vector) return Vector is ((L.X + R.X, L.Y + R.Y));
function "-" (L, R : Vector) return Vector is ((L.X - R.X, L.Y - R.Y));
function "*" (K : Float; V : Vector) return Vector is ((K * V.X, K * V.Y));
function "*" (L, R : Vector) return Float is (L.X * R.X + L.Y * R.Y); -- dot product
function "abs" (V : Vector) return Float is (V.X * V.X + V.Y * V.Y); -- squared length
function "<" (L, R : Vector) return Boolean is (abs L < abs R);
function Image (V : Vector) return String is
("(" & Float'Image (V.X) & "," & Float'Image (V.Y) & " )");
A : constant Vector := (1.0, 2.0);
B : constant Vector := (3.0, -1.0);
begin
Put_Line ("A + B = " & Image (A + B));
Put_Line ("A - B = " & Image (A - B));
Put_Line ("2.0 * A = " & Image (2.0 * A));
Put_Line ("A * B =" & Float'Image (A * B));
Put_Line ("abs B =" & Float'Image (abs B));
Put_Line ("A < B = " & Boolean'Image (A < B));
Put_Line ("A = (1,2) = " & Boolean'Image (A = (1.0, 2.0))); -- predefined "=" on records
end L1
…