What are the differences in efficiency when using a scalar subtype rather than precondition and postcondition aspect clauses?
There are several ways to evaluate efficiency. One is code terseness—using fewer lines of source code. Another is execution efficiency. Yet another is code consistency.
You can define constraints on the input and output values of a function using preconditions and postconditions, such as:
type Shape is tagged record
Area : Float;
end record;
procedure Compute_Area (S : in out Shape)
with
Pre => S.Area >= 0.0,
Post => S.Area >= 0.0;
An alternative to using preconditions and postconditions is to define a subtype of Float, such as:
subtype shape_area is float range 0.0 .. float'last;
type shape is tagged record with
Area : shape_area;
end record;
procedure compute_area (S : in out shape'class);
Which approach above provides the most efficiency?
Edit: Ada types and subtypes can be specified using range constraints, type invariants, or subtype predicates. As described in the Ada 2012 Rationale, type invariants can be used to establish relationships between data members in a private type—for example, ensuring that the X and Y coordinates of a point always lie within a unit circle:
package Places is
type Disc_Pt is private;
... --various operations on disc points
private
type Disc_Pt is
record
X, Y: Float range –1.0 .. +1.0;
end record
with Type_Invariant =>
Disc_Pt.X**2 + Disc_Pt.Y**2 <= 1.0;
end Places;
As seen above, type invariants can involve calculations and are applied as constraints on the type. In this case, the type invariant constraint is used alongside a range constraint.
Is using a type invariant more efficient than using subprogram aspect clauses?