3.9.2 Dispatching Operations of Tagged Types
primitive subprograms of a tagged type, the subprograms declared by formal_abstract_subprogram_declaration
and the stream attributes of a specific tagged type that are available
) at the end of the declaration
list where the type is declared are called dispatching operations
A dispatching operation can be called using a statically determined controlling
tag, in which case the body to be executed is determined at compile time.
Alternatively, the controlling tag can be dynamically determined, in
which case the call dispatches
to a body that is determined at
run time; such a call is termed a dispatching call
. As explained
below, the properties of the operands and the context of a particular
call on a dispatching operation determine how the controlling tag is
determined, and hence whether or not the call is a dispatching call.
Run-time polymorphism is achieved when a dispatching operation is called
by a dispatching call.
on a dispatching operation
is a call whose name
denotes the declaration of a dispatching operation.
in a call on a dispatching operation of a
tagged type T
is one whose corresponding formal parameter is of
or is of an anonymous access type with designated type
the corresponding formal parameter is called
a controlling formal parameter
. If the controlling formal parameter
is an access parameter, the controlling operand is the object designated
by the actual parameter, rather than the actual parameter itself.
the call is to a (primitive) function with result type T
the call has a controlling result
— the context of the call
can control the dispatching. Similarly, if the call is to a function
with access result type designating T
, then the call has a controlling
, and the context can similarly control dispatching.
or expression of a tagged type is either statically
tagged, or tag indeterminate
, according to whether, when used
as a controlling operand, the tag that controls dispatching is determined
statically by the operand's (specific) type, dynamically by its tag at
run time, or from context. A qualified_expression
or parenthesized expression is statically, dynamically, or indeterminately
tagged according to its operand. For other kinds of name
and expressions, this is determined as follows:
- The name
or expression is statically tagged if it is of a specific tagged
type and, if it is a call with a controlling result or controlling access
result, it has at least one statically tagged controlling operand;
- The name
or expression is dynamically tagged if it is of a class-wide type,
or it is a call with a controlling result or controlling access result
and at least one dynamically tagged controlling operand;
- The name
or expression is tag indeterminate if it is a call with a controlling
result or controlling access result, all of whose controlling operands
(if any) are tag indeterminate.
is statically or dynamically tagged according to whether the type determined
by the subtype_mark
is specific or class-wide, respectively. For an object that is designated
by an expression whose expected type is an anonymous access-to-specific
tagged type, the object is dynamically tagged if the expression, ignoring
enclosing parentheses, is of the form X'Access, where X is of a class-wide
type, or is of the form new
T'(...), where T denotes a class-wide
subtype. Otherwise, the object is statically or dynamically tagged according
to whether the designated type of the type of the expression is specific
or class-wide, respectively.
A call on a dispatching operation shall not have
both dynamically tagged and statically tagged controlling operands.
If the expected type for an expression or name
is some specific tagged type, then the expression or name
shall not be dynamically tagged unless it is a controlling operand in
a call on a dispatching operation. Similarly, if the expected type for
an expression is an anonymous access-to-specific tagged type, then the
object designated by the expression shall not be dynamically tagged unless
it is a controlling operand in a call on a dispatching operation.
In the declaration of a dispatching operation of
a tagged type, everywhere a subtype of the tagged type appears as a subtype
of the profile (see 6.1
), it shall statically
match the first subtype of the tagged type.
dispatching operation overrides an inherited subprogram, it shall be
subtype conformant with the inherited subprogram.
convention of an inherited dispatching operation is the convention of
the corresponding primitive operation of the parent or progenitor type.
The default convention of a dispatching operation that overrides an inherited
primitive operation is the convention of the inherited operation; if
the operation overrides multiple inherited operations, then they shall
all have the same convention. An explicitly declared dispatching operation
shall not be of convention Intrinsic.
for a controlling formal parameter of a dispatching operation shall be
If a dispatching operation is defined by a subprogram_renaming_declaration
or the instantiation of a generic subprogram, any access parameter of
the renamed subprogram or the generic subprogram that corresponds to
a controlling access parameter of the dispatching operation, shall have
a subtype that excludes null.
A given subprogram shall not be a dispatching operation
of two or more distinct tagged types.
The explicit declaration of a primitive subprogram
of a tagged type shall occur before the type is frozen (see 13.14
For example, new dispatching operations cannot be added after objects
or values of the type exist, nor after deriving a record extension from
it, nor after a body.
the execution of a call on a dispatching operation of a type T
the controlling tag value
determines which subprogram body is
executed. The controlling tag value is defined as follows:
- If one or more
controlling operands are statically tagged, then the controlling tag
value is statically determined to be the tag of T.
- If one or more controlling operands
are dynamically tagged, then the controlling tag value is not statically
determined, but is rather determined by the tags of the controlling operands.
If there is more than one dynamically
tagged controlling operand, a check is made that they all have the same
tag. If this check fails, Constraint_Error is raised
unless the call is a function_call
denotes the declaration of an equality operator (predefined or user defined)
that returns Boolean, in which case the result of the call is defined
to indicate inequality, and no subprogram_body
is executed. This check is performed prior to evaluating any tag-indeterminate
- If all
of the controlling operands (if any) are tag-indeterminate, then:
- If the call has a controlling
result or controlling access result and is itself, or designates, a (possibly
parenthesized or qualified) controlling operand of an enclosing call
on a dispatching operation of a descendant of type T, then its
controlling tag value is determined by the controlling tag value of this
- If the call has a controlling
result or controlling access result and (possibly parenthesized, qualified,
or dereferenced) is the expression of an assignment_statement
whose target is of a class-wide type, then its controlling tag value
is determined by the target;
the controlling tag value is statically determined to be the tag of type
For the execution
of a call on a dispatching operation, the action performed is determined
by the properties of the corresponding dispatching operation of the specific
type identified by the controlling tag value. If the corresponding operation
is explicitly declared for this type, even if the declaration occurs
in a private part, then the action comprises an invocation of the explicit
body for the operation. If the corresponding operation is implicitly
declared for this type:
- if the operation is implemented by
an entry or protected subprogram (see 9.1 and
9.4), then the action comprises a call on this
entry or protected subprogram, with the target object being given by
the first actual parameter of the call, and the actual parameters of
the entry or protected subprogram being given by the remaining actual
parameters of the call, if any;
- otherwise, the action is the same
as the action for the corresponding operation of the parent type.
72 The body to be executed for a call on
a dispatching operation is determined by the tag; it does not matter
whether that tag is determined statically or dynamically, and it does
not matter whether the subprogram's declaration is visible at the place
of the call.
73 This subclause covers calls on dispatching
subprograms of a tagged type. Rules for tagged type membership tests
are described in 4.5.2
. Controlling tag determination
for an assignment_statement
is described in 5.2
74 A dispatching call can dispatch to a
body whose declaration is not visible at the place of the call.
75 A call through an access-to-subprogram
value is never a dispatching call, even if the access value designates
a dispatching operation. Similarly a call whose prefix
denotes a subprogram_renaming_declaration
cannot be a dispatching call unless the renaming itself is the declaration
of a primitive subprogram.