gpt4 book ai didi

generics - 如果一个不完整,有没有办法验证两个通用形式是相同的类型?

转载 作者:行者123 更新时间:2023-12-04 11:48:06 25 4
gpt4 key购买 nike

给定一个通用的父包:

generic
type T(<>) is tagged;
package Parent is
type Instance is tagged private;
private
type T_Access is access T;
type Instance is tagged record
Thing : T_Access := null;
end record;
end Parent;
在子包中是否有一种方法可以确保作为泛型形式传递给子包的类型与 Parent.T 的类型(甚至是其后代)相同?例如,考虑通用子包:
generic
type T(<>) is new Base with private;
package Parent.Child is
type T_Access is access T;
function Make(Ref : not null T_Access) return Parent.Instance;
end Parent.Child;

package body Parent.Child is

function To_Parent(Source : T_Access) return Parent.T_Access is
begin
-- here is where I need to be able to safely convert
-- an access to the complete type to an access to the
-- incomplete type. I can used Unchecked_Conversion,
-- but that goes south if someone passes in a type to
-- Parent.Child that is not the same as Parent. If
-- I could know that Parent.Child.T is a descendant of
-- Parent.T, I could just convert it (I think??).
end To_Parent;

function Make(Ref : not null T_Access) return Parent.Instance is
begin
return (Thing => To_Parent(Ref);
end Make;

end Parent.Child;
其中 Base 是一些基本标记类型。您可以使用以下内容作为占位符:
type Base is tagged limited null record;
我正在寻找一种编译时或运行时的方法来验证 Parent.Child 内部的 Parent.Child.T 与 Parent.T 相同(或者即使 Parent.Child.T 是 Parent.T 的后代。
注意:我正在尝试使用父子包关系,因为它允许 Child 看到 Parent 的私有(private)部分。
我天真地尝试了一些基于运行时的东西:
package body Parent.Child is

-- other stuff

begin
if Child.T not in Parent.T then
raise Storage_Error with "Invalid type passed to child package";
end if;
end Parent.Child;
但这只会导致 GNAT 错误:
premature usage of incomplete type "T"
因为 Parent.T 是不完整的。这里的目的是创建一个可用于不完整类型的自动内存管理框架,因此父包提供大部分功能,而子包可以稍后实例化并添加需要完整类型信息的功能(如构造/解除分配)。然后你可以做如下声明:
type Test is tagged;
package B is new Parent(Test);

type Test is new Base with record
Thing : Parent.Instance;
end record;

package M is new B.Child(Test);
全套测试代码(请记住,这是原始和裸露的,以使其尽可能简单):
------------------------ Base Package ----------------------------
package Base is
type Instance is tagged limited null record;
end Base;

----------------------- Parent Package ---------------------------
generic
type T(<>) is tagged;
package Parent is
type Instance is tagged private;
private
type T_Access is access T;
type Instance is tagged record
Thing : T_Access := null;
end record;
end Parent;

------------------------ Child Package ---------------------------
with Base;

generic
type T(<>) is new Base.Instance with private;
package Parent.Child is

type T_Access is access T;

function Make(Ref : not null T_Access) return Parent.Instance;

end Parent.Child;

with Ada.Unchecked_Conversion;
with Ada.Unchecked_Deallocation;

package body Parent.Child is

-- Used later in code not shown, but needed
-- and requires Child.T to be complete.
procedure Finalize is new Ada.Unchecked_Deallocation
(Object => T,
Name => T_Access);

function To_Parent is new Ada.Unchecked_Conversion
(Source => Child.T_Access,
Target => Parent.T_Access);

-- This is where things get IFFY. I do unchecked conversions here.
-- If Parent.T is not equal to Parent.Child.T, then this can go bad
-- really fast. If there was a way to verify the types were the same,
-- then I could safely do this. Or if there was a way for me to
-- verify that Parent.Child.T was a descendant of Parent.T, then
-- I could just convert them without unchecked_conversion.
function Make(Ref : not null T_Access) return Parent.Instance is
(Thing => To_Parent(Ref));

end Parent.Child;

---------------------------- Main -------------------------------
with Ada.Text_IO;
with Base;
with Parent;
with Parent.Child;

procedure Main is

type Test is tagged;

package P is new Parent(Test);

type Test is new Base.Instance with record
Thing : P.Instance;
end record;

package PC is new P.Child(Test);

Thing : P.Instance := PC.Make(new Test);

begin
Ada.Text_IO.Put_Line("Hello");
end Main;

最佳答案

如果您不需要泛型的父/子关系,则可以执行以下操作:
foo.ads

generic
type T(<>) is tagged;
package Foo is

end Foo;
广告栏
with Foo;

generic
type T(<>) is tagged private;
with package Foo_Instance is new Foo(T); --package parameter
package Bar is

end Bar;
这样,完整类型必须与不完整类型完全匹配,即。它不能是类型扩展,因此:
with Foo;
with Bar;

package Baz is

type Base is tagged;
package Base_Foo is new Foo(Base);


type Base is tagged null record;
package Base_Bar is new Bar(Base, Base_Foo);


type Extension is new Base with null record;
package Extension_Bar is new Bar(Extension, Base_Foo); -- fails!

end Baz;

关于generics - 如果一个不完整,有没有办法验证两个通用形式是相同的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69412438/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com