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

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

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实例化组件,情况也是一样的,它的完整视图是一个受控类型,我不知道它是否相关。

  1. private with Ada.Containers.Hashed_Maps;
  2. private with Ada.Unchecked_Deallocation;
  3. package root is
  4. type Root_t is limited interface;
  5. type Derived_t is abstract limited new Ada.Finalization.Limited_Controlled and
  6. Root_t with private;
  7. overriding
  8. procedure Initialize (this : in out Derived_t) is abstract; --if null implementation is provided, no error is raised
  9. overriding
  10. procedure Finalize (this : in out Derived_t);
  11. private
  12. type array_t is array (Positive range <>) of Positive;
  13. type arrayPtr_t is access array_t;
  14. function fHash (key : Positive) return Ada.Containers.Hash_Type is
  15. (Ada.Containers.Hash_Type(key));
  16. package HashedDict_pck is new Ada.Containers.Hashed_Maps
  17. (Key_Type => Positive,
  18. Element_Type => Positive,
  19. Hash => fHash,
  20. Equivalent_Keys => "=");
  21. --The compilation error is raised before name Derived_t
  22. type Derived_t is abstract limited new Ada.Finalization.Limited_Controlled and
  23. Root_t with
  24. record
  25. arrayMember : arrayPtr_t;
  26. dict : HashedDict_pck.map;
  27. end record;
  28. procedure pFreeArray is new Ada.Unchecked_Deallocation
  29. (array_t, arrayPtr_t);
  30. end root;
  1. --------------
  2. -- Finalize --
  3. --------------
  4. overriding procedure Finalize (this : in out Derived_t) is
  5. begin
  6. this.dict.Clear;
  7. pFreeArray(this.arrayMember);
  8. end Finalize;
  9. 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:

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

  1. type Concrete_t is new Derived_t with private;
  2. overriding
  3. procedure Initialize(this : in out Concrete_t); --Implementation will initialize Derived_t arrayMember
  4. --other Concrete_t public primitives
  5. private
  6. type Concrete_t is new Derived_t with
  7. record
  8. --Some stuff
  9. end record;
  10. 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.

  1. with Ada.Finalization;
  2. private with Ada.Containers.Hashed_Maps;
  3. private with Ada.Unchecked_Deallocation;
  4. package root is
  5. type Root_t is limited interface;
  6. type Derived_t is abstract limited new Ada.Finalization.Limited_Controlled and
  7. Root_t with private;
  8. overriding
  9. procedure Initialize (this : in out Derived_t) is abstract; --if null implementation is provided, no error is raised
  10. overriding
  11. procedure Finalize (this : in out Derived_t);
  12. private
  13. type array_t is array (Positive range &lt;&gt;) of Positive;
  14. type arrayPtr_t is access array_t;
  15. function fHash (key : Positive) return Ada.Containers.Hash_Type is
  16. (Ada.Containers.Hash_Type(key));
  17. package HashedDict_pck is new Ada.Containers.Hashed_Maps
  18. (Key_Type =&gt; Positive,
  19. Element_Type =&gt; Positive,
  20. Hash =&gt; fHash,
  21. Equivalent_Keys =&gt; &quot;=&quot;);
  22. --The compilation error is raised before name Derived_t
  23. type Derived_t is abstract limited new Ada.Finalization.Limited_Controlled and
  24. Root_t with
  25. record
  26. arrayMember : arrayPtr_t;
  27. dict : HashedDict_pck.map;
  28. end record;
  29. procedure pFreeArray is new Ada.Unchecked_Deallocation
  30. (array_t, arrayPtr_t);
  31. end root;
  1. package body root is
  2. --------------
  3. -- Finalize --
  4. --------------
  5. overriding procedure Finalize (this : in out Derived_t) is
  6. begin
  7. this.dict.Clear;
  8. pFreeArray(this.arrayMember);
  9. end Finalize;
  10. 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:

  1. package root.concrete is
  2. type Concrete_t is new Derived_t with private;
  3. overriding
  4. procedure Initialize(this : in out Concrete_t); --Implementation will initialize Derived_t arrayMember
  5. --other Concrete_t public primitives
  6. private
  7. type Concrete_t is new Derived_t with
  8. record
  9. --Some stuff
  10. end record;
  11. 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

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

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

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

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

  1. Count : Positive:= 1;
  2. Procedure Nested_Initialize(This : out Concrete_t) is
  3. Function Initialize return Concrete_t is
  4. Begin
  5. Return Result : Concrete_t:=
  6. Concrete_t'( Derived_t'(others => <>) with others => <> ) do
  7. Result.Value:= Count;
  8. Count:= Positive'Succ( Count );
  9. End return;
  10. End Initialize;
  11. Begin
  12. This:= Initialize;
  13. 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:

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

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

  1. Count : Positive:= 1;
  2. Procedure Nested_Initialize(This : out Concrete_t) is
  3. Function Initialize return Concrete_t is
  4. Begin
  5. Return Result : Concrete_t:=
  6. Concrete_t&#39;( Derived_t&#39;(others =&gt; &lt;&gt;) with others =&gt; &lt;&gt; ) do
  7. Result.Value:= Count;
  8. Count:= Positive&#39;Succ( Count );
  9. End return;
  10. End Initialize;
  11. Begin
  12. This:= Initialize;
  13. 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:

确定