英文:
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 <>) 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;
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'( Derived_t'(dict => Default, arrayMember => <>) with others => <> );
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'( Derived_t'(others => <>) with others => <> ) do
Result.Value:= Count;
Count:= Positive'Succ( Count );
End return;
End Initialize;
Begin
This:= Initialize;
End Nested_Initialize;
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论