File : a-cohase.ads


   1 ------------------------------------------------------------------------------
   2 --                                                                          --
   3 --                         GNAT LIBRARY COMPONENTS                          --
   4 --                                                                          --
   5 --           A D A . C O N T A I N E R S . H A S H E D _ S E T S            --
   6 --                                                                          --
   7 --                                 S p e c                                  --
   8 --                                                                          --
   9 --          Copyright (C) 2004-2015, Free Software Foundation, Inc.         --
  10 --                                                                          --
  11 -- This specification is derived from the Ada Reference Manual for use with --
  12 -- GNAT. The copyright notice above, and the license provisions that follow --
  13 -- apply solely to the  contents of the part following the private keyword. --
  14 --                                                                          --
  15 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  16 -- terms of the  GNU General Public License as published  by the Free Soft- --
  17 -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
  18 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  19 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  20 -- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
  21 --                                                                          --
  22 --                                                                          --
  23 --                                                                          --
  24 --                                                                          --
  25 --                                                                          --
  26 -- You should have received a copy of the GNU General Public License and    --
  27 -- a copy of the GCC Runtime Library Exception along with this program;     --
  28 -- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
  29 -- <http://www.gnu.org/licenses/>.                                          --
  30 --                                                                          --
  31 -- This unit was originally developed by Matthew J Heaney.                  --
  32 ------------------------------------------------------------------------------
  33 
  34 with Ada.Iterator_Interfaces;
  35 
  36 private with Ada.Containers.Hash_Tables;
  37 with Ada.Containers.Helpers;
  38 private with Ada.Finalization;
  39 private with Ada.Streams;
  40 
  41 generic
  42    type Element_Type is private;
  43 
  44    with function Hash (Element : Element_Type) return Hash_Type;
  45 
  46    with function Equivalent_Elements
  47           (Left, Right : Element_Type) return Boolean;
  48 
  49    with function "=" (Left, Right : Element_Type) return Boolean is <>;
  50 
  51 package Ada.Containers.Hashed_Sets is
  52    pragma Annotate (CodePeer, Skip_Analysis);
  53    pragma Preelaborate;
  54    pragma Remote_Types;
  55 
  56    type Set is tagged private
  57    with
  58       Constant_Indexing => Constant_Reference,
  59       Default_Iterator  => Iterate,
  60       Iterator_Element  => Element_Type;
  61 
  62    pragma Preelaborable_Initialization (Set);
  63 
  64    type Cursor is private;
  65    pragma Preelaborable_Initialization (Cursor);
  66 
  67    Empty_Set : constant Set;
  68    --  Set objects declared without an initialization expression are
  69    --  initialized to the value Empty_Set.
  70 
  71    No_Element : constant Cursor;
  72    --  Cursor objects declared without an initialization expression are
  73    --  initialized to the value No_Element.
  74 
  75    function Has_Element (Position : Cursor) return Boolean;
  76    --  Equivalent to Position /= No_Element
  77 
  78    package Set_Iterator_Interfaces is new
  79      Ada.Iterator_Interfaces (Cursor, Has_Element);
  80 
  81    function "=" (Left, Right : Set) return Boolean;
  82    --  For each element in Left, set equality attempts to find the equal
  83    --  element in Right; if a search fails, then set equality immediately
  84    --  returns False. The search works by calling Hash to find the bucket in
  85    --  the Right set that corresponds to the Left element. If the bucket is
  86    --  non-empty, the search calls the generic formal element equality operator
  87    --  to compare the element (in Left) to the element of each node in the
  88    --  bucket (in Right); the search terminates when a matching node in the
  89    --  bucket is found, or the nodes in the bucket are exhausted. (Note that
  90    --  element equality is called here, not Equivalent_Elements. Set equality
  91    --  is the only operation in which element equality is used. Compare set
  92    --  equality to Equivalent_Sets, which does call Equivalent_Elements.)
  93 
  94    function Equivalent_Sets (Left, Right : Set) return Boolean;
  95    --  Similar to set equality, with the difference that the element in Left is
  96    --  compared to the elements in Right using the generic formal
  97    --  Equivalent_Elements operation instead of element equality.
  98 
  99    function To_Set (New_Item : Element_Type) return Set;
 100    --  Constructs a singleton set comprising New_Element. To_Set calls Hash to
 101    --  determine the bucket for New_Item.
 102 
 103    function Capacity (Container : Set) return Count_Type;
 104    --  Returns the current capacity of the set. Capacity is the maximum length
 105    --  before which rehashing in guaranteed not to occur.
 106 
 107    procedure Reserve_Capacity (Container : in out Set; Capacity : Count_Type);
 108    --  Adjusts the current capacity, by allocating a new buckets array. If the
 109    --  requested capacity is less than the current capacity, then the capacity
 110    --  is contracted (to a value not less than the current length). If the
 111    --  requested capacity is greater than the current capacity, then the
 112    --  capacity is expanded (to a value not less than what is requested). In
 113    --  either case, the nodes are rehashed from the old buckets array onto the
 114    --  new buckets array (Hash is called once for each existing element in
 115    --  order to compute the new index), and then the old buckets array is
 116    --  deallocated.
 117 
 118    function Length (Container : Set) return Count_Type;
 119    --  Returns the number of items in the set
 120 
 121    function Is_Empty (Container : Set) return Boolean;
 122    --  Equivalent to Length (Container) = 0
 123 
 124    procedure Clear (Container : in out Set);
 125    --  Removes all of the items from the set
 126 
 127    function Element (Position : Cursor) return Element_Type;
 128    --  Returns the element of the node designated by the cursor
 129 
 130    procedure Replace_Element
 131      (Container : in out Set;
 132       Position  : Cursor;
 133       New_Item  : Element_Type);
 134    --  If New_Item is equivalent (as determined by calling Equivalent_Elements)
 135    --  to the element of the node designated by Position, then New_Element is
 136    --  assigned to that element. Otherwise, it calls Hash to determine the
 137    --  bucket for New_Item. If the bucket is not empty, then it calls
 138    --  Equivalent_Elements for each node in that bucket to determine whether
 139    --  New_Item is equivalent to an element in that bucket. If
 140    --  Equivalent_Elements returns True then Program_Error is raised (because
 141    --  an element may appear only once in the set); otherwise, New_Item is
 142    --  assigned to the node designated by Position, and the node is moved to
 143    --  its new bucket.
 144 
 145    procedure Query_Element
 146      (Position : Cursor;
 147       Process  : not null access procedure (Element : Element_Type));
 148    --  Calls Process with the element (having only a constant view) of the node
 149    --  designed by the cursor.
 150 
 151    type Constant_Reference_Type
 152      (Element : not null access constant Element_Type) is private
 153         with Implicit_Dereference => Element;
 154 
 155    function Constant_Reference
 156      (Container : aliased Set;
 157       Position  : Cursor) return Constant_Reference_Type;
 158    pragma Inline (Constant_Reference);
 159 
 160    procedure Assign (Target : in out Set; Source : Set);
 161 
 162    function Copy (Source : Set; Capacity : Count_Type := 0) return Set;
 163 
 164    procedure Move (Target : in out Set; Source : in out Set);
 165    --  Clears Target (if it's not empty), and then moves (not copies) the
 166    --  buckets array and nodes from Source to Target.
 167 
 168    procedure Insert
 169      (Container : in out Set;
 170       New_Item  : Element_Type;
 171       Position  : out Cursor;
 172       Inserted  : out Boolean);
 173    --  Conditionally inserts New_Item into the set. If New_Item is already in
 174    --  the set, then Inserted returns False and Position designates the node
 175    --  containing the existing element (which is not modified). If New_Item is
 176    --  not already in the set, then Inserted returns True and Position
 177    --  designates the newly-inserted node containing New_Item. The search for
 178    --  an existing element works as follows. Hash is called to determine
 179    --  New_Item's bucket; if the bucket is non-empty, then Equivalent_Elements
 180    --  is called to compare New_Item to the element of each node in that
 181    --  bucket. If the bucket is empty, or there were no equivalent elements in
 182    --  the bucket, the search "fails" and the New_Item is inserted in the set
 183    --  (and Inserted returns True); otherwise, the search "succeeds" (and
 184    --  Inserted returns False).
 185 
 186    procedure Insert  (Container : in out Set; New_Item : Element_Type);
 187    --  Attempts to insert New_Item into the set, performing the usual insertion
 188    --  search (which involves calling both Hash and Equivalent_Elements); if
 189    --  the search succeeds (New_Item is equivalent to an element already in the
 190    --  set, and so was not inserted), then this operation raises
 191    --  Constraint_Error. (This version of Insert is similar to Replace, but
 192    --  having the opposite exception behavior. It is intended for use when you
 193    --  want to assert that the item is not already in the set.)
 194 
 195    procedure Include (Container : in out Set; New_Item : Element_Type);
 196    --  Attempts to insert New_Item into the set. If an element equivalent to
 197    --  New_Item is already in the set (the insertion search succeeded, and
 198    --  hence New_Item was not inserted), then the value of New_Item is assigned
 199    --  to the existing element. (This insertion operation only raises an
 200    --  exception if cursor tampering occurs. It is intended for use when you
 201    --  want to insert the item in the set, and you don't care whether an
 202    --  equivalent element is already present.)
 203 
 204    procedure Replace (Container : in out Set; New_Item : Element_Type);
 205    --  Searches for New_Item in the set; if the search fails (because an
 206    --  equivalent element was not in the set), then it raises
 207    --  Constraint_Error. Otherwise, the existing element is assigned the value
 208    --  New_Item. (This is similar to Insert, but with the opposite exception
 209    --  behavior. It is intended for use when you want to assert that the item
 210    --  is already in the set.)
 211 
 212    procedure Exclude (Container : in out Set; Item : Element_Type);
 213    --  Searches for Item in the set, and if found, removes its node from the
 214    --  set and then deallocates it. The search works as follows. The operation
 215    --  calls Hash to determine the item's bucket; if the bucket is not empty,
 216    --  it calls Equivalent_Elements to compare Item to the element of each node
 217    --  in the bucket. (This is the deletion analog of Include. It is intended
 218    --  for use when you want to remove the item from the set, but don't care
 219    --  whether the item is already in the set.)
 220 
 221    procedure Delete  (Container : in out Set; Item : Element_Type);
 222    --  Searches for Item in the set (which involves calling both Hash and
 223    --  Equivalent_Elements). If the search fails, then the operation raises
 224    --  Constraint_Error. Otherwise it removes the node from the set and then
 225    --  deallocates it. (This is the deletion analog of non-conditional
 226    --  Insert. It is intended for use when you want to assert that the item is
 227    --  already in the set.)
 228 
 229    procedure Delete (Container : in out Set; Position : in out Cursor);
 230    --  Removes the node designated by Position from the set, and then
 231    --  deallocates the node. The operation calls Hash to determine the bucket,
 232    --  and then compares Position to each node in the bucket until there's a
 233    --  match (it does not call Equivalent_Elements).
 234 
 235    procedure Union (Target : in out Set; Source : Set);
 236    --  The operation first calls Reserve_Capacity if the current capacity is
 237    --  less than the sum of the lengths of Source and Target. It then iterates
 238    --  over the Source set, and conditionally inserts each element into Target.
 239 
 240    function Union (Left, Right : Set) return Set;
 241    --  The operation first copies the Left set to the result, and then iterates
 242    --  over the Right set to conditionally insert each element into the result.
 243 
 244    function "or" (Left, Right : Set) return Set renames Union;
 245 
 246    procedure Intersection (Target : in out Set; Source : Set);
 247    --  Iterates over the Target set (calling First and Next), calling Find to
 248    --  determine whether the element is in Source. If an equivalent element is
 249    --  not found in Source, the element is deleted from Target.
 250 
 251    function Intersection (Left, Right : Set) return Set;
 252    --  Iterates over the Left set, calling Find to determine whether the
 253    --  element is in Right. If an equivalent element is found, it is inserted
 254    --  into the result set.
 255 
 256    function "and" (Left, Right : Set) return Set renames Intersection;
 257 
 258    procedure Difference (Target : in out Set; Source : Set);
 259    --  Iterates over the Source (calling First and Next), calling Find to
 260    --  determine whether the element is in Target. If an equivalent element is
 261    --  found, it is deleted from Target.
 262 
 263    function Difference (Left, Right : Set) return Set;
 264    --  Iterates over the Left set, calling Find to determine whether the
 265    --  element is in the Right set. If an equivalent element is not found, the
 266    --  element is inserted into the result set.
 267 
 268    function "-" (Left, Right : Set) return Set renames Difference;
 269 
 270    procedure Symmetric_Difference (Target : in out Set; Source : Set);
 271    --  The operation first calls Reserve_Capacity if the current capacity is
 272    --  less than the sum of the lengths of Source and Target. It then iterates
 273    --  over the Source set, searching for the element in Target (calling Hash
 274    --  and Equivalent_Elements). If an equivalent element is found, it is
 275    --  removed from Target; otherwise it is inserted into Target.
 276 
 277    function Symmetric_Difference (Left, Right : Set) return Set;
 278    --  The operation first iterates over the Left set. It calls Find to
 279    --  determine whether the element is in the Right set. If no equivalent
 280    --  element is found, the element from Left is inserted into the result. The
 281    --  operation then iterates over the Right set, to determine whether the
 282    --  element is in the Left set. If no equivalent element is found, the Right
 283    --  element is inserted into the result.
 284 
 285    function "xor" (Left, Right : Set) return Set
 286      renames Symmetric_Difference;
 287 
 288    function Overlap (Left, Right : Set) return Boolean;
 289    --  Iterates over the Left set (calling First and Next), calling Find to
 290    --  determine whether the element is in the Right set. If an equivalent
 291    --  element is found, the operation immediately returns True. The operation
 292    --  returns False if the iteration over Left terminates without finding any
 293    --  equivalent element in Right.
 294 
 295    function Is_Subset (Subset : Set; Of_Set : Set) return Boolean;
 296    --  Iterates over Subset (calling First and Next), calling Find to determine
 297    --  whether the element is in Of_Set. If no equivalent element is found in
 298    --  Of_Set, the operation immediately returns False. The operation returns
 299    --  True if the iteration over Subset terminates without finding an element
 300    --  not in Of_Set (that is, every element in Subset is equivalent to an
 301    --  element in Of_Set).
 302 
 303    function First (Container : Set) return Cursor;
 304    --  Returns a cursor that designates the first non-empty bucket, by
 305    --  searching from the beginning of the buckets array.
 306 
 307    function Next (Position : Cursor) return Cursor;
 308    --  Returns a cursor that designates the node that follows the current one
 309    --  designated by Position. If Position designates the last node in its
 310    --  bucket, the operation calls Hash to compute the index of this bucket,
 311    --  and searches the buckets array for the first non-empty bucket, starting
 312    --  from that index; otherwise, it simply follows the link to the next node
 313    --  in the same bucket.
 314 
 315    procedure Next (Position : in out Cursor);
 316    --  Equivalent to Position := Next (Position)
 317 
 318    function Find
 319      (Container : Set;
 320       Item      : Element_Type) return Cursor;
 321    --  Searches for Item in the set. Find calls Hash to determine the item's
 322    --  bucket; if the bucket is not empty, it calls Equivalent_Elements to
 323    --  compare Item to each element in the bucket. If the search succeeds, Find
 324    --  returns a cursor designating the node containing the equivalent element;
 325    --  otherwise, it returns No_Element.
 326 
 327    function Contains (Container : Set; Item : Element_Type) return Boolean;
 328    --  Equivalent to Find (Container, Item) /= No_Element
 329 
 330    function Equivalent_Elements (Left, Right : Cursor) return Boolean;
 331    --  Returns the result of calling Equivalent_Elements with the elements of
 332    --  the nodes designated by cursors Left and Right.
 333 
 334    function Equivalent_Elements
 335      (Left  : Cursor;
 336       Right : Element_Type) return Boolean;
 337    --  Returns the result of calling Equivalent_Elements with element of the
 338    --  node designated by Left and element Right.
 339 
 340    function Equivalent_Elements
 341      (Left  : Element_Type;
 342       Right : Cursor) return Boolean;
 343    --  Returns the result of calling Equivalent_Elements with element Left and
 344    --  the element of the node designated by Right.
 345 
 346    procedure Iterate
 347      (Container : Set;
 348       Process   : not null access procedure (Position : Cursor));
 349    --  Calls Process for each node in the set
 350 
 351    function Iterate
 352      (Container : Set) return Set_Iterator_Interfaces.Forward_Iterator'Class;
 353 
 354    generic
 355       type Key_Type (<>) is private;
 356 
 357       with function Key (Element : Element_Type) return Key_Type;
 358 
 359       with function Hash (Key : Key_Type) return Hash_Type;
 360 
 361       with function Equivalent_Keys (Left, Right : Key_Type) return Boolean;
 362 
 363    package Generic_Keys is
 364 
 365       function Key (Position : Cursor) return Key_Type;
 366       --  Applies generic formal operation Key to the element of the node
 367       --  designated by Position.
 368 
 369       function Element (Container : Set; Key : Key_Type) return Element_Type;
 370       --  Searches (as per the key-based Find) for the node containing Key, and
 371       --  returns the associated element.
 372 
 373       procedure Replace
 374         (Container : in out Set;
 375          Key       : Key_Type;
 376          New_Item  : Element_Type);
 377       --  Searches (as per the key-based Find) for the node containing Key, and
 378       --  then replaces the element of that node (as per the element-based
 379       --  Replace_Element).
 380 
 381       procedure Exclude (Container : in out Set; Key : Key_Type);
 382       --  Searches for Key in the set, and if found, removes its node from the
 383       --  set and then deallocates it. The search works by first calling Hash
 384       --  (on Key) to determine the bucket; if the bucket is not empty, it
 385       --  calls Equivalent_Keys to compare parameter Key to the value of
 386       --  generic formal operation Key applied to element of each node in the
 387       --  bucket.
 388 
 389       procedure Delete (Container : in out Set; Key : Key_Type);
 390       --  Deletes the node containing Key as per Exclude, with the difference
 391       --  that Constraint_Error is raised if Key is not found.
 392 
 393       function Find (Container : Set; Key : Key_Type) return Cursor;
 394       --  Searches for the node containing Key, and returns a cursor
 395       --  designating the node. The search works by first calling Hash (on Key)
 396       --  to determine the bucket. If the bucket is not empty, the search
 397       --  compares Key to the element of each node in the bucket, and returns
 398       --  the matching node. The comparison itself works by applying the
 399       --  generic formal Key operation to the element of the node, and then
 400       --  calling generic formal operation Equivalent_Keys.
 401 
 402       function Contains (Container : Set; Key : Key_Type) return Boolean;
 403       --  Equivalent to Find (Container, Key) /= No_Element
 404 
 405       procedure Update_Element_Preserving_Key
 406         (Container : in out Set;
 407          Position  : Cursor;
 408          Process   : not null access
 409                        procedure (Element : in out Element_Type));
 410       --  Calls Process with the element of the node designated by Position,
 411       --  but with the restriction that the key-value of the element is not
 412       --  modified. The operation first makes a copy of the value returned by
 413       --  applying generic formal operation Key on the element of the node, and
 414       --  then calls Process with the element. The operation verifies that the
 415       --  key-part has not been modified by calling generic formal operation
 416       --  Equivalent_Keys to compare the saved key-value to the value returned
 417       --  by applying generic formal operation Key to the post-Process value of
 418       --  element. If the key values compare equal then the operation
 419       --  completes. Otherwise, the node is removed from the set and
 420       --  Program_Error is raised.
 421 
 422       type Reference_Type (Element : not null access Element_Type) is private
 423         with Implicit_Dereference => Element;
 424 
 425       function Reference_Preserving_Key
 426         (Container : aliased in out Set;
 427          Position  : Cursor) return Reference_Type;
 428 
 429       function Constant_Reference
 430         (Container : aliased Set;
 431          Key       : Key_Type) return Constant_Reference_Type;
 432 
 433       function Reference_Preserving_Key
 434         (Container : aliased in out Set;
 435          Key       : Key_Type) return Reference_Type;
 436 
 437    private
 438       use Ada.Streams;
 439       type Set_Access is access all Set;
 440       for Set_Access'Storage_Size use 0;
 441 
 442       --  Key_Preserving references must carry information to allow removal
 443       --  of elements whose value may have been altered improperly, i.e. have
 444       --  been given values incompatible with the hash-code of the previous
 445       --  value, and are thus in the wrong bucket. (RM 18.7 (96.6/3))
 446 
 447       --  We cannot store the key directly because it is an unconstrained type.
 448       --  To avoid using additional dynamic allocation we store the old cursor
 449       --  which simplifies possible removal. This is not possible for some
 450       --  other set types.
 451 
 452       --  The mechanism is different for Update_Element_Preserving_Key, as
 453       --  in that case the check that buckets have not changed is performed
 454       --  at the time of the update, not when the reference is finalized.
 455 
 456       package Impl is new Helpers.Generic_Implementation;
 457 
 458       type Reference_Control_Type is
 459          new Impl.Reference_Control_Type with
 460       record
 461          Container : Set_Access;
 462          Index     : Hash_Type;
 463          Old_Pos   : Cursor;
 464          Old_Hash  : Hash_Type;
 465       end record;
 466 
 467       overriding procedure Finalize (Control : in out Reference_Control_Type);
 468       pragma Inline (Finalize);
 469 
 470       type Reference_Type (Element : not null access Element_Type) is record
 471          Control  : Reference_Control_Type;
 472       end record;
 473 
 474       procedure Read
 475         (Stream : not null access Root_Stream_Type'Class;
 476          Item   : out Reference_Type);
 477 
 478       for Reference_Type'Read use Read;
 479 
 480       procedure Write
 481         (Stream : not null access Root_Stream_Type'Class;
 482          Item   : Reference_Type);
 483 
 484       for Reference_Type'Write use Write;
 485    end Generic_Keys;
 486 
 487 private
 488    pragma Inline (Next);
 489 
 490    type Node_Type;
 491    type Node_Access is access Node_Type;
 492 
 493    type Node_Type is limited record
 494       Element : aliased Element_Type;
 495       Next    : Node_Access;
 496    end record;
 497 
 498    package HT_Types is
 499      new Hash_Tables.Generic_Hash_Table_Types (Node_Type, Node_Access);
 500 
 501    type Set is new Ada.Finalization.Controlled with record
 502       HT : HT_Types.Hash_Table_Type;
 503    end record;
 504 
 505    overriding procedure Adjust (Container : in out Set);
 506 
 507    overriding procedure Finalize (Container : in out Set);
 508 
 509    use HT_Types, HT_Types.Implementation;
 510    use Ada.Finalization;
 511    use Ada.Streams;
 512 
 513    procedure Write
 514      (Stream    : not null access Root_Stream_Type'Class;
 515       Container : Set);
 516 
 517    for Set'Write use Write;
 518 
 519    procedure Read
 520      (Stream    : not null access Root_Stream_Type'Class;
 521       Container : out Set);
 522 
 523    for Set'Read use Read;
 524 
 525    type Set_Access is access all Set;
 526    for Set_Access'Storage_Size use 0;
 527 
 528    type Cursor is record
 529       Container : Set_Access;
 530       Node      : Node_Access;
 531    end record;
 532 
 533    procedure Write
 534      (Stream : not null access Root_Stream_Type'Class;
 535       Item   : Cursor);
 536 
 537    for Cursor'Write use Write;
 538 
 539    procedure Read
 540      (Stream : not null access Root_Stream_Type'Class;
 541       Item   : out Cursor);
 542 
 543    for Cursor'Read use Read;
 544 
 545    subtype Reference_Control_Type is Implementation.Reference_Control_Type;
 546    --  It is necessary to rename this here, so that the compiler can find it
 547 
 548    type Constant_Reference_Type
 549      (Element : not null access constant Element_Type) is
 550       record
 551          Control : Reference_Control_Type :=
 552            raise Program_Error with "uninitialized reference";
 553          --  The RM says, "The default initialization of an object of
 554          --  type Constant_Reference_Type or Reference_Type propagates
 555          --  Program_Error."
 556       end record;
 557 
 558    procedure Read
 559      (Stream : not null access Root_Stream_Type'Class;
 560       Item   : out Constant_Reference_Type);
 561 
 562    for Constant_Reference_Type'Read use Read;
 563 
 564    procedure Write
 565      (Stream : not null access Root_Stream_Type'Class;
 566       Item   : Constant_Reference_Type);
 567 
 568    for Constant_Reference_Type'Write use Write;
 569 
 570    --  Three operations are used to optimize in the expansion of "for ... of"
 571    --  loops: the Next(Cursor) procedure in the visible part, and the following
 572    --  Pseudo_Reference and Get_Element_Access functions. See Sem_Ch5 for
 573    --  details.
 574 
 575    function Pseudo_Reference
 576      (Container : aliased Set'Class) return Reference_Control_Type;
 577    pragma Inline (Pseudo_Reference);
 578    --  Creates an object of type Reference_Control_Type pointing to the
 579    --  container, and increments the Lock. Finalization of this object will
 580    --  decrement the Lock.
 581 
 582    type Element_Access is access all Element_Type with
 583      Storage_Size => 0;
 584 
 585    function Get_Element_Access
 586      (Position : Cursor) return not null Element_Access;
 587    --  Returns a pointer to the element designated by Position.
 588 
 589    Empty_Set : constant Set := (Controlled with others => <>);
 590 
 591    No_Element : constant Cursor := (Container => null, Node => null);
 592 
 593    type Iterator is new Limited_Controlled and
 594      Set_Iterator_Interfaces.Forward_Iterator with
 595    record
 596       Container : Set_Access;
 597    end record
 598      with Disable_Controlled => not T_Check;
 599 
 600    overriding function First (Object : Iterator) return Cursor;
 601 
 602    overriding function Next
 603      (Object   : Iterator;
 604       Position : Cursor) return Cursor;
 605    overriding procedure Finalize (Object : in out Iterator);
 606 
 607 end Ada.Containers.Hashed_Sets;