Contents Index Search Related Documents Previous Next
3.7 Discriminants
1/2
A
composite type (other than an array or interface 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 view of a type specifies that the discriminants
of the type are unknown for the given view; all subtypes of such a view
are indefinite subtypes.
Syntax
2/2
discriminant_part
::= unknown_discriminant_part |
known_discriminant_part
3
unknown_discriminant_part
::= (<>)
4
known_discriminant_part
::=
(
discriminant_specification {;
discriminant_specification})
5/2
discriminant_specification
::=
defining_identifier_list : [
null_exclusion]
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/2
A
discriminant_part
is only permitted in a declaration for a composite type that is not an
array or interface 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/2
The subtype of a discriminant may be defined
by an optional
null_exclusion and
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.
A discriminant that is defined by an
access_definition
is called an
access discriminant and is of an anonymous access
type.
9.1/2
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.
10/2
A
discriminant_specification
for an access discriminant may have a
default_expression
only in the declaration for a task or protected type, or for a type that
is a descendant of an explicitly limited record type. 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/2
This paragraph was deleted.
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/2
For an access discriminant, its
access_definition
is elaborated when the value of the access discriminant is defined: by
evaluation of its
default_expression,
by elaboration of a
discriminant_constraint,
or by an assignment that initializes the enclosing object.
28
52 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
53 The default_expression
for a discriminant of a type is evaluated when an object of an unconstrained
subtype of the type is created.
30
54 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
55 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/2
task type Worker(Prio : System.Priority; Buf : access Buffer) is
-- discriminants used to parameterize the task type (see 9.1)
pragma Priority(Prio); -- see D.1
entry Fill;
entry Drain;
end Worker;
Contents Index Search Related Documents Previous Next Legal