Ada2012受控类型错误:调用抽象过程必须是分派的。

huangapple go评论64阅读模式
英文:

Ada2012 controlled types error: call to abstract procedure must be dispatching

问题

I'm facing a compilation error where I'm not sure about what is going on.

我遇到了一个编译错误,我不确定发生了什么。

I provide a minimal reproducibable example; if I implement the Initialize procedure, everything is ok and no errors are thrown. The same occurs if class Derived_t has no Hashed_Maps instantiation component, which it's full view is a controlled type and I don't know if it could be related.

我提供了一个最小可复现的示例;如果我实现Initialize过程,一切都正常,没有错误。如果Derived_t类没有Hashed_Maps实例化组件,情况也是一样的,它的完整视图是一个受控类型,我不知道它是否相关。

private with Ada.Containers.Hashed_Maps;
private with Ada.Unchecked_Deallocation;

package root is

  type Root_t is limited interface;

  type Derived_t is abstract limited new Ada.Finalization.Limited_Controlled and
    Root_t with private;

  overriding
  procedure Initialize (this : in out Derived_t) is abstract; --if null implementation is provided, no error is raised

  overriding
  procedure Finalize (this : in out Derived_t);

private

  type array_t is array (Positive range <>) of Positive;
  type arrayPtr_t is access array_t;

  function fHash (key : Positive) return Ada.Containers.Hash_Type is
    (Ada.Containers.Hash_Type(key));

  package HashedDict_pck is new Ada.Containers.Hashed_Maps
    (Key_Type => Positive,
     Element_Type => Positive,
     Hash => fHash,
     Equivalent_Keys => "=");

  --The compilation error is raised before name Derived_t
  type Derived_t is abstract limited new Ada.Finalization.Limited_Controlled and
    Root_t with
     record
       arrayMember : arrayPtr_t;
       dict : HashedDict_pck.map;
     end record;

  procedure pFreeArray is new Ada.Unchecked_Deallocation
    (array_t, arrayPtr_t);

end root;

  --------------
  -- Finalize --
  --------------

  overriding procedure Finalize (this : in out Derived_t) is
  begin
    this.dict.Clear;
    pFreeArray(this.arrayMember);
  end Finalize;

end root;

The compilation error occurs at line 33 column 8, just before entity name Derived_t in the private part: call to abstract procedure must be dispatching.

编译错误发生在第33行第8列,就在Derived_t实体名称之前,在私有部分:调用抽象过程必须是分派过程。

I know that controlled types are usually implemented privately, to hide the procedures to clients; I decided to make it public to enforce implementers of concrete classes to implement the Initialize procedure.

我知道通常会将受控类型私有化,以隐藏过程对客户端的可见性;我决定将其公开,以强制具体类的实现者实现Initialize过程。

An implementer would do the following to implement a concrete class:

一个实现者会执行以下步骤来实现具体类:


  type Concrete_t is new Derived_t with private;

  overriding
  procedure Initialize(this : in out Concrete_t); --Implementation will initialize Derived_t arrayMember

  --other Concrete_t public primitives

private

  type Concrete_t is new Derived_t with 
    record
      --Some stuff
    end record;

end root.concrete;

I think that, as I declare the map as a member record, and as the map is a controlled type, it needs to initialise its enclosing record but, as the Initialize is abstract, the compiler don't know what to call. Am I right?

我认为,因为我将map声明为成员记录,并且map是一个受控类型,它需要初始化其封闭记录,但是由于Initialize是抽象的,编译器不知道应该调用什么。我说得对吗?

I'll privatize the use of controlled types with a null default implementation of the Initialize to fix it, anyway an implementer shall implement the procedure for a concrete class to construct it correctly.

我将使用Initialize的空默认实现来私有化受控类型的使用,以修复它,不管怎样,实现者都应该为具体类实现该过程以正确构造它。

英文:

I'm facing a compilation error where I'm not sure about what is going on.

I provide a minimal reproducibable example; if I implement the Initialize procedure, everything is ok and no errors are thrown. The same occurs if class Derived_t has no Hashed_Maps instantiation component, which it's full view is a controlled type and I don't know if it could be related.

with Ada.Finalization;
private with Ada.Containers.Hashed_Maps;
private with Ada.Unchecked_Deallocation;

package root is
  
  type Root_t is limited interface;
  
  type Derived_t is abstract limited new Ada.Finalization.Limited_Controlled and
    Root_t with private;
  
  overriding
  procedure Initialize (this : in out Derived_t) is abstract; --if null implementation is provided, no error is raised
  
  overriding
  procedure Finalize (this : in out Derived_t);
  
private
  
  type array_t is array (Positive range &lt;&gt;) of Positive;
  type arrayPtr_t is access array_t;
  
  function fHash (key : Positive) return Ada.Containers.Hash_Type is
    (Ada.Containers.Hash_Type(key));
  
  package HashedDict_pck is new Ada.Containers.Hashed_Maps
    (Key_Type =&gt; Positive,
     Element_Type =&gt; Positive,
     Hash =&gt; fHash,
     Equivalent_Keys =&gt; &quot;=&quot;);
  
  --The compilation error is raised before name Derived_t
  type Derived_t is abstract limited new Ada.Finalization.Limited_Controlled and
    Root_t with
     record
       arrayMember : arrayPtr_t;
       dict : HashedDict_pck.map;
     end record;
  
  procedure pFreeArray is new Ada.Unchecked_Deallocation
    (array_t, arrayPtr_t);

end root;
package body root is

  --------------
  -- Finalize --
  --------------

  overriding procedure Finalize (this : in out Derived_t) is
  begin
    this.dict.Clear;
    pFreeArray(this.arrayMember);
  end Finalize;

end root;

The compilation error occurs at line 33 column 8, just before entity name Derived_t in the private part: call to abstract procedure must be dispatching.

I know that controlled types are usually implemented privately, to hide the procedures to clients; I decided to make it public to enforce implementers of concrete classes to implement the Initialize procedure.

An implementer would do the following to implement a concrete class:

package root.concrete is

  type Concrete_t is new Derived_t with private;

  overriding
  procedure Initialize(this : in out Concrete_t); --Implementation will initialize Derived_t arrayMember

  --other Concrete_t public primitives

private

  type Concrete_t is new Derived_t with 
    record
      --Some stuff
    end record;

end root.concrete;

I think that, as I declare the map as a member record, and as the map is a controlled type, it needs to initialise its enclosing record but, as the Initialize is abstract, the compiler don't know what to call. Am I right?

I'll privatize the use of controlled types with a null default implementation of the Initialize to fix it, anyway an implementer shall implement the procedure for a concrete class to construct it correctly.

答案1

得分: 1

我认为,由于我将地图声明为成员记录,并且地图是一种受控类型,它需要初始化其封闭记录,但是由于初始化是抽象的,编译器不知道要调用什么。我对了吗?

大部分说得对。如果我理解正确,你需要做的是一个扩展聚合 - 就像这样:

overriding
procedure Initialize(this : in out Concrete_t) is
   Function Default return HashedDict_pck.map is separate;
Begin
   This := Concrete_t'( Derived_t'(dict => Default, arrayMember => <>) with others => <> );
End Initialize;

另一种可能性是使用一个函数来构造你的初始值,然后使用它:

Count : Positive:= 1;

Procedure Nested_Initialize(This : out Concrete_t) is
    Function Initialize return Concrete_t is
    Begin
        Return Result : Concrete_t:=
          Concrete_t'( Derived_t'(others => <>) with others => <> ) do
            Result.Value:= Count;
            Count:= Positive'Succ( Count );
        End return;
    End Initialize;
Begin
   This:= Initialize;
End Nested_Initialize;
英文:

> I think that, as I declare the map as a member record, and as the map
> is a controlled type, it needs to initialise its enclosing record but,
> as the Initialize is abstract, the compiler don't know what to call.
> Am I right?

Mostly on the right track.
IIUC, what you'll need to do is an extension aggregate -- like this:

overriding
procedure Initialize(this : in out Concrete_t) is
   Function Default return HashedDict_pck.map is separate;
Begin
   This := Concrete_t&#39;( Derived_t&#39;(dict =&gt; Default, arrayMember =&gt; &lt;&gt;) with others =&gt; &lt;&gt; );
End Initialize;

Another possibility is to use a function to construct your initial value and use that.

Count : Positive:= 1;

Procedure Nested_Initialize(This : out Concrete_t) is
    Function Initialize return Concrete_t is
    Begin
        Return Result : Concrete_t:=
          Concrete_t&#39;( Derived_t&#39;(others =&gt; &lt;&gt;) with others =&gt; &lt;&gt; ) do
            Result.Value:= Count;
            Count:= Positive&#39;Succ( Count );
        End return;
    End Initialize;
Begin
   This:= Initialize;
End Nested_Initialize;

huangapple
  • 本文由 发表于 2023年6月15日 14:52:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76479843.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定