1
Tagged types and type extensions support object-oriented programming, based on inheritance with extension and run-time polymorphism via
dispatching operations.
Static Semantics2/2
A record type or private type that has the reserved word
taggedin its declaration is called a
taggedtype. In addition, an interface type is a tagged type, as is a task or protected type derived from an interface (see
3.9.4). When deriving from a tagged type, as for any derived type, additional primitive subprograms may be defined, and inherited primitive subprograms may be overridden.
The derived type is called an
extensionof its ancestor types, or simply a
type extension.
2.1/2
Every type extension is also a tagged type, and is a
record extensionor a
private extensionof some other tagged type, or a non-interface synchronized tagged type (see
3.9.4). A record extension is defined by a
derived_type_definitionwith a
record_extension_part(see
3.9.1), which may include the definition of additional components. A private extension, which is a partial view of a record extension or of a synchronized tagged type, can be declared in the visible part of a package (see
7.3) or in a generic formal part (see
12.5.1).
3
An object of a tagged type has an associated (run-time)
tagthat identifies the specific tagged type used to create the object originally. The tag of an operand of a class-wide tagged type
T'Class controls which subprogram body is to be executed when a primitive subprogram of type
Tis applied to the operand (see
3.9.2);
using a tag to control which body to execute is called
dispatching.
4/2
The tag of a specific tagged type identifies the
full_type_declarationof the type, and for a type extension, is sufficient to uniquely identify the type among all descendants of the same ancestor. If a declaration for a tagged type occurs within a
generic_package_declaration, then the corresponding type declarations in distinct instances of the generic package are associated with distinct tags. For a tagged type that is local to a generic package body and with all of its ancestors (if any) also local to the generic body, the language does not specify whether repeated instantiations of the generic body result in distinct tags.
5
The following language-defined library package exists:
6/2
packageAda.Tags
isPreelaborate(Tags);
Tag
is private;
Preelaborable_Initialization(Tag);
6.1/2
7/2
functionExpanded_Name(T : Tag)
returnString;
Wide_Expanded_Name(T : Tag)
returnWide_String;
Wide_Wide_Expanded_Name(T : Tag)
returnWide_Wide_String;
External_Tag(T : Tag)
returnString;
Internal_Tag(External : String)
returnTag;
7.1/2
functionDescendant_Tag(External : String; Ancestor : Tag)
returnTag;
Is_Descendant_At_Same_Level(Descendant, Ancestor : Tag)
Boolean;
7.2/2
functionParent_Tag (T : Tag)
returnTag;
7.3/2
typeTag_Array
is array(Positive
range<>)
ofTag;
7.4/2
functionInterface_Ancestor_Tags (T : Tag)
returnTag_Array;
8
9
private
... -- not specified by the language
end Ada.Tags;
9.1/2
No_Tag is the default initial value of type Tag.
10/2
The function Wide_Wide_Expanded_Name returns the full expanded name of the first subtype of the specific type identified by the tag, in upper case, starting with a root library unit. The result is implementation defined if the type is declared within an unnamed
block_statement.
10.1/2
The function Expanded_Name (respectively, Wide_Expanded_Name) returns the same sequence of graphic characters as that defined for Wide_Wide_Expanded_Name, if all the graphic characters are defined in Character (respectively, Wide_Character); otherwise, the sequence of characters is implementation defined, but no shorter than that returned by Wide_Wide_Expanded_Name for the same value of the argument.
11
The function External_Tag returns a string to be used in an external representation for the given tag. The call External_Tag(S'Tag) is equivalent to the
attribute_referenceS'External_Tag (see
13.3).
11.1/2
The string returned by the functions Expanded_Name, Wide_Expanded_Name, Wide_Wide_Expanded_Name, and External_Tag has lower bound 1.
12/2
The function Internal_Tag returns a tag that corresponds to the given external tag, or raises Tag_Error if the given string is not the external tag for any specific type of the partition. Tag_Error is also raised if the specific type identified is a library-level type whose tag has not yet been created (see
13.14).
12.1/2
The function Descendant_Tag returns the (internal) tag for the type that corresponds to the given external tag and is both a descendant of the type identified by the Ancestor tag and has the same accessibility level as the identified ancestor. Tag_Error is raised if External is not the external tag for such a type. Tag_Error is also raised if the specific type identified is a library-level type whose tag has not yet been created.
12.2/2
The function Is_Descendant_At_Same_Level returns True if the Descendant tag identifies a type that is both a descendant of the type identified by Ancestor and at the same accessibility level. If not, it returns False.
12.3/2
The function Parent_Tag returns the tag of the parent type of the type whose tag is T. If the type does not have a parent type (that is, it was not declared by a derived_type_declaration), then No_Tag is returned.
12.4/2
The function Interface_Ancestor_Tags returns an array containing the tag of each interface ancestor type of the type whose tag is T, other than T itself. The lower bound of the returned array is 1, and the order of the returned tags is unspecified. Each tag appears in the result exactly once. If the type whose tag is T has no interface ancestors, a null array is returned.
13
For every subtype S of a tagged type T (specific or class-wide), the following attributes are defined:
14
S'Class
S'Class denotes a subtype of the class-wide type (called
T'Class in this International Standard) for the class rooted at
T(or if S already denotes a class-wide subtype, then S'Class is the same as S).
15
S'Class is unconstrained. However, if S is constrained, then the values of S'Class are only those that when converted to the type
Tbelong to S.
16
S'Tag
S'Tag denotes the tag of the type
T(or if
Tis class-wide, the tag of the root type of the corresponding class). The value of this attribute is of type Tag.
17
Given a
prefixX that is of a class-wide tagged type (after any implicit dereference), the following attribute is defined:
18
X'Tag
X'Tag denotes the tag of X. The value of this attribute is of type Tag.
18.1/2
The following language-defined generic function exists:
18.2/2
genericT (<>)
is abstract tagged limited private;
Parameters (<>)
is limited private;
Constructor (Params :
not null accessParameters)
T
is abstract;
Ada.Tags.Generic_Dispatching_Constructor
(The_Tag : Tag;
Params :
not null accessParameters)
returnT'Class;
Preelaborate(Generic_Dispatching_Constructor);
Convention(Intrinsic, Generic_Dispatching_Constructor);
18.3/2
Tags.Generic_Dispatching_Constructor provides a mechanism to create an object of an appropriate type from just a tag value. The function Constructor is expected to create the object given a reference to an object of type Parameters.
Dynamic Semantics19
The tag associated with an object of a tagged type is determined as follows:
20
21
22
23
24/2
25
The tag is preserved by type conversion and by parameter passing. The tag of a value is the tag of the associated object (see
6.2).
25.1/2
Tag_Error is raised by a call of Descendant_Tag, Expanded_Name, External_Tag, Interface_Ancestor_Tag, Is_Descendant_At_Same_Level, or Parent_Tag if any tag passed is No_Tag.
25.2/2
An instance of Tags.Generic_Dispatching_Constructor raises Tag_Error if The_Tag does not represent a concrete descendant of T or if the innermost master (see
7.6.1) of this descendant is not also a master of the instance. Otherwise, it dispatches to the primitive function denoted by the formal Constructor for the type identified by The_Tag, passing Params, and returns the result. Any exception raised by the function is propagated.
Erroneous Execution25.3/2
If an internal tag provided to an instance of Tags.Generic_Dispatching_Constructor or to any subprogram declared in package Tags identifies either a type that is not library-level and whose tag has not been created (see
13.14), or a type that does not exist in the partition at the time of the call, then execution is erroneous.
Implementation Permissions26/2
The implementation of Internal_Tag and Descendant_Tag may raise Tag_Error if no specific type corresponding to the string External passed as a parameter exists in the partition at the time the function is called, or if there is no such type whose innermost master is a master of the point of the function call.
Implementation Advice26.1/2
Internal_Tag should return the tag of a type whose innermost master is the master of the point of the function call.
27
64 A type declared with the reserved word
taggedshould normally be declared in a
package_specification, so that new primitive subprograms can be declared for it.
28
65 Once an object has been created, its tag never changes.
29
66 Class-wide types are defined to have unknown discriminants (see
3.7). This means that objects of a class-wide type have to be explicitly initialized (whether created by an
object_declarationor an
allocator), and that
aggregates have to be explicitly qualified with a specific type when their expected type is class-wide.
30/2
This paragraph was deleted.
30.1/2
67 The capability provided by Tags.Generic_Dispatching_Constructor is sometimes known as a
factory.
Examples31
Examples of tagged record types:
32
type Point is tagged
record
X, Y : Real := 0.0;
end record;
33
type Expression is tagged null record;
-- Components will be added by each extension
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4