无法为受保护类型写入聚合

Can’t write aggregate for protected type

我有以下功能

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'()".

的时候没见过

ValueNext 唯一可见的地方(当然,Node 规范的私有部分除外)是它们自己的 Node的 body.

我看不到 NodeAllocate 的写法。我放弃了

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 (so you can't say Node'Access)
invisible selector "Value" for type “Node"

所以我认为您需要使用某种包装器。

正确,没有针对受保护类型的聚合。正如西蒙在他的回答中所说,受保护字段是私有的,并且仅在受保护类型的主体内可见(或者可能稍后在受保护类型的私有部分中可见)。外界根本看不到田野。所以你必须添加一个受保护的过程来设置字段:

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;

(或者像 Simon 的回答一样使用扩展 return——我认为它会起作用。)

注意:我没有测试过这个。

另一种可能性,如果 ValueNext 在受保护对象的整个生命周期中永远不会改变,则使用判别式:

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

现在你可以说

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

请注意,此语法中没有刻度线!不过,我还没有对此进行测试,所以我不确定它是否会起作用。我认为在判别表中引用相同类型是可以接受的,但我不确定。