Переменные удаляются в массивах Fortran? - PullRequest
0 голосов
/ 08 июня 2018

У меня есть следующий код с абстрактным типом, унаследованным типом и короткой программой, где я создаю объект и сохраняю его в массиве.

module m
    implicit none

    type :: container
        class(a), allocatable :: item
    end type container

    type, abstract :: a
        integer, public :: num
    end type a

    type, extends(a) :: b
        integer, public :: num2
   end type b
end module m

program mwe
    use m

    implicit none

    class(a), allocatable :: o1
    class(container), allocatable :: arr(:)

    o1 = b(1, 2)

    allocate(arr(2))
    arr(1) = container(o1)

    select type(t => o1)
        type is(b)
        write(*,*) t%num, t%num2
    end select

    select type(t => arr(1)%item)
        type is(b)
        write(*,*) t%num, t%num2
    end select
end program mwe

Проблема в том, чтоВыходные данные выглядят так:

       1           2
       1           0

Как видно, в той же переменной, хранящейся в массиве, вторая переменная обнуляется.Почему это происходит?Это потому, что массив имеет тип a, который содержит только первую переменную?

Я компилирую код с ifort version 18.0.3.

Ответы [ 2 ]

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

Я считаю, что

arr(1) = container(o1)

является недопустимым Fortran 2008. Это внутреннее утверждение присваивания, но в разделе 7.2.1.2 стандарта говорится, что

в внутреннем утверждении присваивания, (1) если переменная полиморфна, она должна быть размещаемой, а не копией.

Насколько я вижу, arr(1) является полиморфной, но не выделяемой, поэтому компилятор, соответствующий стандартам, долженвыдать ошибку и прервать компиляцию.

Если мои рассуждения верны, тот факт, что компилятор Intel Fortran компилирует этот код, является ошибкой компилятора и должен сообщаться в Intel.

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

Как и в случае ответа от ripero , можно сказать, что любой вывод из программы действителен.Тем не менее, мы можем сделать простую модификацию кода, чтобы сделать его правильным Fortran. 1 Этот ответ касается этой модифицированной версии.

Я бы назвал этот неожиданный вывод и обратился за помощью кпоставщик компилятора.

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

Я проверил ваш код с Intel Fortran 18.0.2 и вижу тот же вывод.

По вашему вопросу

Это потому, что массив имеет тип a, который содержит только первую переменную?

Нет: в части select type с выводом t не являетсяполиморфная сущность типа b.

Вы можете обойти эту проблему, избегая использования конструктора структуры:

arr(1)%item = o1

Я также вижу, что компиляторы Intel до 18.0.2 по-прежнему делают что-то другое.


1 С объявлением

    class(container), allocatable :: arr(:)

arr является полиморфным и выделяемым.Как отмечает Риперо, это означает, что arr(1), элемент arr является полиморфным.Однако, как элемент массива, arr(1) сам по себе не является полиморфным и поэтому не может находиться слева от внутреннего оператора присваивания.Мы можем изменить код двумя способами: предоставить определенное назначение или сделать arr не полиморфным.В коде вопроса, по-видимому, нет причин для того, чтобы контейнер был полиморфным, поэтому я рассмотрю

type(container), allocatable :: arr(:)

Далее, как описано в комментариях к вопросу, если вы хотите работать с gfortran 8, илиранее, чтобы увидеть, что происходит, вы должны также изменить код в вопросе так, чтобы определение производного типа container следовало после определения производного типа a.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...