问题描述
在C / C ++中,我经常使用预处理器来定义基于通用基本过程的过程(是的,我知道,C语言中的函数)。
例如(名称,类型和值是假设的):
// in some .h file
void some_base_procedure(int a,char c);
#define proc1(a) some_base_procedure(a,'d')
#define proc2(a) some_base_procedure(a,'e')
#define proc3(a) some_base_procedure(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文件中为some_base实现一个主体,就不必实现仅使用正确的参数值调用some_base的proc1,proc2,proc3子程序主体。在我的一些用例中,尽管我还有其他方面,但仅是Import和Address,所以可能无法很好地扩展。
由于缺少更好的术语,我将其称为带参数的子程序别名。
上述方法的一些问题:
- 在对proc1,proc2或proc3的调用中,仍然可以覆盖b。这是次要的,因为必须有意地这样做(出于什么目的?)
- 可以认为它通常不是Ada的做事方式 (可能被视为C'ism),并且可能有更干净的方法来使用泛型,但如果每个子程序涉及一个单独的ads / adb,那么对于如上所述的这种简单用例而言,这太冗长了。
- 如果每个参数化子程序别名的各个方面变为几行,则现在在维护期间需要更新的内容更多,并成为与维护问题类似的维护问题,因为每个参数化子程序别名都需要显式主体。
所以我的问题是关于以上最后一点。
是否有某种方法可以将Import => True,Address => some_base'Address;
放入某种方面集,然后将其重新用于每个参数化的子程序别名?
这样会是这样( aspect_set ,使用some_base_set ,...组成了此示例):
-- in some .ads file
procedure some_base(a:integer; c: character);
aspect_set some_base_set is Import => True,Address => some_base'Address;
procedure proc1(a:integer; b: character := 'd') using some_base_set;
procedure proc2(a:integer; b: character := 'e') using some_base_set;
procedure proc3(a:integer; b: character := 'f') using some_base_set;
即使没有,我也认为我的上述方法足够好,除非有人有说服力地指出为什么这是一种非常糟糕的方法,并且还有一种更具表现力的 Ada方式 做这样的事情。
解决方法
深入研究之后,我找到了一个更通用的解决方案。
-- 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');