Generics 有没有办法在Ada中创建和重用方面集(特别是GNAT)?

Generics 有没有办法在Ada中创建和重用方面集(特别是GNAT)?,generics,ada,gnat,Generics,Ada,Gnat,在C/C++中,我经常使用预处理器来定义基于公共基过程的过程(是的,我知道,C中的函数) 例如(名称、类型和值是假设的): //在某个.h文件中 取消一些基本程序(int a,char c); #定义proc1(a)一些基本过程(a,‘d’) #定义proc2(a)一些基本程序(a,‘e’) #定义proc3(a)一些基本程序(a,‘f’) 我已经研究了Ada中的泛型,并将它们用于包,但对于子程序,我不确定如何干净地执行类似于上述C示例的操作 然而,我确实想到了这个: -- in some .

在C/C++中,我经常使用预处理器来定义基于公共基过程的过程(是的,我知道,C中的函数)

例如(名称、类型和值是假设的):

//在某个.h文件中
取消一些基本程序(int a,char c);
#定义proc1(a)一些基本过程(a,‘d’)
#定义proc2(a)一些基本程序(a,‘e’)
#定义proc3(a)一些基本程序(a,‘f’)
我已经研究了Ada中的泛型,并将它们用于包,但对于子程序,我不确定如何干净地执行类似于上述C示例的操作

然而,我确实想到了这个:

-- in some .ads file
procedure some_base(a:integer; c: character);

procedure proc1(a:integer; b: character := 'd') with
  Import    => True,
  Address   => some_base'Address;
procedure proc2(a:integer; b: character := 'e') with
  Import    => True,
  Address   => some_base'Address;
procedure proc3(a:integer; b: character := 'f') with
  Import    => True,
  Address   => some_base'Address;
这实际上工作得相当好,我只需要为相关的.adb文件中的某个_基实现一个body,而不必实现只调用具有正确参数值的某个_基的proc1、proc2、proc3子程序body。在我的一些用例中,虽然我有更多的方面,但只是导入和寻址,所以这可能无法很好地扩展

由于缺少更好的术语,我将这些称为参数化子程序别名

上述方法存在一些问题:

  • 仍然可以在调用proc1、proc2或proc3时重写b。这是次要的,因为这必须是有意的(为了什么目的?)
  • 它可能被认为是通常不是Ada的做事方式(可能被认为是C'ism),并且可能有更干净的方法来处理泛型,但是如果它涉及每个子程序单独的ads/adb,对于上面描述的这样一个简单用例来说,这太冗长了
  • 如果每个参数化子程序别名的特性变为几行,那么现在在维护过程中需要更新的内容更多,并且成为一个类似的维护问题,因为每个参数化子程序别名都需要显式的主体
  • 所以我的问题是关于上面最后一点

    有没有办法把
    Import=>True,Address=>some_base'Address编码到某种方面集,然后对每个参数化子程序别名重用它

    所以它应该是这样的(aspect_set,使用一些基本集,…为这个例子制作):


    即使没有,我认为我的上述方法是好的,除非有人能令人信服地指出为什么它是一个非常糟糕的方法,并且有一个更具表现力的<艾达>类似的方式< /强>这样做。

    在深入研究之后,我发现了一个更一般的解决方案。
    -- in some .ads file
    procedure some_base(a:integer; c: character);
    procedure proc1(a:integer; b: character := 'd') renames some_base;
    procedure proc2(a:integer; b: character := 'e') renames some_base;
    procedure proc3(a:integer; b: character := 'f') renames some_base;
    

    这比我使用的更干净,尽管仍然可以覆盖默认值,但这是次要的。它解决了维护问题,这是问题的核心所在。

    泛型有什么问题

    generic
       C : Character;
    procedure Some_Base(A : Integer);
    
    procedure Some_Base(A : Integer) is
    begin
       -- do something with A and B;
    end Some_Base;
    
    
    procedure Proc_1 is new Some_Base('d');
    procedure Proc_2 is new Some_Base('e');
    procedure Proc_3 is new Some_Base('f');
    

    我不太清楚为什么以这种方式叠加子程序会让我不寒而栗!我不确定这是不是便携式的。使用添加或更改的参数默认值重命名,您在下面发现的是,并且是Ada Way(TM)。在一个.adb文件中也许我能做到?但我不能将某个_库的主体放在.adb文件中,而在.ads文件中则是一个通用原型,除非得到警告:不能在看到主体之前实例化“某个_库”。我希望所有派生过程都在同一个.ads文件中定义。有些库可以是自己的。ads和.adbI可以让泛型像你说的那样工作,我只是不让它们在我的用例中工作,在我的用例中,最终派生函数正在设置其他默认值(例如使用GNAT.Source\u Info时,它与“重命名”一起工作)方法。好的,只需使用一些_Base就可以了…无需重命名、实例化或导入。使用泛型函数为包层次结构增加了一些复杂性,但这很好。以前我只使用package1.ads和package1.adb。现在我有package1.ads、package2.ads、Base _procedure.ads、Base _procedure.adb.Base _procedure使用s package1,package2使用base_过程。所以在这方面有点奇怪,但我让它工作了。
    generic
       C : Character;
    procedure Some_Base(A : Integer);
    
    procedure Some_Base(A : Integer) is
    begin
       -- do something with A and B;
    end Some_Base;
    
    
    procedure Proc_1 is new Some_Base('d');
    procedure Proc_2 is new Some_Base('e');
    procedure Proc_3 is new Some_Base('f');