Contents Index 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 prefixprefix
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 Previous Next Legal