Ada2012继承判别式使用报错咨询及替代写法合规性疑问
原始代码与报错
原始代码:
procedure Main is type Component_t (Id : Natural) is tagged limited null record; type Root_t (Id : Natural) is tagged limited null record; type Child_t is limited new Root_t with record component : Component_t(Id => Id); end record; begin -- Insert code here. null; end Main;
报错信息:
9:38 -> error: Id is not visible
error: non-visible declaration at line 5
error: inherited discriminant not allowed here (RM 3.8 (12), 3.8.1 (6))
RM条款对应说明
你提到的RM条款内容正确:
RM 3.8(12/3)
表示非继承判别式的名称允许出现在类型声明内部,但不能出现在判别式部分。如果该判别式用于定义组件的约束、入口族的范围,或者派生类型定义中父子类型的约束,那么它的名称必须作为直接名称单独出现(不能作为更大表达式的一部分或扩展名称)。判别式不得用于定义标量组件的约束。
RM 3.8.1(6)
判别式直接名称必须解析为包含变体部分的完整类型声明中,已知判别式部分指定的判别式(称为变体部分的判别式)。变体中每个离散选择的预期类型是变体部分判别式的类型。
报错核心逻辑:声明Child_t时,直接继承Root_t但未显式声明自身判别式,此时父类型的Id属于继承判别式,Ada语法禁止在组件约束中直接引用继承判别式。必须显式声明自身判别式并传递给父类型,才能合法在组件定义中引用。
修改后代码的合规性
你修改后的写法完全合规:
type Child_t (Id : Natural) is limited new Root_t (Id => Id) with record component : Component_t(Id => Id); end record;
这里显式声明了Child_t的Id判别式,同时将其传递给父类型Root_t,此时组件定义中引用的Id是Child_t自身的非继承判别式,完全符合RM 3.8(12/3)的要求——自身判别式可用于定义组件约束,且以直接名称形式使用。
更简洁的解决方案
目前这个写法已是Ada语法要求下最简洁的合规方案。Ada类型系统明确要求:若要在派生类型的组件定义中使用判别式约束,必须显式声明派生类型自身的判别式(哪怕和父类型判别式完全一致),再传递给父类型,没有可绕过该要求的简化写法。
内容的提问来源于stack exchange,提问作者Albatros23

