Reputation: 473
I'm trying to compile this code :
function valid(a:Toto'Class; t: Titi) return Boolean with Pre'Class => fonction(a);
GNAT says "aspect "pre'class" can only be specified for a primitive operation of a tagged private"
I guess it's because of the Toto'Class but how could I make it work ?
Upvotes: 0
Views: 329
Reputation: 31689
The purpose of Pre'Class
and Post'Class
, I believe, is to specify preconditions that apply even when a subprogram is overridden.
package Pack1 is
type Base_Type is tagged record ... end record;
procedure Operation (Obj : Base_Type) with Pre'Class => [condition];
end Pack1;
What this means is that if the condition is met, then Operation
is allowed, even if derived types impose other conditions. Suppose a procedure uses this operation on a Base_Type'Class
object:
procedure Something_Else (Obj : Base_Type'Class) is
begin
-- check to make sure the condition is true
Obj.Operation;
end Something_Else;
Something_Else
doesn't know what the actual type of Obj
is. But it can still be assured that if the Pre'Class
condition is true
, then Operation
can be performed (i.e. it satisfies the preconditions). If the condition were just Pre => [condition]
, it could not be assured that this would work, because Obj
's actual type could be a derived type, and Operation
could be overridden for that derived type with a more restrictive condition, and the condition on the overriding Operation
would be the one that is checked (since the call would dispatch to the overriding Operation
). With Pre'Class
, both conditions are checked, and the operation is allowable if either condition is true (thus a derived type can make things less restrictive). But the important thing is that Something_Else
is relying on the contract that, if the Pre'Class
condition is true, then Operation
is allowable.
However, none of this matters if Operation
can't be overridden. In your example, since Valid
's parameter is Toto'Class
, and since (I assume) Titi
is not a tagged type, Valid
is not a primitive operation and therefore is not a dispatching operation.
procedure Another_Procedure (Obj : Toto'Class; T : Titi) is
begin
if Obj.Valid(T) then
...
end if;
end Another_Procedure;
When Another_Procedure
calls Valid
, it will always call the Valid
that you wrote; it will never dispatch to a different Valid
, no matter what type Obj
actually is. Valid
is not a dispatching function. Because of that, there's no point in putting a class-wide precondition on it. So the language disallows it.
Note: In a simple case where there is just a base type and a derived type, not a chain of types, Pre'Class
means that an operation can be performed if the condition or any precondition on the derived type succeeds. Post'Class
means that a subprogram meets the condition if the condition and any postcondition on the derived type succeed.
Upvotes: 3