Contents Index Search Previous Next
3.7 Discriminants
1
A
composite type (other than an array type) can have discriminants, which
parameterize the type. A
known_discriminant_part
specifies the discriminants of a composite type. A discriminant of an
object is a component of the object, and is either of a discrete type
or an access type. An
unknown_discriminant_part
in the declaration of a partial view of a type specifies that the discriminants
of the type are unknown for the given view; all subtypes of such a partial
view are indefinite subtypes.
Syntax
2
discriminant_part
::= unknown_discriminant_part |
known_discriminant_part
3
unknown_discriminant_part
::= (<>)
4
known_discriminant_part
::=
(
discriminant_specification {;
discriminant_specification})
5
discriminant_specification
::=
defining_identifier_list :
subtype_mark [:=
default_expression]
|
defining_identifier_list :
access_definition [:=
default_expression]
6
default_expression
::= expression
Name Resolution Rules
7
The expected type for the
default_expression of a
discriminant_specification
is that of the corresponding discriminant.
Legality Rules
8/1
A
discriminant_part
is only permitted in a declaration for a composite type that is not an
array type (this includes generic formal types). A type declared with
a
known_discriminant_part is called
a
discriminated type,
as is a type that inherits
(known) discriminants.
9
The subtype of a discriminant may be defined by
a
subtype_mark, in which case the
subtype_mark shall denote a discrete
or access subtype, or it may be defined by an
access_definition
(in which case the
subtype_mark
of the
access_definition may denote
any kind of subtype).
A discriminant that is defined
by an
access_definition is called
an
access discriminant and is of an anonymous general access-to-variable
type whose designated subtype is denoted by the
subtype_mark
of the
access_definition.
10
A
discriminant_specification
for an access discriminant shall appear only in the declaration for a
task or protected type, or for a type with the reserved word
limited
in its (full) definition or in that of one of its ancestors. In addition
to the places where Legality Rules normally apply (see
12.3),
this rule applies also in the private part of an instance of a generic
unit.
11
Default_expressions
shall be provided either for all or for none of the discriminants of
a known_discriminant_part. No default_expressions
are permitted in a known_discriminant_part
in a declaration of a tagged type or a generic formal type.
12
For a type defined
by a derived_type_definition, if
a known_discriminant_part is provided
in its declaration, then:
13
- The parent subtype shall be constrained;
14
- If the parent type is not a tagged
type, then each discriminant of the derived type shall be used in the
constraint defining the parent subtype;
15
- If a discriminant is used in the constraint
defining the parent subtype, the subtype of the discriminant shall be
statically compatible (see 4.9.1) with the
subtype of the corresponding parent discriminant.
16
The type of the
default_expression,
if any, for an access discriminant shall be convertible to the anonymous
access type of the discriminant (see
4.6).
Static Semantics
17
A discriminant_specification
declares a discriminant; the subtype_mark
denotes its subtype unless it is an access discriminant, in which case
the discriminant's subtype is the anonymous access-to-variable subtype
defined by the access_definition.
18
For a type defined by a
derived_type_definition,
each discriminant of the parent type is either inherited, constrained
to equal some new discriminant of the derived type, or constrained to
the value of an expression.
When inherited or constrained
to equal some new discriminant, the parent discriminant and the discriminant
of the derived type are said to
correspond. Two discriminants
also correspond if there is some common discriminant to which they both
correspond. A discriminant corresponds to itself as well.
If
a discriminant of a parent type is constrained to a specific value by
a
derived_type_definition, then
that discriminant is said to be
specified by that
derived_type_definition.
19
A
constraint
that appears within the definition of a discriminated type
depends
on a discriminant of the type if it names the discriminant as a bound
or discriminant value. A
component_definition
depends on a discriminant if its
constraint
depends on the discriminant, or on a discriminant that corresponds to
it.
20
A
component
depends on a discriminant if:
21
- Its component_definition
depends on the discriminant; or
22
- It is declared in a variant_part
that is governed by the discriminant; or
23
- It is a component inherited as part
of a derived_type_definition, and
the constraint of the parent_subtype_indication
depends on the discriminant; or
24
- It is a subcomponent of a component
that depends on the discriminant.
25
Each value of a discriminated type includes a
value for each component of the type that does not depend on a discriminant;
this includes the discriminants themselves. The values of discriminants
determine which other component values are present in the value of the
discriminated type.
26
A
type declared with a
known_discriminant_part
is said to have
known discriminants; its first subtype is unconstrained.
A type declared with an
unknown_discriminant_part
is said to have
unknown discriminants. A type declared without
a
discriminant_part has no discriminants,
unless it is a derived type; if derived, such a type has the same sort
of discriminants (known, unknown, or none) as its parent (or ancestor)
type. A tagged class-wide type also has unknown discriminants.
Any
subtype of a type with unknown discriminants is an unconstrained and
indefinite subtype (see
3.2 and
3.3).
Dynamic Semantics
27
An
access_definition
is elaborated when the value of a corresponding access discriminant is
defined, either by evaluation of its
default_expression
or by elaboration of a
discriminant_constraint.
The elaboration of an
access_definition
creates the anonymous access type. When the expression defining the access
discriminant is evaluated, it is converted to this anonymous access type
(see
4.6).
28
50 If a discriminated type
has default_expressions for its
discriminants, then unconstrained variables of the type are permitted,
and the values of the discriminants can be changed by an assignment to
such a variable. If defaults are not provided for the discriminants,
then all variables of the type are constrained, either by explicit constraint
or by their initial value; the values of the discriminants of such a
variable cannot be changed after initialization.
29
51 The default_expression
for a discriminant of a type is evaluated when an object of an unconstrained
subtype of the type is created.
30
52 Assignment to a discriminant
of an object (after its initialization) is not allowed, since the name
of a discriminant is a constant; neither assignment_statements
nor assignments inherent in passing as an in out or out
parameter are allowed. Note however that the value of a discriminant
can be changed by assigning to the enclosing object, presuming it is
an unconstrained variable.
31
53 A discriminant that
is of a named access type is not called an access discriminant; that
term is used only for discriminants defined by an access_definition.
Examples
32
Examples of
discriminated types:
33
type Buffer(Size : Buffer_Size := 100) is -- see 3.5.4
record
Pos : Buffer_Size := 0;
Value : String(1 .. Size);
end record;
34
type Matrix_Rec(Rows, Columns : Integer) is
record
Mat : Matrix(1 .. Rows, 1 .. Columns); -- see 3.6
end record;
35
type Square(Side : Integer) is new
Matrix_Rec(Rows => Side, Columns => Side);
36
type Double_Square(Number : Integer) is
record
Left : Square(Number);
Right : Square(Number);
end record;
37
type Item(Number : Positive) is
record
Content : Integer;
-- no component depends on the discriminant
end record;
Contents Index Search Previous Next Legal