Руководство по Ada (Ada 2022)
A.18.18 Обобщенный пакет Containers.Indefinite_Holders
Определяемый языком обобщенный пакет Containers.Indefinite_Holders предоставляет частный тип Holder и набор операций для этого типа. Контейнер holder хранит один элемент неопределенного типа.
Контейнер holder позволяет объявить объект, который может использоваться как неинициализированная переменная или компонент неопределенного типа.
Контейнер holder может быть *пустым*. Пустой holder не содержит элемент.
Статическая семантика
Обобщенный пакет библиотек Containers.Indefinite_Holders имеет следующее объявление:
generic
type Element_Type (<>) is private;
with function "=" (Left, Right : Element_Type) return Boolean is <>;
package Ada.Containers.Indefinite_Holders
with Preelaborate, Remote_Types,
Nonblocking, Global => in out synchronized is
type Element_Type (<>) is private;
with function "=" (Left, Right : Element_Type) return Boolean is <>;
package Ada.Containers.Indefinite_Holders
with Preelaborate, Remote_Types,
Nonblocking, Global => in out synchronized is
type Holder is tagged private
with Stable_Properties => (Is_Empty,
Tampering_With_The_Element_Prohibited),
Default_Initial_Condition => Is_Empty (Holder),
Preelaborable_Initialization;
with Stable_Properties => (Is_Empty,
Tampering_With_The_Element_Prohibited),
Default_Initial_Condition => Is_Empty (Holder),
Preelaborable_Initialization;
Empty_Holder : constant Holder;
function Equal_Element (Left, Right : Element_Type) return Boolean
renames "=";
renames "=";
function "=" (Left, Right : Holder) return Boolean;
function Tampering_With_The_Element_Prohibited
(Container : Holder) return Boolean
with Nonblocking, Global => null, Use_Formal => null;
(Container : Holder) return Boolean
with Nonblocking, Global => null, Use_Formal => null;
function Empty return Holder
is (Empty_Holder)
with Post =>
not Tampering_With_The_Element_Prohibited (Empty'Result)
and then Is_Empty (Empty'Result);
is (Empty_Holder)
with Post =>
not Tampering_With_The_Element_Prohibited (Empty'Result)
and then Is_Empty (Empty'Result);
function To_Holder (New_Item : Element_Type) return Holder
with Post => not Is_Empty (To_Holder'Result);
with Post => not Is_Empty (To_Holder'Result);
function Is_Empty (Container : Holder) return Boolean
with Global => null, Use_Formal => null;
with Global => null, Use_Formal => null;
procedure Clear (Container : in out Holder)
with Pre => not Tampering_With_The_Element_Prohibited (Container)
or else raise Program_Error,
Post => Is_Empty (Container);
with Pre => not Tampering_With_The_Element_Prohibited (Container)
or else raise Program_Error,
Post => Is_Empty (Container);
function Element (Container : Holder) return Element_Type
with Pre => not Is_Empty (Container) or else raise Constraint_Error,
Global => null, Use_Formal => Element_Type;
with Pre => not Is_Empty (Container) or else raise Constraint_Error,
Global => null, Use_Formal => Element_Type;
procedure Replace_Element (Container : in out Holder;
New_Item : in Element_Type)
with Pre => not Tampering_With_The_Element_Prohibited (Container)
or else raise Program_Error,
Post => not Is_Empty (Container);
New_Item : in Element_Type)
with Pre => not Tampering_With_The_Element_Prohibited (Container)
or else raise Program_Error,
Post => not Is_Empty (Container);
procedure Query_Element
(Container : in Holder;
Process : not null access procedure (Element : in Element_Type))
with Pre => not Is_Empty (Container) or else raise Constraint_Error;
(Container : in Holder;
Process : not null access procedure (Element : in Element_Type))
with Pre => not Is_Empty (Container) or else raise Constraint_Error;
procedure Update_Element
(Container : in out Holder;
Process : not null access procedure (Element : in out Element_Type))
with Pre => not Is_Empty (Container) or else raise Constraint_Error;
(Container : in out Holder;
Process : not null access procedure (Element : in out Element_Type))
with Pre => not Is_Empty (Container) or else raise Constraint_Error;
type Constant_Reference_Type
(Element : not null access constant Element_Type) is private
with Implicit_Dereference => Element,
Nonblocking, Global => in out synchronized,
Default_Initial_Condition => (raise Program_Error);
(Element : not null access constant Element_Type) is private
with Implicit_Dereference => Element,
Nonblocking, Global => in out synchronized,
Default_Initial_Condition => (raise Program_Error);
type Reference_Type
(Element : not null access Element_Type) is private
with Implicit_Dereference => Element,
Nonblocking, Global => in out synchronized,
Default_Initial_Condition => (raise Program_Error);
(Element : not null access Element_Type) is private
with Implicit_Dereference => Element,
Nonblocking, Global => in out synchronized,
Default_Initial_Condition => (raise Program_Error);
function Constant_Reference (Container : aliased in Holder)
return Constant_Reference_Type
with Pre => not Is_Empty (Container)
or else raise Constraint_Error,
Post => Tampering_With_The_Element_Prohibited (Container),
Nonblocking, Global => null, Use_Formal => null;
return Constant_Reference_Type
with Pre => not Is_Empty (Container)
or else raise Constraint_Error,
Post => Tampering_With_The_Element_Prohibited (Container),
Nonblocking, Global => null, Use_Formal => null;
function Reference (Container : aliased in out Holder)
return Reference_Type
with Pre => not Is_Empty (Container)
or else raise Constraint_Error,
Post => Tampering_With_The_Element_Prohibited (Container),
Nonblocking, Global => null, Use_Formal => null;
return Reference_Type
with Pre => not Is_Empty (Container)
or else raise Constraint_Error,
Post => Tampering_With_The_Element_Prohibited (Container),
Nonblocking, Global => null, Use_Formal => null;
procedure Assign (Target : in out Holder; Source : in Holder)
with Post => (Is_Empty (Source) = Is_Empty (Target));
with Post => (Is_Empty (Source) = Is_Empty (Target));
function Copy (Source : Holder) return Holder
with Post => (Is_Empty (Source) = Is_Empty (Copy'Result));
with Post => (Is_Empty (Source) = Is_Empty (Copy'Result));
procedure Move (Target : in out Holder; Source : in out Holder)
with Pre => (not Tampering_With_The_Element_Prohibited (Target)
or else raise Program_Error) and then
(not Tampering_With_The_Element_Prohibited (Source)
or else raise Program_Error),
Post => (if not Target'Has_Same_Storage (Source) then
Is_Empty (Source) and then (not Is_Empty (Target)));
with Pre => (not Tampering_With_The_Element_Prohibited (Target)
or else raise Program_Error) and then
(not Tampering_With_The_Element_Prohibited (Source)
or else raise Program_Error),
Post => (if not Target'Has_Same_Storage (Source) then
Is_Empty (Source) and then (not Is_Empty (Target)));
procedure Swap (Left, Right : in out Holder)
with Pre => (not Tampering_With_The_Element_Prohibited (Left)
or else raise Program_Error) and then
(not Tampering_With_The_Element_Prohibited (Right)
or else raise Program_Error),
Post => Is_Empty (Left) = Is_Empty (Right)'Old and then
Is_Empty (Right) = Is_Empty (Left)'Old;
with Pre => (not Tampering_With_The_Element_Prohibited (Left)
or else raise Program_Error) and then
(not Tampering_With_The_Element_Prohibited (Right)
or else raise Program_Error),
Post => Is_Empty (Left) = Is_Empty (Right)'Old and then
Is_Empty (Right) = Is_Empty (Left)'Old;
private
... -- не определено языком
end Ada.Containers.Indefinite_Holders;
Ожидается, что фактическая функция для обобщенного формального оператора «=» для значений Element_Type определит рефлексивное и симметричное отношение и вернет то же значение результата каждый раз, когда вызывается с конкретной парой значений. Если она ведет себя иначе, функция «=» для значений holder возвращает неопределенное значение. Точные аргументы и количество вызовов этой обобщенной формальной функции функцией «=» для значений holder не указаны.
Тип Holder используется для представления контейнеров holder. Тип Holder требует финализации (см. 7.6).
Empty_Holder представляет собой пустой объект holder. Если объект типа Holder не инициализирован иначе, он инициализируется тем же значением, что и Empty_Holder.
Некоторые операции проверяют «вмешательство в элемент» контейнера, поскольку они зависят от того, что элемент контейнера не заменяется. Если вмешательство в элемент запрещено для конкретного объекта holder H, Program_Error распространяется при финализации H, а также при вызове, передающем H в некоторые операции этого пакета, как указано в предусловии такой операции.
Абзацы 30–35 удалены, так как теперь эти правила описываются в предусловиях.
function "=" (Left, Right : Holder) return Boolean;
Если Left и Right обозначают один и тот же объект holder, функция возвращает True. В противном случае она сравнивает элемент, содержащийся в Left, с элементом, содержащимся в Right, с помощью обобщенного формального оператора равенства, возвращая результат этой операции. Любое исключение, возникшее во время вычисления равенства элементов, передается.
function Tampering_With_The_Element_Prohibited
(Container : Holder) return Boolean
with Nonblocking, Global => null, Use_Formal => null;
(Container : Holder) return Boolean
with Nonblocking, Global => null, Use_Formal => null;
Возвращает True, если вмешательство в элемент в данный момент запрещено для Container, и False в противном случае.
function To_Holder (New_Item : Element_Type) return Holder
with Post => not Is_Empty (To_Holder'Result);
with Post => not Is_Empty (To_Holder'Result);
Возвращает непустой holder, содержащий элемент, инициализированный New_Item. To_Holder выполняет неопределенную вставку (см. A.18).
function Is_Empty (Container : Holder) return Boolean
with Global => null, Use_Formal => null;
with Global => null, Use_Formal => null;
Возвращает True, если Container пустой, и False, если он содержит элемент.
procedure Clear (Container : in out Holder)
with Pre => not Tampering_With_The_Element_Prohibited (Container)
or else raise Program_Error,
Post => Is_Empty (Container);
with Pre => not Tampering_With_The_Element_Prohibited (Container)
or else raise Program_Error,
Post => Is_Empty (Container);
Удаляет элемент из Container.
function Element (Container : Holder) return Element_Type
with Pre => not Is_Empty (Container) or else raise Constraint_Error,
Global => null, Use_Formal => Element_Type;
with Pre => not Is_Empty (Container) or else raise Constraint_Error,
Global => null, Use_Formal => Element_Type;
Возвращает элемент, хранящийся в Container.
procedure Replace_Element (Container : in out Holder;
New_Item : in Element_Type)
with Pre => not Tampering_With_The_Element_Prohibited (Container)
or else raise Program_Error,
Post => not Is_Empty (Container);
New_Item : in Element_Type)
with Pre => not Tampering_With_The_Element_Prohibited (Container)
or else raise Program_Error,
Post => not Is_Empty (Container);
Replace_Element присваивает значение New_Item в Container, заменяя любое предыдущее содержимое Container; Replace_Element выполняет неопределенную вставку (см. A.18).
procedure Query_Element
(Container : in Holder;
Process : not null access procedure (Element : in Element_Type))
with Pre => not Is_Empty (Container) or else raise Constraint_Error,
Global => null, Use_Formal => null;
(Container : in Holder;
Process : not null access procedure (Element : in Element_Type))
with Pre => not Is_Empty (Container) or else raise Constraint_Error,
Global => null, Use_Formal => null;
Вызов Query_Element вызывает Process.all с содержащимся элементом в качестве аргумента. В процессе выполнения вызова Process.all запрещено изменять элемент Container. Любое исключение, поднятое Process.all, передаётся вверх.
процедура Update_Element
(Container : вход/выход Holder;
Process : не null доступная процедура (Element : вход/выход Element_Type))
с Pre => не Is_Empty (Container) иначе поднять Constraint_Error;
(Container : вход/выход Holder;
Process : не null доступная процедура (Element : вход/выход Element_Type))
с Pre => не Is_Empty (Container) иначе поднять Constraint_Error;
Update_Element вызывает Process.all с содержащимся элементом в качестве аргумента. В процессе выполнения вызова Process.all запрещено изменять элемент Container. Любое исключение, поднятое Process.all, передаётся вверх.
тип Constant_Reference_Type
(Element : не null доступная константа Element_Type) частный
с Implicit_Dereference => Element,
Nonblocking, Global => вход/выход синхронизированный,
Default_Initial_Condition => (поднять Program_Error);
(Element : не null доступная константа Element_Type) частный
с Implicit_Dereference => Element,
Nonblocking, Global => вход/выход синхронизированный,
Default_Initial_Condition => (поднять Program_Error);
тип Reference_Type (Element : не null доступная Element_Type) частный
с Implicit_Dereference => Element,
Nonblocking, Global => вход/выход синхронизированный,
Default_Initial_Condition => (поднять Program_Error);
с Implicit_Dereference => Element,
Nonblocking, Global => вход/выход синхронизированный,
Default_Initial_Condition => (поднять Program_Error);
Типы Constant_Reference_Type и Reference_Type требуют завершения.
Этот абзац был удалён.
функция Constant_Reference (Container : aliased in Holder)
возвращает Constant_Reference_Type
с Pre => не Is_Empty (Container) иначе поднять Constraint_Error,
Post => Tampering_With_The_Element_Prohibited (Container),
Nonblocking, Global => null, Use_Formal => null;
возвращает Constant_Reference_Type
с Pre => не Is_Empty (Container) иначе поднять Constraint_Error,
Post => Tampering_With_The_Element_Prohibited (Container),
Nonblocking, Global => null, Use_Formal => null;
Эта функция (в сочетании с аспектом Implicit_Dereference) предоставляет удобный способ получения чтения доступа к содержащемуся элементу контейнера-держателя.
Constant_Reference возвращает объект, дискриминант которого является значением доступа, обозначающим содержащийся элемент. Изменение элемента Container запрещено, пока существует возвращаемый Constant_Reference объект и он не завершён.
функция Reference (Container : aliased in out Holder)
возвращает Reference_Type
с Pre => не Is_Empty (Container) иначе поднять Constraint_Error,
Post => Tampering_With_The_Element_Prohibited (Container),
Nonblocking, Global => null, Use_Formal => null;
возвращает Reference_Type
с Pre => не Is_Empty (Container) иначе поднять Constraint_Error,
Post => Tampering_With_The_Element_Prohibited (Container),
Nonblocking, Global => null, Use_Formal => null;
Эта функция (в сочетании с аспектами Implicit_Dereference) предоставляет удобный способ получения чтения и записи доступа к содержащемуся элементу контейнера-держателя.
Reference возвращает объект, дискриминант которого является значением доступа, обозначающим содержащийся элемент. Изменение элемента Container запрещено, пока существует возвращаемый Reference объект и он не завершён.
процедура Assign (Target : вход/выход Holder; Source : вход Holder)
с Post => (Is_Empty (Source) = Is_Empty (Target));
с Post => (Is_Empty (Source) = Is_Empty (Target));
Если Target обозначает тот же объект, что и Source, операция не имеет эффекта. Если Source пустой, вызывается Clear (Target). В противном случае вызывается Replace_Element (Target, Element (Source)).
функция Copy (Source : Holder) возвращает Holder
с Post => (Is_Empty (Source) = Is_Empty (Copy'Result));
с Post => (Is_Empty (Source) = Is_Empty (Copy'Result));
Если Source пустой, возвращает пустой контейнер-держатель; в противном случае возвращает To_Holder (Element (Source)).
процедура Move (Target : вход/выход Holder; Source : вход/выход Holder)
с Pre => (не Tampering_With_The_Element_Prohibited (Target)
иначе поднять Program_Error) и затем
(не Tampering_With_The_Element_Prohibited (Source)
иначе поднять Program_Error),
Post => (если не Target'Has_Same_Storage (Source) то
Is_Empty (Source) и затем (не Is_Empty (Target)));
с Pre => (не Tampering_With_The_Element_Prohibited (Target)
иначе поднять Program_Error) и затем
(не Tampering_With_The_Element_Prohibited (Source)
иначе поднять Program_Error),
Post => (если не Target'Has_Same_Storage (Source) то
Is_Empty (Source) и затем (не Is_Empty (Target)));
Если Target обозначает тот же объект, что и Source, операция не имеет эффекта. В противном случае, элемент, содержащийся в Source (если таковой имеется), удаляется из Source и вставляется в Target, заменяя любое предыдущее содержимое.
процедура Swap (Left, Right : вход/выход Holder)
с Pre => (не Tampering_With_The_Element_Prohibited (Left)
иначе поднять Program_Error) и затем
(не Tampering_With_The_Element_Prohibited (Right)
иначе поднять Program_Error),
Post => Is_Empty (Left) = Is_Empty (Right)'Old и затем
Is_Empty (Right) = Is_Empty (Left)'Old;
с Pre => (не Tampering_With_The_Element_Prohibited (Left)
иначе поднять Program_Error) и затем
(не Tampering_With_The_Element_Prohibited (Right)
иначе поднять Program_Error),
Post => Is_Empty (Left) = Is_Empty (Right)'Old и затем
Is_Empty (Right) = Is_Empty (Left)'Old;
Если Left обозначает тот же объект, что и Right, операция не имеет эффекта. В противном случае, операция меняет местами элементы (если таковые имеются) в Left и Right.
Ограниченные (временно́й ошибки)
Это ограниченная ошибка для фактической функции, связанной с формальным подпрограммой-генериком, при вызове в качестве части операции этого пакета, если она изменяет элемент любого параметра Holder операции. Либо поднимается Program_Error, либо операция работает как определено для значения Holder до или после некоторых или всех изменений в Holder.
Это ограниченная ошибка при вызове любой подпрограммы, объявленной в видимой части Containers.Indefinite_Holders, когда связанный контейнер завершён. Если операция принимает Container в качестве параметра вход/выход, то она поднимает Constraint_Error или Program_Error. В противном случае операция либо работает как для пустого контейнера, либо поднимает Constraint_Error или Program_Error.
Ошибка выполнения
Выполнение является ошибочным, если контейнер-держатель, связанный с результатом вызова Reference или Constant_Reference, завершается до того, как результат возвращаемого вызова Reference или Constant_Reference завершается.
Требования к реализации
Никакой памяти, связанной с объектом-держателем, не должно теряться при присваивании или выходе из области видимости.
Выполнение оператора присваивания для контейнера-держателя должно иметь эффект копирования элемента (если есть) из источника объекта-держателя в целевой объект-держатель.
Рекомендации по реализации
Move и Swap не должны копировать элементы и должны минимизировать копирование внутренних структур данных.
Если исключение распространяется из операции holder, никакая память не должна теряться, и элемент не должен удаляться из контейнера-держателя, если не указано в операции.