Невозможно записать агрегат для защищенного типа

У меня есть следующая функция

function Allocate(V : Value_Type; N : access Node) return access Node is
begin
    return new Node'(Value => V, Next => N);
end Allocate;

при компиляции GNAT жалуется на то, что ожидает доступа к Node, но находит составной тип. Это кажется сломанным.

Узел:

protected type Node is
    --Various routines
private
    Value : Value_Type;
    Next : access Node;
end Node;

Я вернулся к типам без задач, и у меня нет точного сообщения об ошибке. Это то, что я видел много раз, когда, например, просто использовал:

return (Value => V, Next => N);

или похожие. Я никогда не видел этого при использовании "new Type'()".


person Patrick Kelly    schedule 21.03.2015    source источник
comment
Покажите нам объявление Node и фактическое сообщение об ошибке!   -  person Simon Wright    schedule 22.03.2015


Ответы (2)


Правильно, нет агрегатов для защищенных типов. Как сказал Саймон в своем ответе, защищенные поля являются частными и видны только в теле защищенного типа (или, возможно, позже в частной части защищенного типа). Внешний мир вообще не может видеть поля. Поэтому вам нужно добавить защищенную процедуру для установки полей:

protected type Node is
    --Various routines
    procedure Set_Value(V : Value_Type);
    procedure Set_Next(N : access Node);
private
    Value : Value_Type;
    Next : access Node;
end Node;

и вызовите процедуры в вашем Allocate:

function Allocate (V : Boolean; N : access Node) return access Node is
   New_Node : access Node;
begin
   New_Node := new Node;
   New_Node.Set_Value (V);
   New_Node.Set_Next (N); 
   return New_Node;
end Allocate;

(Или используйте расширенный возврат, как в ответе Саймона - я думаю, это сработает.)

ПРИМЕЧАНИЕ. Я не проверял это.

Другая возможность, если Value и Next никогда не изменятся в течение жизни защищаемого объекта, заключается в использовании дискриминантов:

protected type Node (Value : Value_Type; Next : access Node) is ...

и теперь вы можете сказать

return new Node(Value => V, Next => N);

Обратите внимание, что в этом синтаксисе нет галочки! Однако я не проверял это, поэтому не уверен, что это сработает. Я думаю, что допустимо иметь ссылку на тот же тип в списке дискриминантов, но я не уверен.

person ajb    schedule 23.03.2015

Единственное место, где видны Value и Next (кроме приватной части спецификации Node, конечно), находится в их собственном теле Node.

Я не вижу способа написать Allocate внутри Node. я сдался в

function Allocate (V : Boolean) return access Node is
begin
   return N : access Node do
      N := new Node;
      N.Next := Node'Access;
      N.Value := V;
   end return;
end Allocate;

получив сообщения по пути, в том числе

protected function cannot modify protected object
protected type cannot be used as type mark within its own spec or body (так что нельзя сказать Node'Access)
invisible selector "Value" for type “Node"

поэтому я думаю, вам нужно использовать какую-то обертку.

person Simon Wright    schedule 22.03.2015