A.18.18 The Generic Package Containers.Indefinite_Holders
The language-defined generic package Containers.Indefinite_Holders 
provides a private type Holder and a set of operations for that type. 
A holder container holds a single element of an indefinite type.
A holder container allows the declaration of an object 
that can be used like an uninitialized variable or component of an indefinite 
type.
A holder container may be 
empty. An empty 
holder does not contain an element.
  
Static Semantics
The generic library 
package Containers.Indefinite_Holders has the following declaration: 
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;
 The actual function for the generic formal function 
"=" on Element_Type values is expected to define a reflexive 
and symmetric relationship and return the same result value each time 
it is called with a particular pair of values. If it behaves in some 
other manner, the function "=" on holder values returns an 
unspecified value. The exact arguments and number of calls of this generic 
formal function by the function "=" on holder values are unspecified.
 The type Holder is used to represent holder containers. 
The type Holder needs finalization
 (see 
7.6).
 
 Empty_Holder represents an empty holder object. 
If an object of type Holder is not otherwise initialized, it is initialized 
to the same value as Empty_Holder.
 Some operations of this generic package have access-to-subprogram 
parameters. To ensure such operations are well-defined, they guard against 
certain actions by the designated subprogram. In particular, some operations 
check for “tampering with the element” of a container because 
they depend on the element of the container not being replaced.
 A 
subprogram is said to 
tamper with the element of a holder object 
H if:
 
It clears the element contained by H, that 
is, it calls the Clear procedure with H as a parameter;
It replaces the element contained by H, 
that is, it calls the Replace_Element procedure with H as a parameter;
It calls the Move procedure with H as a 
parameter;
It finalizes H.
 When tampering 
with the element is 
prohibited for a particular holder object 
H, Program_Error is propagated by a call of any language-defined 
subprogram that is defined to tamper with the element of 
H, leaving 
H unmodified. These checks are made before any other defined behavior 
of the body of the language-defined subprogram.
 
function "=" (Left, Right : Holder) return Boolean;
If Left and Right 
denote the same holder object, then the function returns True. Otherwise, 
it compares the element contained in Left to the element contained in 
Right using the generic formal equality operator, returning the result 
of that operation. Any exception raised during the evaluation of element 
equality is propagated.
function To_Holder (New_Item : Element_Type) return Holder;
Returns a nonempty 
holder containing an element initialized to New_Item. To_Holder performs 
indefinite insertion (see 
A.18).
 
function Is_Empty (Container : Holder) return Boolean;
Returns True if 
Container is empty, and False if it contains an element.
procedure Clear (Container : in out Holder);
Removes the element 
from Container. Container is empty after a successful Clear operation.
function Element (Container : Holder) return Element_Type;
If Container is 
empty, Constraint_Error is propagated. Otherwise, returns the element 
stored in Container.
procedure Replace_Element (Container : in out Holder;
                           New_Item  : in     Element_Type);
Replace_Element 
assigns the value New_Item into Container, replacing any preexisting 
content of Container; Replace_Element performs indefinite insertion (see 
A.18). Container is not empty after a successful 
call to Replace_Element.
 
procedure Query_Element
  (Container : in Holder;
   Process   : not null access procedure (Element : in Element_Type));
If Container is 
empty, Constraint_Error is propagated. Otherwise, Query_Element calls 
Process.all with the contained element as the argument. Tampering 
with the element of Container is prohibited during the execution of the 
call on Process.all. Any exception raised by Process.all 
is propagated.
procedure Update_Element
  (Container : in out Holder;
   Process   : not null access procedure (Element : in out Element_Type));
If Container is 
empty, Constraint_Error is propagated. Otherwise, Update_Element calls 
Process.all with the contained element as the argument. Tampering 
with the element of Container is prohibited during the execution of the 
call on Process.all. Any exception raised by Process.all 
is propagated.
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;
The types Constant_Reference_Type 
and Reference_Type need finalization.
 
The default initialization of an object of type 
Constant_Reference_Type or Reference_Type propagates Program_Error.
function Constant_Reference (Container : aliased in Holder)
   return Constant_Reference_Type;
This function (combined 
with the Implicit_Dereference aspect) provides a convenient way to gain 
read access to the contained element of a holder container.
If Container is empty, Constraint_Error is propagated. 
Otherwise, Constant_Reference returns an object whose discriminant is 
an access value that designates the contained element. Tampering with 
the elements of Container is prohibited while the object returned by 
Constant_Reference exists and has not been finalized.
function Reference (Container : aliased in out Holder)
   return Reference_Type;
This function (combined 
with the Implicit_Dereference aspects) provides a convenient way to gain 
read and write access to the contained element of a holder container.
If Container is empty, Constraint_Error is propagated. 
Otherwise, Reference returns an object whose discriminant is an access 
value that designates the contained element. Tampering with the elements 
of Container is prohibited while the object returned by Reference exists 
and has not been finalized. 
procedure Assign (Target : in out Holder; Source : in Holder);
If Target denotes 
the same object as Source, the operation has no effect. If Source is 
empty, Clear (Target) is called. Otherwise, Replace_Element (Target, 
Element (Source)) is called. 
function Copy (Source : Holder) return Holder;
If Source is empty, 
returns an empty holder container; otherwise, returns To_Holder (Element 
(Source)).
procedure Move (Target : in out Holder; Source : in out Holder);
If Target denotes 
the same object as Source, then the operation has no effect. Otherwise, 
the element contained by Source (if any) is removed from Source and inserted 
into Target, replacing any preexisting content. Source is empty after 
a successful call to Move.
Bounded (Run-Time) Errors
 It is a bounded error for the 
actual function associated with a generic formal subprogram, when called 
as part of an operation of this package, to tamper with the element of 
any Holder parameter of the operation. Either Program_Error is raised, 
or the operation works as defined on the value of the Holder either prior 
to, or subsequent to, some or all of the modifications to the Holder.
 
 It is a bounded error to call 
any subprogram declared in the visible part of Containers.Indefinite_Holders 
when the associated container has been finalized. If the operation takes 
Container as an 
in out parameter, then it raises Constraint_Error 
or Program_Error. Otherwise, the operation either proceeds as it would 
for an empty container, or it raises Constraint_Error or Program_Error. 
 
Erroneous Execution
 Execution is erroneous if the holder container associated 
with the result of a call to Reference or Constant_Reference is finalized 
before the result object returned by the call to Reference or Constant_Reference 
is finalized.
 
Implementation Requirements
 No storage associated with a holder object shall 
be lost upon assignment or scope exit.
 The execution of an 
assignment_statement 
for a holder container shall have the effect of copying the element (if 
any) from the source holder object to the target holder object.
 
Implementation Advice
 Move should not copy the element, and should minimize 
copying of internal data structures. 
 If an exception is propagated from a holder operation, 
no storage should be lost, nor should the element be removed from a holder 
container unless specified by the operation. 
Ada 2005 and 2012 Editions sponsored in part by Ada-Europe