Rationale for Ada 2012
8.5 The holder container
As mentioned in the
Introduction, it is not possible to declare an object of an indefinite
type that can hold any value of that type since the object becomes constrained
by the mandatory initial value. Thus we can write
Pet: String := "dog";
We can assign "cat"
to Pet but we cannot assign "rabbit"
because it is too long.
This is overcome in
Ada 2012 by the introduction of the holder container which can hold a
single indefinite object. Its specification is
generic
type Element_Type(<>)
is private;
with function "=" (Left, Right: Element_Type)
return Boolean
is <>;
package Ada.Containers.Indefinite_Holders
is
pragma Preelaborate(Indefinite_Holders);
pragma Remote_Types(Indefinite_Holders);
type Holder is tagged private;
pragma Preelaborable_Initialization(Holder);
Empty_Holder: constant Holder;
function "=" (Left, Right: Holder) return Boolean;
function To_Holder(New_Item: Element_Type)
return Holder;
function Is_Empty(Container: Holder) return Boolean;
procedure Clear(Container: in out Holder);
function Element(Container: Holder) return Element_Type;
procedure Replace_Element(Container: in out Holder; New_Item: in Element_Type);
procedure Query_Element
(Container: in Holder;
Process: not null access procedure (Element: in Element_Type));
procedure Update_Element
(Container: in out Holder;
Process: not null access procedure (Element: in out Element_Type));
type Constant_Reference_Type
(Element: not null access constant Element_Type) is private
with Implicit_Dereference => Element;
type Reference_Type
(Element: not null access Element_Type) is private
with Implicit_Dereference => Element;
function Constant_Reference
(Container: aliased in Holder) return Constant_Reference_Type;
function Reference(Container: aliased in out Holder) return Reference_Type;
procedure Assign(Target: in out Holder; Source: in Holder);
function Copy(Source: Holder) return Holder;
procedure Move(Target: in out Holder; Source: in out Holder);
private
... -- not specified by the language
end Ada.Containers.Indefinite_Holders;
Hopefully, the purpose of the facilities provided
by this container are obvious given an understanding of the use of the
existing containers. It would be possible to use a list container with
just a single element to act as a holder but it seems better to have
an explicit container with probably less overhead and risk of confusion.
A trivial example of
its use might be to provide a holder for pets. We write
package Strings is
new Ada.Containers.Indefinite_Holders(String);
Kennel: Strings.Holder := To_Holder("cat");
This declares an object
Kennel which is a wrapper for a string and
initializes it with the string "cat".
We can replace the cat with a rabbit by writing
Kennel := To_Holder("rabbit");
However, using To_Holder
in this way could be a bit slow since this will create a new object which
has to be destroyed after the assignment. It is better to write
Replace_Element(Kennel, "rabbit");
If we want to print
out the contents of the kennel we just write
Put(Element(Kennel));
Operations such as Update_Element
are provided partly for uniformity but also because the object might
be large so that it is better to update it in situ. Alternatively,
we can use the functions such as Reference
as explained earlier.
© 2011, 2012, 2013 John Barnes Informatics.
Sponsored in part by: