Как вы инициализируете массив только с одним элементом, без жесткого кодирования первого индекса? - PullRequest
0 голосов
/ 18 сентября 2018

Я пытаюсь передать массив 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;

Ответы [ 3 ]

0 голосов
/ 18 сентября 2018
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.

Пока выне накладывайте ограничения на тип, у вас не будет доступа к этим атрибутам.

0 голосов
/ 20 сентября 2018

То, что вы хотите (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");    
0 голосов
/ 18 сентября 2018

Короткий ответ: все объекты массива должны быть ограничены, а это означает, что вызывающим абонентам обычно приходится выбирать границы массива.

Однако вы знаете тип индекса и можете выполнить

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, не затрагивая при этом никаких вызывающих.Но все еще нет гарантии, что злые программисты изменят тип индекса самого массива ...

...