- The primitive subprograms of a tagged type 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
- A call on a dispatching operation is a call whose name or prefix denotes
the declaration of a primitive subprogram of a tagged type, that is, a
dispatching operation. A controlling operand in a call on a dispatching
operation of a tagged type T is one whose corresponding formal parameter is
of type T or is of an anonymous access type with designated type T; 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. If the call is to a (primitive) function with
result type T, then the call has a controlling result -- the context of the
call can control the dispatching.
- A name or expression of a tagged type is either statically tagged,
dynamically 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 names 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, it has at least one statically tagged controlling
- The name or expression is dynamically tagged if it is of a
class-wide type, or it is a call with a controlling 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, all of whose controlling operands (if any)
are tag indeterminate.
- A type_conversion is statically or dynamically tagged according to
whether the type determined by the subtype_mark is specific or class-wide,
respectively. For a controlling operand that is designated by an actual
parameter, the controlling operand is statically or dynamically tagged
according to whether the designated type of the actual parameter 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 expression shall not be of an access-to-class-wide type unless
it designates 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.
If the dispatching operation overrides an inherited subprogram, it shall be
subtype conformant with the inherited subprogram. A dispatching operation
shall not be of convention Intrinsic. If a dispatching operation overrides
the predefined equals operator, then it shall be of convention Ada (either
explicitly or by default -- see 6.3.1).
- The default_expression for a controlling formal parameter of a
dispatching operation shall be tag indeterminate. A controlling formal
parameter that is an access parameter shall not have a default_expression.
- 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.
- For 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
- 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 whose name 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 controlling operands.
- If all of the controlling operands are tag-indeterminate, then:
- If the call has a controlling result and is itself a
(possibly parenthesized or qualified) controlling operand
of an enclosing call on a dispatching operation of type T,
then its controlling tag value is determined by the
controlling tag value of this enclosing call;
- Otherwise, the controlling tag value is statically
determined to be the tag of type T.
- For the execution of a call on a dispatching operation, the body
executed is the one for the corresponding primitive subprogram of the
specific type identified by the controlling tag value. The body for an
explicitly declared dispatching operation is the corresponding explicit body
for the subprogram. The body for an implicitly declared dispatching
operation that is overridden is the body for the overriding subprogram, even
if the overriding occurs in a private part. The body for an inherited
dispatching operation that is not overridden is the body of the corresponding
subprogram of the parent or ancestor type.
(70) 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.
(71) This subclause covers calls on primitive 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.
(72) A dispatching call can dispatch to a body whose declaration is not
visible at the place of the call.
(73) 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.
-- Email comments, additions, corrections, gripes, kudos, etc. to:
Magnus Kempe -- Magnus.Kempe@di.epfl.ch
Page last generated: 95-03-12