Contents Index Search Previous Next
12.5.1 Formal Private and Derived Types
1
[The class determined for a formal private type
can be either limited or nonlimited, and either tagged or untagged; no
more specific class is known for such a type. The class determined for
a formal derived type is the derivation class rooted at the ancestor
type.]
Syntax
2
formal_private_type_definition
::= [[
abstract]
tagged] [
limited]
private
3
formal_derived_type_definition
::= [
abstract]
new subtype_mark [
with private]
Legality Rules
4
If a generic formal type declaration has a known_discriminant_part,
then it shall not include a default_expression
for a discriminant.
4.a
Ramification: Consequently,
a generic formal subtype with a known_discriminant_part
is an indefinite subtype, so the declaration of a stand-alone variable
has to provide a constraint on such a subtype, either explicitly, or
by its initial value.
5
{ancestor subtype (of a formal
derived type)} The
ancestor subtype
of a formal derived type is the subtype denoted by the
subtype_mark
of the
formal_derived_type_definition.
For a formal derived type declaration, the reserved words
with private
shall appear if and only if the ancestor type is a tagged type; in this
case the formal derived type is a private extension of the ancestor type
and the ancestor shall not be a class-wide type. [Similarly, the optional
reserved word
abstract shall appear only if the ancestor type
is a tagged type].
5.a
Reason: We use the term
``ancestor'' here instead of ``parent'' because the actual can be any
descendant of the ancestor, not necessarily a direct descendant.
6
If the formal subtype is definite, then the actual
subtype shall also be definite.
6.a
Ramification: On the
other hand, for an indefinite formal subtype, the actual can be either
definite or indefinite.
7
For a generic formal
derived type with no discriminant_part:
8
- If the ancestor subtype is constrained,
the actual subtype shall be constrained, and shall be statically compatible
with the ancestor;
8.a
Ramification: In other
words, any constraint on the ancestor subtype is considered part of the
``contract.''
9
- If the ancestor subtype is an unconstrained
access or composite subtype, the actual subtype shall be unconstrained.
9.a
Reason: This rule ensures
that if a composite constraint is allowed on the formal, one is also
allowed on the actual. If the ancestor subtype is an unconstrained scalar
subtype, the actual is allowed to be constrained, since a scalar constraint
does not cause further constraints to be illegal.
10
- If the ancestor subtype is an unconstrained
discriminated subtype, then the actual shall have the same number of
discriminants, and each discriminant of the actual shall correspond to
a discriminant of the ancestor, in the sense of 3.7.
10.a
Reason: This ensures
that if a discriminant constraint is given on the formal subtype, the
corresponding constraint in the instance will make sense, without additional
run-time checks. This is not necessary for arrays, since the bounds cannot
be overridden in a type extension. An unknown_discriminant_part
may be used to relax these matching requirements.
11
The declaration
of a formal derived type shall not have a known_discriminant_part.
For a generic formal private type with a known_discriminant_part:
12
- The actual type shall be a type with
the same number of discriminants.
13
- The actual subtype shall be unconstrained.
14
- The subtype of each discriminant of
the actual type shall statically match the subtype of the corresponding
discriminant of the formal type. {statically matching
(required) [partial]}
14.a
Reason: We considered
defining the first and third rule to be called ``subtype conformance''
for discriminant_parts. We rejected
that idea, because it would require implicit (inherited) discriminant_parts,
which seemed like too much mechanism.
15
[For a generic formal type with an unknown_discriminant_part,
the actual may, but need not, have discriminants, and may be definite
or indefinite.]
Static Semantics
16
The class determined
for a formal private type is as follows:
17
Type Definition Determined Class
limited private the class of all types
private the class of all nonlimited types
tagged limited private the class of all tagged types
tagged private the class of all nonlimited tagged types
18
[The presence of the reserved word abstract
determines whether the actual type may be abstract.]
19
A formal private or derived type is a private
or derived type, respectively. A formal derived tagged type is a private
extension. [A formal private or derived type is abstract if the reserved
word abstract appears in its declaration.]
20
If the ancestor type is a composite type that
is not an array type, the formal type inherits components from the ancestor
type (including discriminants if a new
discriminant_part
is not specified), as for a derived type defined by a
derived_type_definition
(see
3.4).
21/1
{
8652/0038}
For a formal derived type, the predefined operators and inherited user-defined
subprograms are determined by the ancestor type, and are implicitly declared
at the earliest place, if any, within the immediate scope of the formal
type, where the corresponding primitive subprogram of the ancestor is
visible (see
7.3.1). In an instance, the
copy of such an implicit declaration declares a view of the corresponding
primitive subprogram of the ancestor
of the formal derived type ,
even if this primitive has been overridden for the actual type.
When
the ancestor of the formal derived type is itself a formal type, the
copy of the implicit declaration declares a view of the corresponding
copied operation of the ancestor. [In the case of a formal private
extension, however, the tag of the formal type is that of the actual
type, so if the tag in a call is statically determined to be that of
the formal type, the body executed will be that corresponding to the
actual type.]
21.a
Ramification: The above
rule defining the properties of primitive subprograms in an instance
applies even if the subprogram has been overridden or hidden for the
actual type. This rule is necessary for untagged types, because their
primitive subprograms might have been overridden by operations that are
not subtype-conformant with the operations defined for the class. For
tagged types, the rule still applies, but the primitive subprograms will
dispatch to the appropriate implementation based on the type and tag
of the operands. Even for tagged types, the formal parameter names and
default_expressions are determined
by those of the primitive subprograms of the specified ancestor type.
22/1
For a prefix prefix
S that denotes a formal indefinite subtype, the following attribute is
defined:
23
- S'Definite
-
S'Definite yields True if the
actual subtype corresponding to S is definite; otherwise it yields False.
The value of this attribute is of the predefined type Boolean.
23.a
Discussion: Whether an
actual subtype is definite or indefinite may have a major effect on the
algorithm used in a generic. For example, in a generic I/O package, whether
to use fixed-length or variable-length records could depend on whether
the actual is definite or indefinite. This attribute is essentially a
replacement for the Constrained attribute which is now considered obsolete.
24
9 In
accordance with the general rule that the actual type shall belong to
the class determined for the formal (see 12.5,
``Formal Types''):
25
- If the formal
type is nonlimited, then so shall be the actual;
26
- For a formal
derived type, the actual shall be in the class rooted at the ancestor
subtype.
27
10 [The actual type can
be abstract only if the formal type is abstract (see 3.9.3).]
27.a
Reason: This is necessary
to avoid contract model problems, since one or more of its primitive
subprograms are abstract; it is forbidden to create objects of the type,
or to declare functions returning the type.
27.b
Ramification: On the
other hand, it is OK to pass a non-abstract actual to an abstract formal
-- abstract on the formal indicates that the actual might be abstract.
28
11 If the formal has a
discriminant_part, the actual can
be either definite or indefinite. Otherwise, the actual has to be definite.
Incompatibilities With Ada 83
28.a
{incompatibilities with Ada
83} Ada 83 does not have unknown_discriminant_parts,
so it allows indefinite subtypes to be passed to definite formals, and
applies a legality rule to the instance body. This is a contract model
violation. Ada 95 disallows such cases at the point of the instantiation.
The workaround is to add (<>) as the discriminant_part
of any formal subtype if it is intended to be used with indefinite actuals.
If that's the intent, then there can't be anything in the generic body
that would require a definite subtype.
28.b
The check for discriminant subtype
matching is changed from a run-time check to a compile-time check.
Contents Index Search Previous Next Legal