Ада - как инициализировать ограниченный теговый тип, который содержит члены File_Type? - PullRequest
3 голосов
/ 10 ноября 2019

В следующем коде Mix_Card_Reader наследует от Mix_IO_Device, последняя является абстрактной теговой записью.

Ранее она содержала один Positive и два Stream_Access члена. Я хотел бы изменить код так, чтобы вместо него использовалось File_Type членов.

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

Проблема в том, что я не могу инициализировать этот наследуемый тип, потому что File_Type является ограниченным типом. Как я могу написать свою функцию Create_Mix_Card_Reader, чтобы разрешить это?

.ads ...

   type Mix_IO_Device is abstract tagged limited
      record
         Block_Size : Positive;
         Input_File : File_Type;
         Output_File : File_Type;
      end record;

   type Mix_Card_Reader is new Mix_IO_Device with null record;

.adb ...

   function Create_Mix_Card_Reader return Mix_IO_Device_Access is
      Ret : Mix_IO_Device_Access := new Mix_Card_Reader'(16, null, null);
   begin
      return Ret;
   end Create_Mix_Card_Reader;

GNAT жалуется на то, что я не могу передать null, null в пару File_Type членов, потому что они, конечно, несовместимы, нули остаются с тех пор, как это было Stream_Access участники. Кажется, что я должен передать что-то здесь, но я не хочу преждевременно открывать файлы, просто чтобы успокоить компилятор.

Что делать?

Редактировать: У меня естьпара очевидных вариантов:

  • использовать взамен access File_Type (но я все еще должен поддерживать открытие / закрытие файлов в другом месте).
  • хранить все объекты File_Type в массивеотдельно и просто обращайтесь к ним, используя потоки, как и раньше, но это выглядит грязно.

Ответы [ 2 ]

7 голосов
/ 10 ноября 2019

Это должно сработать:

function Create_Mix_Card_Reader return Mix_IO_Device_Access is
   Ret : Mix_IO_Device_Access := new Mix_Card_Reader'(
     16, Input_Type => <>, Ouptut_Type => <>);
begin
   return Ret;
end Create_Mix_Card_Reader;

Обозначение блока является заполнителем для значения по умолчанию. Чтобы использовать его в совокупности, вам нужен как минимум Ada 2005 и не должны использоваться позиционные обозначения, подробности объяснены в Обосновании Ada 2005 . Вы можете сократить два назначения до others => <>, если хотите.

3 голосов
/ 11 ноября 2019

Вам на самом деле не нужно инициализировать File_Type переменные, поскольку они изначально инициализируются (но не открываются).

У меня сложилось впечатление, что вы не начали с использования типа доступа? Попробуйте это (не ответ на поставленный вопрос, но все еще может быть полезным):

with Ada.Text_IO; use Ada.Text_IO;
package Wossname is

   type Mix_IO_Device is abstract tagged limited
      record
         Block_Size : Positive;
         Input_File : File_Type;
         Output_File : File_Type;
      end record;

   type Mix_Card_Reader is new Mix_IO_Device with null record;

   function Create_Mix_Card_Reader return Mix_IO_Device'Class;

end Wossname;

Я не на 100% уверен в точной легальности здесь, но я думаю, что это "инициализация на месте":

package body Wossname is

   function Create_Mix_Card_Reader return Mix_IO_Device'Class is
   begin
      return Ret : Mix_Card_Reader do
         Ret.Block_Size := 16;
      end return;
   end Create_Mix_Card_Reader;

end Wossname;

и, как вы видите, он компилируется (и работает!) ОК.

procedure Wossname.Test is
   Reader : Mix_IO_Device'Class := Create_Mix_Card_Reader;
begin
   begin
      Create (Reader.Output_File, Name => "wossname.out", Mode => Out_File);
   exception
      when Use_Error =>
         Open (Reader.Output_File, Name => "wossname.out", Mode => Out_File);
   end;
   Put (Reader.Output_File, "hi!");
   Close (Reader.Output_File);
end Wossname.Test;
...