Вернуть постоянную ссылку на переменную-член в Аде - PullRequest
0 голосов
/ 12 июня 2018

У меня есть класс в Аде, который содержит матрицу.Я хочу реализовать функцию, которая возвращает его как тип constant access, просто чтобы иметь возможность получить его как значение только для чтения, но избегая ненужной копии.

Я пробовал это, возвращая ссылку наЦелое число только для целей тестирования:

package Tests_Package is
    type B is private;

    function Test(Self : in B) return access constant Integer;

    private
        type B is tagged
        record
            I : aliased Integer;
        end record;
end Tests_Package;

-------------------------------------------

package body Tests_Package is

    function Test(Self : in B) return access constant Integer is
    begin
        return Self.I'access;
    end Test;

end Tests_Package;

Выше не скомпилируется, ошибка: non-local pointer cannot point to local object.

Мои вопросы:

Почему именно я получаю эту ошибку?

Есть ли способ достичь того, чего я хочу, без использования Unchecked_Access?

Нужно ли мне возвращать ссылку на переменную, или копия можетбыть оптимизирован компилятором Ada?

Ответы [ 3 ]

0 голосов
/ 12 июня 2018

Сделать параметр aliased:

function Test(Self : aliased in B) return access constant Integer;

(который заставляет параметр передаваться по ссылке, ARM 6.2 (3)

0 голосов
/ 13 июня 2018

Безопасные ссылки были введены в Ada 2012 путем сочетания «анонимных типов доступа, введенных в Ada 2005» и «аспекта Implicit_Dereference, введенных в Ada 2012» и кратко описаны здесь:

https://www.adacore.com/gems/gem-123-implicit-dereferencing-in-ada-2012

Дэн, в вашем конкретном случае

package Tests_Package is

   type Integer_Ref
     (Element : not null access constant Integer) is limited null record with
     Implicit_Dereference => Element;

   type B is tagged private;

   function Test (Self : aliased B) return Integer_Ref;

private

   type B is tagged
      record
         I : aliased Integer := 5;
      end record;

   function Test (Self : aliased B) return Integer_Ref is
      ((Element => Self.I'Access));

end Tests_Package;

И используется так:

with Tests_Package;
with Ada.Text_IO;

procedure Main is
   Variable : Tests_Package.B;

   Result   : Integer := 3 + Variable.Test;
begin
   Ada.Text_IO.Put_Line (Result'Img);
end Main;

Если вы попытаетесь установить личную переменную с помощью "Variable.Test: = 1;"вы получите ошибку времени компиляции, так как у вас есть только чтение только целое число.

0 голосов
/ 12 июня 2018

Вы получаете сообщение об ошибке, потому что компилятор не может гарантировать, что вы не можете сохранить ссылку на сущность после того, как она выходит из области видимости / исчезает.

Есть некоторые приемы с аспектом Implicit_Dereference, которая должна решить вашу проблему.

...