我试图将Unbounded_String数组传递给函数,并且我不在乎索引的范围,因为函数将遍历每个元素。
(element1,element2)语法自动从该范围内的第一个索引值开始,然后递增给定的第二个值,这对于多个值都适用。但是,对于单个值,不能将其用作括号,因为括号被认为是多余的。
此代码显示我每次尝试的错误消息。 (1)有效,但是(2)传递单元素数组的首选语法无效。 (3)是有效的,并作为对this similar question的回答。但是,这会将范围的第一个索引硬编码到调用方。如果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;
答案 0 :(得分:5)
简短的回答是,必须限制所有数组对象,这意味着调用者通常必须决定数组的边界。
但是,您知道索引类型,并且可以做到
Foo((Positive'First => +"only"));
并不能真正回答您的问题,因为有人可能仍在摆弄数组范围,实际上并没有任何防范措施。
添加新的子类型作为范围可能是可行的解决方案,但是:
subtype String_Array_Range is Positive;
type String_Array is array (String_Array_Range range <>) of Unbounded_String;
...
Foo((String_Array_Range'First => +"only"));
现在可以在String_Array_Range子类型上进行任何摆弄,而不会影响任何调用者。但是仍然无法保证邪恶的程序员不会更改数组本身的索引类型...
答案 1 :(得分:4)
您想要的(2)实际上是不可能的,因为它可能被误认为是带括号的表达式(请参见http://www.adaic.org/resources/add_content/standards/12aarm/html/AA-4-3-3.html注10)。
如果您出于陈述的原因确实要避免使用表达式(3),则可以定义一个函数来处理单元素数组情况:
function Singleton_String_Array (S: String) return String_Array is ((1 => + S));
-- one element call
Foo(Singleton_String_Array ("only"));
它可以重用您的表达式(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");
答案 2 :(得分:0)
type String_Array is array (Positive range <>) of Unbounded_String;
声明数组的类型,但不提供大小。 请记住,数组的大小是静态的。
因此 String_Array'First 和 String_Array'Range 都不匹配。 如果您声明
type my_String_Array is String_Array(1 .. 35);
my_arr : my_String_Array
然后 my_arr'First 表示1,而 my_arr'Range 表示1..35。
只要不对类型施加约束,就无法访问这些属性。