我试图将一个Unbounded_String数组传递给一个函数,我不关心索引的范围,因为函数将遍历每个元素.
(element1,element2)语法自动从范围中的第一个索引值开始,然后为给定的第二个值递增,这适用于多个值.但是,对于单个值,不能使用此值,因为括号被认为是多余的.
此代码显示了我所做的每个尝试的错误消息.(1)工作,但(2),传递单元素数组的优选语法不.(3)作品,作为这个类似问题的答案.然而,这将该范围的第一个索引硬编码到呼叫方; 如果String_Array实现发生更改,则必须更改所有调用站点,即使它们不关心所使用的索引值.
with Ada.Strings.Unbounded; use Ada.Strings.Unbounded;
procedure Main is
function "+"(S: String) return Ada.Strings.Unbounded.Unbounded_String
renames Ada.Strings.Unbounded.To_Unbounded_String;
type String_Array is array (Positive range <>) of Unbounded_String;
procedure Foo(input : in String_Array) is
begin
null;
end Foo;
begin
Foo((+"one", +"two")); --(1)
--Foo((+"only")); --(2) positional aggregate cannot have one component
Foo((1 => +"only")); --(3)
--Foo((String_Array'First => +"only")); --(4) prefix for "First" attribute must be constrained array
--Foo((String_Array'Range => +"only")); --(5) prefix for "Range" attribute must be constrained array
--Foo((String_Array'Range'First => +"only")); --(6) range attribute cannot be used in expression
--Foo((String_Array'Range'Type_Class'First => +"only")); --(7) range attribute cannot be used in expression
end Main;
Run Code Online (Sandbox Code Playgroud)
简短的回答是必须约束所有数组对象,这意味着调用者通常必须决定数组边界.
但是,您知道索引类型,并且可以这样做
Foo((Positive'First => +"only"));
Run Code Online (Sandbox Code Playgroud)
这并没有真正回答你的问题,因为有人可能仍然在摆弄数组范围,而且实际上并没有任何防范.
但是,添加新子类型作为范围可能是一个可行的解决方案:
subtype String_Array_Range is Positive;
type String_Array is array (String_Array_Range range <>) of Unbounded_String;
...
Foo((String_Array_Range'First => +"only"));
Run Code Online (Sandbox Code Playgroud)
现在可以在String_Array_Range子类型上完成任何摆弄,而不会影响任何调用者.但仍然无法保证恶意程序员改变数组本身的索引类型......
小智 5
你想要的(2)确实是不可能的,因为它可能被误认为是括号表达式(参见http://www.adaic.org/resources/add_content/standards/12aarm/html/AA-4-3-3.html note 10)。
如果出于您所述的原因,您真的想避免表达式 (3),作为解决方法,您可以定义一个函数来处理单元素数组的情况:
function Singleton_String_Array (S: String) return String_Array is ((1 => + S));
-- one element call
Foo(Singleton_String_Array ("only"));
Run Code Online (Sandbox Code Playgroud)
它重用您的表达式 (3),但不再在调用站点上完成第一个索引硬编码。
您还可以重载 foo 函数来处理特殊的单元素情况:
procedure Process_String (input : in Ada.Strings.Unbounded.Unbounded_String) is
begin
null;
end Process_String;
procedure Foo(input : in String_Array) is
begin
for string of input loop
Process_String (string);
end loop;
end Foo;
procedure Foo(input : in Ada.Strings.Unbounded.Unbounded_String) is
begin
Process_String (input);
end Foo;
-- One element call
Foo(+"only");
Run Code Online (Sandbox Code Playgroud)