Справочное руководство по Ada 2012
A.18.18 Общий пакет Containers.Indefinite_Holders
Определяемый языком общий пакет Containers.Indefinite_Holders предоставляет частный тип Holder и набор операций для этого типа. Контейнер-держатель хранит один элемент неопределенного типа.
Контейнер-держатель позволяет объявить объект, который может использоваться как неинициализированная переменная или компонент неопределенного типа.
Контейнер-держатель может быть *пустым*. Пустой держатель не содержит элемент.
Статическая семантика
Общий библиотечный пакет Containers.Indefinite_Holders имеет следующее объявление:
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 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);
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);
New_Item : in Element_Type);
procedure Query_Element
(Container : in Holder;
Process : not null access procedure (Element : in Element_Type));
(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));
(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;
(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;
with Implicit_Dereference => Element;
function Constant_Reference (Container : aliased in Holder)
return Constant_Reference_Type;
return Constant_Reference_Type;
function Reference (Container : aliased in out Holder)
return Reference_Type;
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
... -- не определено языком
end Ada.Containers.Indefinite_Holders;
Ожидается, что фактическая функция общего формального параметра "=" для значений Element_Type определит рефлексивное и симметричное отношение и вернет то же значение результата каждый раз, когда она вызывается с конкретной парой значений. Если она ведет себя каким-либо иным образом, функция "=" для значений holder возвращает неопределенное значение. Точные аргументы и количество вызовов этой общей формальной функции функцией "=" для значений holder не определены.
Тип Holder используется для представления контейнеров-держателей. Тип Holder требует финализации (см. 7.6).
Empty_Holder представляет собой пустой объект-держатель. Если объект типа Holder не инициализирован иначе, он инициализируется тем же значением, что и Empty_Holder.
Некоторые операции этого общего пакета имеют параметры доступа к подпрограммам. Чтобы гарантировать корректность таких операций, они предотвращают определенные действия выделенной подпрограммой. В частности, некоторые операции проверяют «вмешательство в элемент» контейнера, так как они зависят от того, что элемент контейнера не заменяется.
Подпрограмма называется *вмешательством в элемент* объекта-держателя *H*, если:
- Она очищает элемент, содержащийся в *H*, то есть вызывает процедуру Clear с *H* в качестве параметра;
- Она заменяет элемент, содержащийся в *H*, то есть вызывает процедуру Replace_Element с *H* в качестве параметра;
- Она вызывает процедуру Move с *H* в качестве параметра;
- Она завершает *H*.
Когда вмешательство в элемент запрещено для определенного объекта-держателя *H*, Program_Error передается при вызове любой определяемой языком подпрограммы, которая определена как вмешательство в элемент *H*, оставляя *H* неизменным. Эти проверки выполняются до любого другого определенного поведения тела определяемой языком подпрограммы.
function "=" (Left, Right : Holder) return Boolean;
Если Left и Right обозначают один и тот же объект-держатель, то функция возвращает True. В противном случае сравниваются элементы, содержащиеся в Left и Right, используя общий формальный оператор равенства, возвращая результат этой операции. Любое исключение, возникшее во время вычисления равенства элементов, передаётся.
function To_Holder (New_Item : Element_Type) return Holder;
Возвращает непустой держатель, содержащий элемент, инициализированный New_Item. To_Holder выполняет неопределённую вставку (см. A.18).
function Is_Empty (Container : Holder) return Boolean;
Возвращает True, если Container пуст, и False, если он содержит элемент.
procedure Clear (Container : in out Holder);
Удаляет элемент из Container. Container пуст после успешной операции Clear.
function Element (Container : Holder) return Element_Type;
Если Container пуст, генерируется Constraint_Error. В противном случае возвращает элемент, хранящийся в Container.
procedure Replace_Element (Container : in out Holder;
New_Item : in Element_Type);
New_Item : in Element_Type);
Replace_Element присваивает значение New_Item в Container, заменяя любое предыдущее содержимое Container; Replace_Element выполняет неопределённую вставку (см. A.18). Container не пуст после успешного вызова Replace_Element.
procedure Query_Element
(Container : in Holder;
Process : not null access procedure (Element : in Element_Type));
(Container : in Holder;
Process : not null access procedure (Element : in Element_Type));
Если Container пуст, генерируется Constraint_Error. В противном случае Query_Element вызывает Process.all с содержащимся элементом в качестве аргумента. Вмешательство в элемент Container запрещено во время выполнения вызова Process.all. Любое исключение, сгенерированное Process.all, передаётся.
procedure Update_Element
(Container : in out Holder;
Process : not null access procedure (Element : in out Element_Type));
(Container : in out Holder;
Process : not null access procedure (Element : in out Element_Type));
Если Container пуст, генерируется Constraint_Error. В противном случае Update_Element вызывает Process.all с содержащимся элементом в качестве аргумента. Вмешательство в элемент Container запрещено во время выполнения вызова Process.all. Любое исключение, сгенерированное Process.all, передаётся.
type Constant_Reference_Type
(Element : not null access constant Element_Type) is private
with Implicit_Dereference => Element;
(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;
with Implicit_Dereference => Element;
Типы Constant_Reference_Type и Reference_Type требуют финализации.
По умолчанию инициализация объекта типа Constant_Reference_Type или Reference_Type вызывает Program_Error.
function Constant_Reference (Container : aliased in Holder)
return Constant_Reference_Type;
return Constant_Reference_Type;
Эта функция (в сочетании с аспектом Implicit_Dereference) предоставляет удобный способ получения чтения доступа к содержащемуся элементу контейнера-держателя.
Если Container пуст, генерируется Constraint_Error. В противном случае Constant_Reference возвращает объект, дискриминанта которого представляет собой доступ к значению, обозначающему содержащийся элемент. Вмешательство в элементы Container запрещено, пока существует объект, возвращённый Constant_Reference, и он не завершён.
function Reference (Container : aliased in out Holder)
return Reference_Type;
return Reference_Type;
Эта функция (в сочетании с аспектами Implicit_Dereference) предоставляет удобный способ получения чтения и записи доступа к содержащемуся элементу контейнера-держателя.
Если Container пуст, генерируется Constraint_Error. В противном случае Reference возвращает объект, дискриминанта которого представляет собой доступ к значению, обозначающему содержащийся элемент. Вмешательство в элементы Container запрещено, пока существует объект, возвращённый Reference, и он не завершён.
procedure Assign (Target : in out Holder; Source : in Holder);
Если Target обозначает тот же объект, что и Source, операция не имеет эффекта. Если Source пуст, вызывается Clear (Target). В противном случае вызывается Replace_Element (Target, Element (Source)).
function Copy (Source : Holder) return Holder;
Если Source пуст, возвращается пустой контейнер-держатель; в противном случае возвращается To_Holder (Element (Source)).
procedure Move (Target : in out Holder; Source : in out Holder);
Если Target обозначает тот же объект, что и Source, то операция не оказывает никакого влияния. В противном случае, элемент, содержащийся в Source (если таковой имеется), удаляется из Source и вставляется в Target, заменяя любое ранее существовавшее содержимое. После успешного вызова Move Source оказывается пустым.
Ограниченные (временные) ошибки
Возникает ограниченная ошибка для фактической функции, связанной с обобщённой формальной подпрограммой, при вызове в рамках операции этого пакета, если она изменяет элемент любого параметра Holder операции. Либо возникает Program_Error, либо операция работает в соответствии с определением на значении Holder, как до, так и после части или всех изменений Holder.
Возникает ограниченная ошибка при вызове любой подпрограммы, объявленной в видимой части Containers.Indefinite_Holders, когда связанный контейнер завершён. Если операция принимает Container в качестве параметра in out, то она вызывает Constraint_Error или Program_Error. В противном случае операция либо выполняется так, как это было бы для пустого контейнера, либо вызывает Constraint_Error или Program_Error.
Ошибка выполнения
Выполнение является ошибочным, если контейнер-хранилище, связанный с результатом вызова Reference или Constant_Reference, завершён до того, как объект результата, возвращённый вызовом Reference или Constant_Reference, завершён.
Требования к реализации
Никакой памяти, связанной с объектом хранилища, не должна быть потеряна при присваивании или выходе из области видимости.
Выполнение оператора assignment_statement для контейнера-хранилища должно иметь эффект копирования элемента (если таковой имеется) из исходного объекта-хранилища в целевой объект-хранилище.
Рекомендации по реализации
Move не должен копировать элемент и должен свести к минимуму копирование внутренних структур данных.
Если исключение распространяется из операции хранения, никакая память не должна быть потеряна, и элемент не должен быть удалён из контейнера хранилища, если это не указано в операции.