Rationale for Ada 2012

John Barnes
Contents   Index   References   Search   Previous   Next 

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.

Contents   Index   References   Search   Previous   Next 
© 2011, 2012, 2013 John Barnes Informatics.
Sponsored in part by:
The Ada Resource Association:

    ARA
  AdaCore:


    AdaCore
and   Ada-Europe:

Ada-Europe